source: trunk/client/src/ndpsmb.c

Last change on this file was 983, checked in by Yuri Dario, 9 years ago

Get plugin helper table pointer at init time. ticket#274.

  • Property svn:eol-style set to native
File size: 70.0 KB
RevLine 
[151]1/*
2 Netdrive Samba client plugin
3 plugin API
[957]4 Copyright (C) netlabs.org 2003-2012
5 Copyright (C) bww bitwise works GmbH 2012-2016
[151]6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
[48]22#include <stdio.h>
23#include <stdlib.h>
24#include <stdarg.h>
[183]25#include <string.h>
[48]26#include <time.h>
[5]27
[145]28#define NDPL_LARGEFILES
29#define INCL_LONGLONG
30#include <ndextpl2.h>
[966]31#include "dircache.h"
[147]32#include "smbwrp.h"
33#include "util.h"
[48]34
[126]35// -------------------------------------------------------------
36
37/* time conversion functions: SMB protocol sends timestamps in GMT time,
[960]38 * os2 api uses localtime,
39 * emx/klibc uses timezone and daylight saving to convert GMT timestamps,
40 * so only the timezone must be counted in conversion.
41 */
42void fsphUnixTimeToDosDate(Resource *pRes, time_t time, FDATE* fdate, FTIME *ftime)
[126]43{
[959]44 struct tm* gmt = localtime( &time);
[494]45#if 0 // as localtime() already does dst we don't need to add something
[959]46 if (gmt->tm_isdst>0)
47 {
[960]48 debuglocal(pRes, 9, "daylight saving in effect %d, timezone %d\n",gmt->tm_isdst, timezone);
[959]49 time -= 3600;
50 gmt = localtime( &time);
51 }
[494]52#endif
[959]53 fdate->day = gmt->tm_mday;
54 fdate->month = gmt->tm_mon+1;
55 fdate->year = gmt->tm_year + 1900 - 1980;
56 ftime->twosecs = gmt->tm_sec/2;
57 ftime->minutes = gmt->tm_min;
58 ftime->hours = gmt->tm_hour;
[960]59 return;
[126]60}
61
[960]62void fsphDosDateToUnixTime(Resource *pRes, FDATE fdate, FTIME ftime, ULONG* time)
[126]63{
[959]64 struct tm gmtime = { 0 };
[126]65
[960]66 debuglocal(pRes, 9, "fsphDosDateToUnixTime time %02d:%02d:%02d\n", ftime.hours, ftime.minutes, ftime.twosecs*2);
[959]67 gmtime.tm_mday = fdate.day;
68 gmtime.tm_mon = fdate.month-1;
69 gmtime.tm_year = fdate.year + 1980 - 1900;
70 gmtime.tm_sec = ftime.twosecs*2;
71 gmtime.tm_min = ftime.minutes;
72 gmtime.tm_hour = ftime.hours;
73 gmtime.tm_isdst = -1; // force libc to check dst saving
[126]74
[959]75 *time = mktime( &gmtime);
[960]76 debuglocal(pRes, 9, "fsphDosDateToUnixTime time1 %d %s", *time, ctime( (time_t*)time));
[494]77#if 0 // as mktime() already does dst we don't need to add something
[959]78 struct tm* gmt;
79 gmt = localtime( (time_t*) time);
80 if (gmt->tm_isdst>0)
81 {
[960]82 debuglocal(pRes, 9, "fsphDosDateToUnixTime daylight saving in effect %d, timezone %d\n",gmt->tm_isdst, timezone);
[959]83 *time += 3600;
84 }
[960]85 debuglocal(pRes, 9, "fsphDosDateToUnixTime time2 %d %s", *time, ctime( (time_t*)time));
[494]86#endif
[960]87 return;
[126]88}
89
[131]90// -------------------------------------------------------------
91
[5]92/* uppercased type of resource */
93const char *NdpTypes[] =
94{
[959]95 "SMBFS",
96 NULL
[5]97}
98;
99
100/* Properties of supported resource types */
101
102/* Properties of resource */
103static const NDPROPERTYINFO smbProperties[] =
104{
[959]105 {ND_PROP_STRING, 0, "WORKGROUP", ""},
106 {ND_PROP_STRING, 0, "SERVER", ""},
107 {ND_PROP_STRING, 0, "SHARE", ""},
108 {ND_PROP_STRING, 0, "USER", "guest"},
109 {ND_PROP_STRING, 0, "PASSWORD", ""},
110 {ND_PROP_STRING, 0, "SPASSWORD", ""},
111 {ND_PROP_STRING, 0, "MASTER", "WORKGROUP"},
112 {ND_PROP_ULONG, 0, "MASTERTYPE", "1"},
113 {ND_PROP_ULONG, 0, "CTO", "10"},
114 {ND_PROP_ULONG, 0, "CLD", "32"},
115 {ND_PROP_ULONG, 0, "EASUPPORT", "1"},
[960]116 {ND_PROP_ULONG, 0, "LOGLEVEL", "0"},
[959]117 {ND_PROP_STRING, 0, NULL, NULL}
[5]118};
119
120
121/* Exported array of properties */
122const NDPROPERTYINFO *NdpPropertiesInfo[] =
123{
[959]124 smbProperties
[5]125};
126
127
[499]128PLUGINHELPERTABLE2L *ph;
[5]129static int ifL;
130
[584]131/* A mutex to serialize plugin calls because libsmb may not be thread safe. */
[567]132static NDMUTEX mutex;
[818]133
[567]134static int lockInit (void)
135{
[959]136 return ph->fsphCreateMutex (&mutex);
[567]137}
[818]138
[567]139static void lockClose (void)
140{
[959]141 ph->fsphCloseMutex (mutex);
[567]142}
[818]143
[567]144static int lockRequest (void)
145{
[959]146 return ph->fsphRequestMutex (mutex, SEM_INDEFINITE_WAIT);
[567]147}
148
149static void lockRelease (void)
150{
[959]151 ph->fsphReleaseMutex (mutex);
[567]152}
153
[589]154#if LIBSMB_THREAD_SAFE==0
[584]155
[959]156#define ENTER() do { \
157 int rcLock = lockRequest(); \
158 if (rcLock != NO_ERROR) \
159 return rcLock; \
[960]160 smbwrp_Logging(pRes); \
[567]161} while (0)
162
[959]163#define LEAVE() do { \
164 lockRelease(); \
[567]165} while (0)
166
[584]167#else
168#define ENTER() do { /* nothing */ } while (0)
169#define LEAVE() do { /* nothing */ } while (0)
170#endif
171
[960]172int helperEASet (Resource *pRes, cli_state *cli, FEALIST *pFEAList, char *path)
[892]173{
[959]174 int rc = 0;
[892]175
[959]176 if (!path || !pFEAList || pFEAList->cbList <= sizeof(long))
177 return ERROR_EAS_NOT_SUPPORTED;
[892]178
[959]179 ENTER();
[892]180
[959]181 do {
182 // got FEA there
183 FEA * pfea;
184 unsigned long done = sizeof(long);
185 pfea = pFEAList->list;
186 while (done < pFEAList->cbList)
187 {
[960]188 rc = smbwrp_setea(pRes, cli, path, (char*)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
[959]189 if (rc)
190 break;
191 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
192 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
193 }
194 } while (0);
195
196 LEAVE();
197 return rc;
[892]198}
199
[963]200/* from ndpl2.c sample:
201 * Helper to concatenate parent path, stored as resource data in
202 * NdpQueryPathInfo and a file object name returned by NdpQueryPathInfo.
203 */
204static void buildfullpath2 (char *szFullPath, NDDATABUF *rsrcData, NDFILEINFO *pfi)
205{
206 *szFullPath = '\0';
207 if (rsrcData->ulSize > 0)
208 {
209 memcpy (szFullPath, rsrcData->pData, rsrcData->ulSize);
210 }
211 strcat( szFullPath, pfi->pszName);
212}
213
214
[5]215int APIENTRY NdpPluginLoad (PLUGINHELPERTABLE2L *pPHT)
216{
[959]217 ph = pPHT;
218 ifL = 0;
219 if (ph->cb >= sizeof (PLUGINHELPERTABLE2L))
220 ifL = 1;
221
222 lockInit();
223 return NO_ERROR;
[5]224}
225
226
227int APIENTRY NdpPluginFree (void)
228{
[959]229 debugDelete();
230 lockClose();
231 return NO_ERROR;
[5]232}
233
[968]234//
235// maps smbwrp_fileinfo data fields into a native OS/2 file informations
236// and add the result to Netdrive internal list
237//
[976]238int addFindInfoL(Resource * pRes, void * plist, smbwrp_fileinfo * finfo, ULONG ulAttribute, char * mask)
[5]239{
[976]240 debuglocal(pRes, 9, "addFindInfoL finfo %p, fname %s\n", finfo, finfo->fname);
[959]241 FILESTATUS3L stat = {0};
242 char * name = ph->fsphStrRChr(finfo->fname, '\\');
243 if (name)
244 name++;
245 else
246 name = finfo->fname;
[5]247
[976]248 if (!*name && pRes != NULL)
249 name = pRes->srv.share_name;
[5]250
[959]251 if (mask && (!ph->fsphAttrMatch(ulAttribute, finfo->attr & 0x37) || !ph->fsphWildMatch(mask, name, ND_IGNORE_CASE)))
252 return 0;
[5]253
[959]254 stat.cbFile = finfo->size;
255 stat.cbFileAlloc = stat.cbFile;
256 stat.attrFile = (finfo->attr & 0x37);
257
[976]258 fsphUnixTimeToDosDate(pRes, finfo->mtime, &stat.fdateLastWrite, &stat.ftimeLastWrite);
259 fsphUnixTimeToDosDate(pRes, finfo->ctime, &stat.fdateCreation, &stat.ftimeCreation);
260 fsphUnixTimeToDosDate(pRes, finfo->atime, &stat.fdateLastAccess, &stat.ftimeLastAccess);
261 debuglocal(pRes, 9, "fname %s\n", finfo->fname);
262 debuglocal(pRes, 9, "mtime %d %s", finfo->mtime, ctime( (time_t*)&finfo->mtime));
263 debuglocal(pRes, 9, "ftimeLastAccess %02d:%02d:%02d\n", stat.ftimeLastWrite.hours, stat.ftimeLastWrite.minutes, stat.ftimeLastWrite.twosecs*2);
[959]264
265 ph->fsphAddFile32L(plist, &stat, name, strlen(name), finfo, sizeof(*finfo), 0);
266 return 1;
[5]267}
268
[976]269//
270// maps smbwrp_fileinfo data fields into a native OS/2 file informations
271// and add the result to Netdrive internal list
272//
273void addFindInfoCachedL(void *plist, void* custom)
274{
275 smbwrp_fileinfo* finfo = (smbwrp_fileinfo*)custom;
276 debuglocal(NULL, 9, "addFindInfoCachedL finfo %p, fname %s\n", finfo, finfo->fname);
277
278 // convert STATUS fields
279 FILESTATUS3L stat = {0};
280 stat.cbFile = finfo->size;
281 stat.cbFileAlloc = stat.cbFile;
282 stat.attrFile = (finfo->attr & 0x37);
283
284 // convert timestamps
285 fsphUnixTimeToDosDate(NULL, finfo->mtime, &stat.fdateLastWrite, &stat.ftimeLastWrite);
286 fsphUnixTimeToDosDate(NULL, finfo->ctime, &stat.fdateCreation, &stat.ftimeCreation);
287 fsphUnixTimeToDosDate(NULL, finfo->atime, &stat.fdateLastAccess, &stat.ftimeLastAccess);
288
289 // add to netdrive plist
290 ph->fsphAddFile32L(plist, &stat, finfo->fname, strlen(finfo->fname),
291 finfo, sizeof(smbwrp_fileinfo), 0);
292}
293
[116]294static unsigned char fromhex (char c)
295{
[959]296 if ('0' <= c && c <= '9')
297 return c - '0';
[818]298
[959]299 if ('A' <= c && c <= 'F')
300 return c - 'A' + 0xA;
[818]301
[959]302 if ('a' <= c && c <= 'f')
303 return c - 'a' + 0xA;
[818]304
[959]305 return 0;
[116]306}
[5]307
[116]308static char tohex (unsigned char b)
309{
[959]310 b &= 0xF;
[818]311
[959]312 if (b <= 9)
313 return b + '0';
[818]314
[959]315 return 'A' + (b - 0xA);
[116]316}
317
318static void decryptPassword (const char *pszCrypt, char *pszPlain)
319{
[959]320 // A simple "decryption", character from the hex value.
321 const char *s = pszCrypt;
322 char *d = pszPlain;
[818]323
[959]324 while (*s)
325 {
326 *d++ = (char)((fromhex (*s++) << 4) + fromhex (*s++));
327 }
[818]328
[959]329 *d++ = 0;
330 return;
[116]331}
332
333static void encryptPassword (const char *pszPlain, char *pszCrypt)
334{
[959]335 // A simple "encryption" encode each character as hex value. */
336 const char *s = pszPlain;
337 char *d = pszCrypt;
[818]338
[959]339 while (*s)
340 {
341 *d++ = tohex ((*s) >> 4);
342 *d++ = tohex (*s);
343 s++;
344 }
[818]345
[959]346 *d++ = 0;
347 return;
[116]348}
349
[976]350/* callback for caching code used to free resources allocated when
351 * calling dircache_write_entry() in smbwrp.c
352 */
353static void cacheFreeEntry( void*custom)
354{
355 smbwrp_fileinfo* finfo = (smbwrp_fileinfo*)custom;
356 debuglocal(NULL, 9, "cacheFreeEntry finfo %p -> %s\n", finfo, finfo->fname);
357 // release memory
358 free( finfo);
359}
360
[5]361/* accept parameters in form
362 * [filename][;name=filename]
363 */
[145]364int initResource (Resource *pRes, NDPROPERTYHANDLE properties)
[5]365{
[959]366 int rc = NO_ERROR;
367 unsigned long t;
368 const char * q = NULL;
369 int defaultPassword = 1;
[5]370
[959]371 pRes->rootlevel = 0;
372 pRes->easupport = 1;
[145]373#ifdef HAVE_KRB5_H
[959]374 pRes->krb5support = 1;
[145]375#else
[959]376 pRes->krb5support = 0;
[145]377#endif
[960]378 pRes->loglevel = 0;
[5]379
[959]380 t = 0, q = NULL;
381 rc = ph->fsphQueryStringProperty (properties, "WORKGROUP", &q, &t);
382 if (!rc && t && *q)
383 {
384 strncpy(pRes->srv.workgroup, q, sizeof(pRes->srv.workgroup) - 1);
385 pRes->rootlevel = 1;
386 }
[5]387
[959]388 t = 0, q = NULL;
389 rc = ph->fsphQueryStringProperty (properties, "SERVER", &q, &t);
390 if (!rc && t && *q)
391 {
392 strncpy(pRes->srv.server_name, q, sizeof(pRes->srv.server_name) - 1);
393 pRes->rootlevel = 2;
394 }
[5]395
[959]396 t = 0, q = NULL;
397 rc = ph->fsphQueryStringProperty (properties, "SHARE", &q, &t);
398 if (!rc && t && *q)
399 {
400 strncpy(pRes->srv.share_name, q, sizeof(pRes->srv.share_name) - 1);
401 pRes->rootlevel = 3;
402 }
[5]403
[959]404 t = 0, q = NULL;
405 rc = ph->fsphQueryStringProperty (properties, "USER", &q, &t);
406 if (!rc && t && *q)
407 strncpy(pRes->srv.username, q, sizeof(pRes->srv.username) - 1);
[5]408
[959]409 t = 0, q = NULL;
410 rc = ph->fsphQueryStringProperty (properties, "PASSWORD", &q, &t);
411 if (!rc && t && *q)
412 {
413 strncpy(pRes->srv.password, q, sizeof(pRes->srv.password) - 1);
414 defaultPassword = 0;
415 }
[5]416
[959]417 t = 0, q = NULL;
418 rc = ph->fsphQueryStringProperty (properties, "SPASSWORD", &q, &t);
419 if (rc == NO_ERROR && *q != '\0' && defaultPassword)
420 {
421 char p[1024];
422 p[0] = 0;
[116]423
[959]424 decryptPassword (q, p);
425 if (*p)
426 {
427 strncpy(pRes->srv.password, p, sizeof(pRes->srv.password) - 1);
428 // clear the plain password
429 ph->fsphSetProperty (properties, "PASSWORD", "");
430 }
431 }
432 else
433 {
434 char c[1024];
435 encryptPassword (pRes->srv.password, c);
436 ph->fsphSetProperty (properties, "SPASSWORD", c);
437 // clear the plain password
438 ph->fsphSetProperty (properties, "PASSWORD", "");
439 }
[818]440
[959]441 t = 0, q = NULL;
442 rc = ph->fsphQueryStringProperty (properties, "MASTER", &q, &t);
443 if (!rc && t && *q)
444 strncpy(pRes->srv.master, q, sizeof(pRes->srv.master) - 1);
[818]445
[959]446 t = 0;
447 rc = ph->fsphQueryUlongProperty (properties, "MASTERTYPE", &t);
448 if (!rc)
449 {
450 if (t > 1)
451 rc = ERROR_INVALID_PARAMETER;
452 else
453 pRes->srv.ifmastergroup = t;
454 }
[818]455
[959]456 t = 0;
457 rc = ph->fsphQueryUlongProperty (properties, "EASUPPORT", &t);
458 if (!rc)
459 {
460 if (t > 1)
461 rc = ERROR_INVALID_PARAMETER;
462 else
463 pRes->easupport = t;
464 }
[818]465
[959]466 t = 0;
467 rc = ph->fsphQueryUlongProperty (properties, "CTO", &t);
468 if (!rc)
469 {
470 if (t > 600)
471 rc = ERROR_INVALID_PARAMETER;
472 else
473 pRes->cachetimeout = t;
474 }
[818]475
[959]476 t = 0;
477 rc = ph->fsphQueryUlongProperty (properties, "CLD", &t);
478 if (!rc)
479 {
480 if (t > 96)
481 rc = ERROR_INVALID_PARAMETER;
482 else
483 pRes->cachedepth = t;
484 }
[5]485
[960]486 t = 0;
487 rc = ph->fsphQueryUlongProperty (properties, "LOGLEVEL", &t);
488 if (!rc)
489 {
490 if (t > 10)
491 rc = ERROR_INVALID_PARAMETER;
492 else
493 pRes->loglevel = t;
494 }
495
496 // figure out the used share/server/workgroup
497 char *logfileext = '\0';
498 if (pRes->srv.share_name)
499 logfileext = pRes->srv.share_name;
500 if (!logfileext && pRes->srv.server_name)
501 logfileext = pRes->srv.server_name;
502 if (!logfileext && pRes->srv.workgroup)
503 logfileext = pRes->srv.workgroup;
504
505 // init debug and write the very first message
506 debugInit(pRes, logfileext, ifL);
507 debuglocal(pRes, 9, "NdpMountResource initResource\n");
508
509 // init code
510 smbwrp_init(pRes);
511
[959]512 /*
513 * Create a directory cache with expiration time and cache listings
514 * the above values come from the gui. default: timeout 10; listings: 32
515 */
[970]516 dircache_create(&pRes->pdc, (void*) pRes,
[983]517 pRes->cachetimeout, pRes->cachedepth, cacheFreeEntry, ph);
[5]518
[959]519 return rc;
[5]520}
521
522int iftestpath(char * path)
523{
[959]524 char * p = path;
525 if (!path)
526 return 0;
527
528 while ((p = ph->fsphStrChr(p, 'A')) != NULL)
529 {
530 if (ph->fsphStrNCmp(p, "A.+,;=[].B", 10) == 0)
531 return 1;
532 p++;
533 }
534 return 0;
[5]535}
536
537int pathparser(Resource *pRes, Connection * pConn, char * path, char * result)
538{
[959]539 int rootlevel;
540 int rc = NO_ERROR;
541 if (!pRes || !path || !result)
542 return ERROR_INVALID_PARAMETER;
[145]543
[959]544 /* handle special case when someone wants to test support of
545 * LFN or smth similar
546 */
547 if (iftestpath(path))
548 {
549 strcpy(result, "\\A.+,;=[].B");
550 return NO_ERROR;
551 }
[180]552
[959]553 rootlevel = pRes->rootlevel;
554 if (*path == '\\') path++;
[180]555
[959]556 if (rootlevel < 3)
557 {
558 char * p;
559 // flag: 1 parameters changed, reconnection required, 0 do nothing
560 int newlevel = 0;
561 // use a temporary resource to test disconnection/reconnection
562 Resource tmpRes;
563 // copy exising data
564 memcpy( &tmpRes, pRes, sizeof( tmpRes));
565 // pointer to new connection fields
566 smbwrp_server * tmp = &tmpRes.srv;
567 if (rootlevel == 0)
568 {
569 p = ph->fsphStrChr(path, '\\');
570 if (!p)
571 p = path + strlen(path);
[145]572
[959]573 if (strlen(tmp->workgroup) != p - path ||
574 (p == path ||
575 ph->fsphStrNICmp(path, tmp->workgroup, p - path)))
576 {
577 strncpy(tmp->workgroup, path, p - path);
578 tmp->workgroup[p - path] = 0;
579 newlevel = 1;
580 }
581 path = *p == '\\' ? p + 1 : p;
582 rootlevel = 1;
583 }
[5]584
[959]585 if (rootlevel == 1) // root path starts from server name
586 {
587 p = ph->fsphStrChr(path, '\\');
588 if (!p)
589 p = path + strlen(path);
590
591 if (strlen(tmp->server_name) != p - path ||
592 (p == path ||
593 ph->fsphStrNICmp(path, tmp->server_name, p - path)))
594 {
595 strncpy(tmp->server_name, path, p - path);
596 tmp->server_name[p - path] = 0;
597 newlevel = 1;
598 }
599 path = *p == '\\' ? p + 1 : p;
600 rootlevel = 2;
601 }
[5]602
[959]603 if (rootlevel == 2) // root path starts from share name
604 {
605 p = ph->fsphStrChr(path, '\\');
606 if (!p)
607 p = path + strlen(path);
[5]608
[959]609 if (strlen(tmp->share_name) != (p - path) ||
610 (p == path ||
611 ph->fsphStrNICmp(path, tmp->share_name, p - path)))
612 {
613 strncpy(tmp->share_name, path, p - path);
614 tmp->share_name[p - path] = 0;
615 newlevel = 1;
616 }
617 path = *p == '\\' ? p + 1 : p;
618 }
619
620 if (newlevel)
621 {
622 // reconnect to server here, first test new connection
623 cli_state* tmp_cli = NULL;
[960]624 rc = smbwrp_connect(&tmpRes, &tmp_cli);
[959]625 if (!rc)
626 {
627 // new connection is ok, disconnect old one
628 cli_state* cli = pConn->cli;
[960]629 smbwrp_disconnect(pRes, cli);
[959]630 // save tmp data structure
631 memcpy( pRes, &tmpRes, sizeof( tmpRes));
632 // save new connection handle
633 pConn->cli = tmp_cli;
634 }
635 }
636 }
637
638 strcpy(result, "\\");
639 strncat(result, path, CCHMAXPATH);
640 return rc;
641}
642
[131]643/* check if the requested resource is available */
[960]644static int checkMountResource(Resource* pRes)
[131]645{
[959]646 int rc;
647 unsigned long action;
648 cli_state* cli = NULL;
[131]649
[960]650 debuglocal(pRes, 9, "checkMountResource in tid#%d\n", _gettid());
651 rc = smbwrp_connect(pRes, &cli);
[959]652 switch (rc)
653 {
654 case 0:
655 rc = NO_ERROR;
656 break;
657 case 1:
658 case 10:
659 case 11:
660 rc = ERROR_BAD_NET_NAME;
661 break;
662 case 2:
663 rc = ERROR_INIT_ROUTINE_FAILED;
664 break;
665 case 3:
666 rc = ERROR_BAD_NET_RESP;
667 break;
668 case 4:
669 rc = ERROR_NETWORK_BUSY;
670 break;
671 case 6:
672 rc = ERROR_NETWORK_ACCESS_DENIED;
673 break;
674 case 7:
675 rc = ERROR_BAD_NETPATH;
676 break;
677 default:
678 rc = ERROR_UNEXP_NET_ERR;
679 break;
680 } /* endswitch */
[179]681
[960]682 smbwrp_disconnect(pRes, cli);
[959]683 return rc;
[131]684}
685
[5]686int APIENTRY NdpMountResource (HRESOURCE *presource, int type, NDPROPERTYHANDLE properties)
687{
[959]688 int rc = NO_ERROR;
689 unsigned long objany = OBJ_ANY;
690 Resource *pRes = NULL;
[131]691
[959]692 ENTER();
[567]693
[959]694 /*
695 * since samba plugin support only 1 type of resources we do not need
696 * to check what the found type really is
697 */
698 pRes = malloc( sizeof(Resource));
699 if (pRes == NULL)
700 rc = ERROR_NOT_ENOUGH_MEMORY;
701 else
702 {
703 memset(pRes, 0, sizeof(Resource));
704 // parse init string
705 rc = initResource (pRes, properties);
706 /*
707 * try to connect to resource (check type) only if thread!=1,
708 * so ndctl startup is not slowed down by network connections.
709 * ndctl does mounting on main thread (#1)
710 * nd/ndpm do not use main thread
711 */
712 if (!rc && _gettid()!=1)
713 rc = checkMountResource( pRes);
714 if (!rc)
715 {
716 // store resource data
717 *presource = (HRESOURCE)pRes;
718 }
719 else
720 free(pRes);
721
722 }
[145]723
[960]724 debuglocal(pRes, 9, "NdpMountResource rc=%d\n", rc);
[959]725 LEAVE();
726 return rc;
[5]727}
728
[145]729int APIENTRY NdpFreeResource (HRESOURCE resource)
[5]730{
[959]731 Resource *pRes = (Resource *)resource;
732 ENTER();
[966]733
734 // free cache dir
735 dircache_delete(pRes->pdc);
736
737 // free local resources
[959]738 memset(&pRes->srv, 0, sizeof(pRes->srv));
[960]739 debuglocal(pRes, 9, "NdpFreeResource %d\n", NO_ERROR);
740 debugClose(pRes);
[959]741 free(pRes);
742 LEAVE();
743 return NO_ERROR;
[5]744}
745
746int APIENTRY NdpRsrcCompare (HRESOURCE resource, HRESOURCE resource2)
747{
[959]748 Resource *pRes = (Resource *)resource;
749 Resource *pRes2 = (Resource *)resource2;
750 int rc = ND_RSRC_DIFFERENT;
[5]751
[960]752 debuglocal(pRes, 9, "NdpRsrcCompare in\n");
[959]753 if (ph->fsphStrICmp(pRes->srv.server_name, pRes2->srv.server_name) == 0
754 && ph->fsphStrICmp(pRes->srv.share_name, pRes2->srv.share_name) == 0
755 && ph->fsphStrICmp(pRes->srv.username, pRes2->srv.username) == 0
756 && ph->fsphStrICmp(pRes->srv.workgroup, pRes2->srv.workgroup) == 0)
757 {
758 // resources are equal
759 rc = ND_RSRC_EQUAL;
760 }
[5]761
[960]762 debuglocal(pRes, 9, "NdpRsrcCompare %d\n", rc);
[959]763 return rc;
[5]764}
765
766int APIENTRY NdpRsrcUpdate (HRESOURCE resource, HRESOURCE resource2)
767{
[959]768 // do nothing
[960]769 Resource *pRes = (Resource *)resource;
770 debuglocal(pRes, 9, "NdpRsrcUpdate %d\n", NO_ERROR);
[959]771 return NO_ERROR;
[5]772}
773
774int APIENTRY NdpRsrcQueryInfo (HRESOURCE resource, ULONG *pulFlags, void *pdata, ULONG insize, ULONG *poutlen)
775{
[959]776 Resource *pRes = (Resource *)resource;
777 int rc = NO_ERROR;
778 char s[4096];
[5]779
[960]780 debuglocal(pRes, 9, "NdpRsrcQueryInfo in\n");
[5]781
[959]782 switch (pRes->rootlevel)
783 {
784 case 0:
785 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s \\\\@%s", ifL ? "64" : "32", pRes->srv.username);
786 break;
787 case 1:
788 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s %s: \\\\@%s", ifL ? "64" : "32", pRes->srv.workgroup, pRes->srv.username);
789 break;
790 case 2:
791 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s \\\\%s%s%s@%s", ifL ? "64" : "32", *pRes->srv.workgroup ? pRes->srv.workgroup : "", *pRes->srv.workgroup ? ":" : "", pRes->srv.server_name, pRes->srv.username);
792 break;
793 default:
794 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s \\\\%s%s%s\\%s@%s", ifL ? "64" : "32", *pRes->srv.workgroup ? pRes->srv.workgroup : "", *pRes->srv.workgroup ? ":" : "", pRes->srv.server_name, pRes->srv.share_name, pRes->srv.username);
795 break;
796 }
797 *poutlen = strlen(s) + 1;
798 if (*poutlen > insize)
799 rc = ERROR_BUFFER_OVERFLOW;
800 else
801 memcpy(pdata, s, *poutlen);
[5]802
[960]803 debuglocal(pRes, 9, "NdpRsrcQueryInfo %d\n", rc);
[959]804 return rc;
[5]805}
806
807int APIENTRY NdpRsrcQueryFSAttach (HRESOURCE resource, void *pdata, ULONG insize, ULONG *poutlen)
808{
[959]809 ULONG ulDummy = 0;
810 // just return the resource info string
811 return NdpRsrcQueryInfo (resource, &ulDummy, pdata, insize, poutlen);
[5]812}
813
814int APIENTRY NdpRsrcQueryFSAllocate (HRESOURCE resource, NDFSALLOCATE *pfsa)
815{
[959]816 Resource *pRes = (Resource *)resource;
817 int rc = NO_ERROR, rc1;
818 unsigned long action = 0;
819 cli_state* cli = NULL;
820 FSALLOCATE fsa;
[5]821
[959]822 ENTER();
[960]823 debuglocal(pRes, 9, "NdpRsrcQueryFSAllocate %08x\n", pfsa);
[5]824
[959]825 if (!pfsa)
826 {
827 LEAVE();
828 return NO_ERROR;
829 }
[5]830
[960]831 debuglocal(pRes, 9, "NdpRsrcQueryFSAllocate in tid#%d\n", _gettid());
832 rc = smbwrp_connect(pRes, &cli);
[959]833 if (rc)
834 {
[960]835 debuglocal(pRes, 9, "NdpRsrcQueryFSAllocate smbwrp_connect failed rc=%d\n", rc);
[959]836 pfsa->cSectorUnit = 1;
837 pfsa->cUnit = 123456;
838 pfsa->cUnitAvail = 123456;
839 pfsa->cbSector = 2048;
840 rc = (rc == 7 ? ERROR_BAD_DEV_TYPE : ERROR_ACCESS_DENIED);
841 LEAVE();
842 return rc;
843 }
[5]844
[960]845 rc = smbwrp_dskattr(pRes, cli, &fsa);
[959]846 if (rc)
847 {
848 pfsa->cSectorUnit = 1;
849 pfsa->cUnit = 123456;
850 pfsa->cUnitAvail = 123456;
851 pfsa->cbSector = 2048;
852 //rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
853 }
854 else
855 {
856 pfsa->cSectorUnit = fsa.cSectorUnit;
857 pfsa->cUnit = fsa.cUnit;
858 pfsa->cUnitAvail = fsa.cUnitAvail;
859 pfsa->cbSector = fsa.cbSector;
860 }
[5]861
[960]862 smbwrp_disconnect(pRes, cli);
863 debuglocal(pRes, 9, "NdpRsrcQueryFSAllocate %d/%d (cUnit = %d/cUnitAvail = %d/cbSector = %d)\n", rc, rc1, pfsa->cUnit, pfsa->cUnitAvail, pfsa->cbSector);
[5]864
[959]865 LEAVE();
866 return rc;
[5]867}
868
[145]869int APIENTRY NdpCreateConnection (HRESOURCE resource, HCONNECTION *pconn)
[5]870{
[959]871 int rc = 0;
872 Resource * pRes = (Resource *)resource;
873 unsigned long action;
874 Connection *pConn = NULL;
[5]875
[959]876 ENTER();
[567]877
[960]878 debuglocal(pRes, 9, "NdpCreateConnection in\n");
[145]879
[959]880 pConn = malloc( sizeof(Connection));
881 if (pConn == NULL)
882 rc = ERROR_NOT_ENOUGH_MEMORY;
[5]883
[959]884 if (rc)
885 {
[960]886 debuglocal(pRes, 9, "NdpCreateConnection ERROR_NOT_ENOUGH_MEMORY %d\n", rc);
[959]887 LEAVE();
888 return rc;
889 }
[5]890
[959]891 memset(pConn, 0, sizeof(Connection));
892 pConn->pRes = pRes;
893 pConn->file.fd = -1;
894
[960]895 debuglocal(pRes, 9, "NdpCreateConnection send CONNECT\n");
896 rc = smbwrp_connect(pRes, &pConn->cli);
[959]897 if (rc)
898 {
899 free(pConn);
900 pConn = NULL;
901 rc = (rc == 7 ? ERROR_BAD_DEV_TYPE : ERROR_INVALID_PARAMETER);
902 }
903
904 *pconn = (HCONNECTION)pConn;
[960]905 debuglocal(pRes, 9, "NdpCreateConnection [%p] %d\n", pConn, rc);
[959]906
907 LEAVE();
908 return rc;
[145]909}
[5]910
[145]911int APIENTRY NdpFreeConnection (HCONNECTION conn)
912{
[959]913 Connection *pConn = (Connection *)conn;
914 Resource *pRes = pConn->pRes;
915 int rc;
[145]916
[959]917 ENTER();
[567]918
[960]919 debuglocal(pRes, 9, "NdpFreeConnection in [%p]\n", pConn);
[959]920 if (pConn->file.fd >= 0)
921 {
[960]922 rc = smbwrp_close(pRes, pConn->cli, &pConn->file);
[959]923 pConn->file.fd = -1;
924 }
[145]925
[960]926 smbwrp_disconnect(pRes, pConn->cli);
[145]927
[960]928 debuglocal(pRes, 9, "NdpFreeConnection %d\n", NO_ERROR);
[959]929 free(pConn);
930
931 LEAVE();
932 return NO_ERROR;
[5]933}
934
[150]935/*
936 * NdpQueryPathInfo is the most important function :) netdrive always calls
[818]937 * the function before every operation to find out the path status:
938 * does it exist, is it a file, does a parent directory exist, etc.
[150]939 * Plugin must return one of the following error codes:
[818]940 * NO_ERROR - path exists and the path information have been successfully
941 * retrieved.
[150]942 * ERROR_FILE_NOT_FOUND - all but the last component of the path exist and the
[818]943 * path without the last component is a directory. dir1_ok\dir2_ok\does_not_exist.
944 * the wildcard can not exist, so the plugin returns FILE_NOT_FOUND, if the parent
945 * directory exist.
[150]946 * ERROR_PATH_NOT_FOUND - any of not last path components does not exist, or all
[818]947 * but the last component exist and is a file: \dir_ok\dir2_ok\file_ok\non_existing.
[150]948 * ERROR_REM_NOT_LIST - resource is temporarily unavailable for some reasons.
949 * Any other error codes means an internal plugin error, not related to the status
950 * of the path queried.
951 */
[5]952int APIENTRY NdpQueryPathInfo (HCONNECTION conn, void *plist, char *szPath)
953{
[959]954 Connection *pConn = (Connection *)conn;
955 Resource *pRes = pConn->pRes;
956 smbwrp_fileinfo finfo;
957 int rc = 0;
958 int rcCon = 0;
959 char path[CCHMAXPATH+1] = {0};
[963]960 NDPATHELEMENT *pel = NULL;
[5]961
[959]962 ENTER();
[567]963
[960]964 debuglocal(pRes, 9, "NdpQueryPathInfo in [%p] <%s>\n", pConn, szPath);
[150]965
[959]966 /*
967 * if wildcard is specified, we suppose parent dir exist,
968 * so exit immediately
969 */
970 if (ph->fsphStrChr(szPath, '*') || ph->fsphStrChr(szPath, '?'))
971 {
972 LEAVE();
973 return ERROR_FILE_NOT_FOUND;
974 }
[5]975
[959]976 do {
977 // First check if there is information in the directory cache.
978 unsigned long ulAge = 0;
[976]979 void* _finfo;
980 if (dircache_find_path(pRes->pdc, szPath, &_finfo, &ulAge))
[959]981 {
982 if (ulAge <= 15) /* @todo configurable. */
983 {
984 rc = NO_ERROR;
[976]985 ((smbwrp_fileinfo*)_finfo)->easize = -1;
986 addFindInfoCachedL(plist, _finfo);
[959]987 break;
988 }
989 }
[150]990
[959]991 rc = pathparser(pRes, pConn, szPath, path);
[960]992 debuglocal(pRes, 9, "NdpQueryPathInfo pathparser for <%s> rc=%d\n", path, rc);
[959]993 switch (rc)
994 {
995 case NO_ERROR :
996 case ERROR_FILE_NOT_FOUND:
997 case ERROR_PATH_NOT_FOUND:
998 case ERROR_ACCESS_DENIED:
999 case ERROR_INVALID_PARAMETER:
1000 break;
1001 default :
1002 rc = ERROR_PATH_NOT_FOUND;
1003 }
[5]1004
[959]1005 if (rc)
1006 break;
[728]1007
[959]1008 strncpy(finfo.fname, path, sizeof(finfo.fname) - 1);
[960]1009 debuglocal(pRes, 9, "NdpQueryPathInfo smbwrp_getattr for <%s>\n", path);
1010 rc = smbwrp_getattr(pRes, &pRes->srv, pConn->cli, &finfo);
[959]1011 if (rc)
1012 {
1013 // remote server not available for first time?
1014 if (rc == ERROR_REM_NOT_LIST)
1015 {
1016 // free current cli resources
[960]1017 smbwrp_disconnect(pRes, pConn->cli);
[959]1018 // reconnect
[960]1019 rcCon = smbwrp_connect(pRes, &pConn->cli);
[959]1020 if (rcCon != NO_ERROR)
[960]1021 debuglocal(pRes, 9, "NdpQueryPathInfo smbwrp_connect rc = %d\n", rcCon);
[959]1022 // try file list again if reconnecting worked
1023 if (rcCon == NO_ERROR)
[960]1024 rc = smbwrp_getattr(pRes, &pRes->srv, pConn->cli, &finfo);
[959]1025 }
[145]1026
[960]1027 debuglocal(pRes, 9, "NdpQueryPathInfo smbwrp_getattr, rc = %d\n", rc);
[959]1028 switch (rc)
1029 {
1030 case NO_ERROR :
1031 case ERROR_FILE_NOT_FOUND:
1032 case ERROR_PATH_NOT_FOUND:
1033 case ERROR_ACCESS_DENIED:
1034 case ERROR_INVALID_PARAMETER:
1035 case ERROR_REM_NOT_LIST:
1036 break;
1037 default :
1038 rc = ERROR_PATH_NOT_FOUND;
1039 }
1040 }
1041
1042 if (rc == NO_ERROR)
1043 {
1044 finfo.easize = -1;
[976]1045 addFindInfoL(pRes, plist, &finfo, 0, NULL);
[959]1046 }
1047 else if (rc == ERROR_FILE_NOT_FOUND)
1048 {
1049 // now try the upper path
1050 char * p = ph->fsphStrRChr(finfo.fname, '\\');
1051 if (p && p > finfo.fname)
1052 {
1053 *p = 0;
[960]1054 rc = smbwrp_getattr(pRes, &pRes->srv, pConn->cli, &finfo);
1055 debuglocal(pRes, 9, "NdpQueryPathInfo upper path in <%s>, rc = %d\n", finfo.fname, rc);
[959]1056 if (rc == NO_ERROR)
1057 rc = (finfo.attr & FILE_DIRECTORY) !=0 ? ERROR_FILE_NOT_FOUND:ERROR_PATH_NOT_FOUND;
1058 else if (rc != ERROR_REM_NOT_LIST)
1059 rc = ERROR_PATH_NOT_FOUND;
1060 }
1061 }
1062 } while (0);
[963]1063
1064 // if file/path exists, store parent path in resourcedata
1065 // for NdpEA* calls
1066 if ((rc == NO_ERROR || rc == ERROR_FILE_NOT_FOUND)
1067 && (pel = ph->fsphNameElem (0)))
1068 {
1069 char szFullPath[CCHMAXPATH+1] = {0};
1070 // save parent full path for future use in NdpEA* calls
1071 strcpy(szFullPath, szPath);
1072 // strip pel name, leaving ending slash in place
1073 int len = strlen(szFullPath) - pel->length;
1074 szFullPath[len] = '\0';
1075 int rc2 = ph->fsphSetResourceData( plist, szFullPath, strlen(szFullPath) + 1);
1076 debuglocal(pRes, 9, "NdpQueryPathInfo <%s> plist %x, szFullPath (%s), rc2=%d\n",
1077 szPath, plist, szFullPath, rc2);
1078 }
1079
[960]1080 debuglocal(pRes, 9, "NdpQueryPathInfo <%s> (%s) %d\n", szPath, path, rc);
[959]1081
1082 LEAVE();
1083 return rc;
[5]1084}
1085
[145]1086int APIENTRY NdpFindStart (HCONNECTION conn, void *plist, NDFILEINFOL *pfiparent, char *szPath, ULONG ulAttribute)
1087{
[959]1088 Connection *pConn = (Connection *)conn;
1089 Resource *pRes = pConn->pRes;
[976]1090 int rc = NO_ERROR;
[959]1091 unsigned long action;
1092 char *mask = "*";
1093 char dir[CCHMAXPATH+1] = {0};
1094 char path[CCHMAXPATH+1] = {0};
1095 NDPATHELEMENT *pel = ph->fsphNameElem(0);
1096 filelist_state state;
1097 char * p;
[145]1098
[959]1099 ENTER();
[567]1100
[960]1101 debuglocal(pRes, 9, "NdpFindStart in [%p]\n", pConn);
[145]1102
[959]1103 strncpy(dir, szPath, sizeof(dir) - 1);
1104 if (pel)
1105 {
1106 mask = pel->name;
1107 dir[strlen(szPath) - pel->length] = 0;
1108 }
1109 action = strlen(dir) - 1;
1110 if (dir[action] == '\\')
1111 dir[action] = 0;
[145]1112
[959]1113 rc = pathparser(pRes, pConn, dir, path);
1114 if (rc)
1115 return rc;
[145]1116
[959]1117 action = strlen(path) - 1;
1118 if (path[action] != '\\')
1119 strncat(path, "\\", sizeof(path) - 1);
1120
1121 strcpy(dir, path);
1122 strncat(path, mask, sizeof(path) - 1);
1123
1124 /*
1125 * this structure will be used by libsmb callbacks,
1126 * so we store here all we need to fill netdrive structures
1127 */
1128 state.pConn = pConn;
1129 state.plist = plist;
1130 state.ulAttribute = ulAttribute;
1131 strcpy(state.dir, dir);
1132 strcpy(state.dir_mask, mask);
1133 strcpy(state.mask, path);
1134 state.fullpath = szPath;
1135 /*
1136 * This plugin always reads a complete directory listing and
[968]1137 * filters results using actual mask (state.dir_mask) in addFindInfoL.
[959]1138 * May be this was a workaround for some server bug.
1139 * If this will be changed, then directory listing cache must
1140 * be changed too, and must remember the mask, which was used to
1141 * obtain a listing. Now the directory cache saves complete directory
1142 * listings and then uses them to find information about single files.
1143 * However, with a directory cache, it is probably faster to get a full
1144 * listing and then use it to obtain info about separate files than to
1145 * perform a network list query operation using actual wild cards for
1146 * each file. Some application, for example OpenOffice, do this.
1147 */
1148 p = getlastslash(state.mask);
1149 if (p)
1150 {
1151 *(p + 1) = '*';
1152 *(p + 2) = 0;
1153 }
1154 else
1155 strcpy(state.mask, "\\*");
1156
[960]1157 debuglocal(pRes, 9, "NdpFindStart: dir [%s], dir_mask [%s], mask [%s], szPath [%s]\n",
[959]1158 state.dir, state.dir_mask, state.mask, state.fullpath);
[960]1159 rc = smbwrp_filelist(pRes, &pRes->srv, pConn->cli, &state);
[959]1160 /*
1161 * we need to handle reconnection also here, because NdpQueryPathInfo
1162 * could be called with '*' and exit then immediately
1163 * (without calling libsmb)
1164 */
1165 if (rc == ERROR_REM_NOT_LIST)
1166 {
1167 // free current cli resources
[960]1168 smbwrp_disconnect(pRes, pConn->cli);
[959]1169 // reconnect
[960]1170 smbwrp_connect(pRes, &pConn->cli);
[959]1171 // try file list again next loop
[960]1172 rc = smbwrp_filelist(pRes, &pRes->srv, pConn->cli, &state);
1173 debuglocal(pRes, 9, "NdpFindStart remote connection lost, rc = %d\n", rc);
[959]1174 }
1175
[976]1176 debuglocal(pRes, 9, "NdpFindStart <%s> (%s) rc %d\n", szPath, path, rc);
[959]1177
1178 LEAVE();
1179 return rc;
[145]1180}
1181
[5]1182int APIENTRY NdpDeletePathInfo (HRESOURCE resource, NDFILEINFOL *pfi)
1183{
[960]1184 Resource * pRes = (Resource *)resource;
1185 debuglocal(pRes, 9, "NdpDeletePathInfo %d\n", 0);
[959]1186 return NO_ERROR;
[5]1187}
1188
1189int APIENTRY NdpRefresh (HCONNECTION conn, char *path, int tree)
1190{
[960]1191 Connection *pConn = (Connection *)conn;
1192 debuglocal(pConn->pRes, 9, "NdpRefresh <%s> %d\n", path, 0);
[959]1193 return NO_ERROR;
[5]1194}
1195
1196int APIENTRY NdpDiscardResourceData (HRESOURCE resource, NDDATABUF *pdatabuf)
1197{
[959]1198 /*
1199 * The plugin do not have to deallocate anything, because
1200 * resource data did not contain any pointers to plugins data.
1201 * Data stored by fsphSetResourceData will be deallocated by NetDrive.
1202 */
[5]1203
[960]1204 Resource * pRes = (Resource *)resource;
1205 debuglocal(pRes, 9, "NdpDicardresourceData %d\n", 0);
[959]1206 return NO_ERROR;
[5]1207}
1208
1209int APIENTRY NdpSetPathInfo (HCONNECTION conn, NDFILEINFOL *pfi, char *szPathName)
1210{
[959]1211 Connection *pConn = (Connection *)conn;
1212 Resource *pRes = pConn->pRes;
1213 int rc = 0;
1214 unsigned long action;
1215 char path[CCHMAXPATH+1] = {0};
1216 smbwrp_fileinfo finfo;
[5]1217
[959]1218 ENTER();
[567]1219
[960]1220 debuglocal(pRes, 9, "NdpSetPathInfo in [%p]\n", pConn);
[145]1221
[959]1222 // delete the dir cache
[966]1223 dircache_invalidate(pRes->pdc, szPathName, 1);
[508]1224
[959]1225 do {
1226 rc = pathparser(pRes, pConn, szPathName, path);
1227 if (rc)
1228 break;
[5]1229
[959]1230 memset(&finfo, 0, sizeof(finfo));
1231 strncpy(finfo.fname, path, sizeof(finfo.fname) - 1);
[960]1232 fsphDosDateToUnixTime(pRes, pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, &(finfo.mtime));
[959]1233 finfo.attr = pfi->stat.attrFile & 0x37;
[960]1234 rc = smbwrp_setattr(pRes, pConn->cli, &finfo);
[959]1235 } while (0);
[5]1236
[960]1237 debuglocal(pRes, 9, "NdpSetPathInfo <%s> (%s) %d\n", szPathName, path, rc);
[959]1238
1239 LEAVE();
1240 return rc;
[5]1241}
1242
[960]1243int buildFEALIST(Resource *pRes, FEALIST *pFEASrc, GEALIST *pGEAList, FEALIST *pFEAList)
[5]1244{
[959]1245 int rc = 0;
1246 FEA * pfea;
1247 FEA * pfeadest;
1248 unsigned long size;
1249 unsigned long done = sizeof(pFEAList->cbList);
1250 unsigned long dsize;
1251 unsigned long ddone = sizeof(pFEAList->cbList);
[5]1252
[959]1253 size = pFEASrc->cbList;
1254 pfea = pFEASrc->list;
1255 pfeadest = pFEAList->list;
1256 dsize = pFEAList->cbList;
[960]1257 //debuglocal(pRes, 9,"buildFEALIST in destsize %d srcsize %d pGEAList=%08x pGEAList->cbList=%d\n", dsize, ddone, size, pGEAList, pGEAList ? pGEAList->cbList : 0);
[959]1258
1259 while (done < size)
1260 {
1261 char * name = (char *)(pfea + 1);
1262 int insert = 1;
1263 if (pGEAList && pGEAList->cbList > sizeof(pGEAList->cbList))
1264 {
1265 GEA * pgea = pGEAList->list;
1266 unsigned long size = pGEAList->cbList - sizeof(pGEAList->cbList);
1267 unsigned long done = 0;
1268 insert = 0;
1269 while (done < size)
1270 {
[960]1271 //debuglocal(pRes, 9,"comp <%s> <%s>\n", name, pgea->szName);
[959]1272 if (!ph->fsphStrNCmp(name, pgea->szName, pgea->cbName))
1273 {
1274 insert = 1;
1275 break;
1276 }
1277 done += pgea->cbName + 2;
1278 pgea = (GEA *)((char *)pgea + pgea->cbName + 2);
1279 }
1280 }
1281 if (insert)
1282 {
1283 ddone += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1284 if (ddone <= dsize)
1285 {
1286 pfeadest->cbName = pfea->cbName;
1287 pfeadest->cbValue = pfea->cbValue;
1288 pfeadest->fEA = 0;
1289 strcpy((char *)(pfeadest + 1), name);
1290 memcpy((char *)(pfeadest + 1) + pfea->cbName + 1, (char *)(pfea + 1) + pfea->cbName + 1, pfea->cbValue);
1291 pfeadest = (FEA *)((char *)pFEAList + ddone);
1292 }
1293 }
1294 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
[960]1295 //debuglocal(pRes, 9,"buuildfea <%s> insert=%d pfea->cbName=%d pfea->cbValue=%d srcdone=%d destdone=%d pfeadest=%08x pfea=%08x\n", name, insert, pfea->cbName, pfea->cbValue, done, ddone, pfeadest, pfea);
[959]1296 pfea = (FEA *)((char *)pFEASrc + done);
1297 }
1298
1299 pFEAList->cbList = ddone;
1300 if (ddone > dsize && dsize > sizeof(pFEAList->cbList))
1301 rc = ERROR_BUFFER_OVERFLOW;
1302
[960]1303 debuglocal(pRes, 9, "buildFEALIST rc=%d destsize=%d destdone=%d srcsize=%d pGEAList=%08x\n", rc, dsize, ddone, size, pGEAList);
[959]1304 return rc;
[5]1305}
1306
1307int APIENTRY NdpEAQuery (HCONNECTION conn, GEALIST *pGEAList, NDFILEINFOL *pfi, FEALIST *pFEAList)
1308{
[959]1309 Connection *pConn = (Connection *)conn;
1310 Resource *pRes = pConn->pRes;
1311 int rc = 0;
1312 FEALIST * pFEASrc;
1313 NDDATABUF fdata = {0};
1314 const int cbBuffer = 64*1024;
[963]1315 NDDATABUF rsrcData = {0};
1316 char szFullPath[CCHMAXPATH+1];
[5]1317
[959]1318 if (!pfi || !pfi->pszName || !pFEAList)
1319 return ERROR_EAS_NOT_SUPPORTED;
[5]1320
[959]1321 if (!pRes->easupport)
1322 return ERROR_EAS_NOT_SUPPORTED;
[567]1323
[963]1324 // get full path stored in resource data
1325 rc = ph->fsphGetResourceData(pfi, &rsrcData, 0);
1326 if (rc != NO_ERROR || rsrcData.ulSize == 0 || rsrcData.pData == NULL)
[959]1327 {
[963]1328 debuglocal(pRes, 9, "NdpEAQuery: ph->fsphGetResourceData = %d/%d %08x\n", rc, fdata.ulSize, fdata.pData);
[959]1329 return ERROR_EAS_NOT_SUPPORTED;
1330 }
[567]1331
[959]1332 ENTER();
[5]1333
[963]1334 // build full path for file
1335 buildfullpath2(szFullPath, &rsrcData, pfi);
1336 debuglocal(pRes, 1, "NdpEAQuery szFullPath '%s', pfi->name '%s'\n",
1337 szFullPath, pfi->pszName);
1338
[964]1339 debuglocal(pRes, 9, "NdpEAQuery in [%p] <%s> %08x %d\n", pConn, szFullPath, pGEAList, pGEAList ? pGEAList->cbList : 0);
[145]1340
[959]1341 char *pchBuffer = (char *)malloc(cbBuffer);
1342 if (!pchBuffer)
1343 {
1344 LEAVE();
1345 return ERROR_NOT_ENOUGH_MEMORY;
1346 }
[533]1347
[959]1348 do {
[963]1349 rc = smbwrp_listea(pRes, pConn->cli, szFullPath, pchBuffer, cbBuffer);
[959]1350 pFEASrc = (FEALIST*) pchBuffer;
1351 if (rc)
1352 {
1353 switch (rc)
1354 {
1355 case ERROR_FILE_NOT_FOUND :
1356 case ERROR_PATH_NOT_FOUND :
1357 pFEAList->cbList = sizeof(pFEAList->cbList);
1358 rc = NO_ERROR;
1359 break;
1360 case ERROR_BUFFER_OVERFLOW :
1361 pFEAList->cbList = pFEASrc->cbList;
1362 break;
1363 default :
1364 rc = ERROR_EAS_NOT_SUPPORTED;
1365 }
1366 }
1367 else
[960]1368 rc = buildFEALIST(pRes, (FEALIST *)pFEASrc, pGEAList, pFEAList);
[959]1369 } while (0);
1370
1371 free(pchBuffer);
[960]1372 debuglocal(pRes, 9, "NdpEAQuery <%s> %d %d %d\n", pfi->pszName, rc, pFEASrc->cbList, pFEAList->cbList);
[959]1373
1374 LEAVE();
1375 return rc;
[5]1376}
1377
1378int APIENTRY NdpEASet (HCONNECTION conn, FEALIST *pFEAList, NDFILEINFOL *pfi)
1379{
[959]1380 Connection *pConn = (Connection *)conn;
1381 Resource *pRes = pConn->pRes;
1382 int rc = 0;
1383 NDDATABUF fdata = {0};
[963]1384 NDDATABUF rsrcData = {0};
1385 char szFullPath[CCHMAXPATH+1];
[5]1386
[960]1387 debuglocal(pRes, 9, "NdpEASet in [%p]\n", pConn);
[5]1388
[959]1389 if (!pfi || !pfi->pszName)
1390 return ERROR_EAS_NOT_SUPPORTED;
[5]1391
[959]1392 if (!pRes->easupport)
1393 return ERROR_EAS_NOT_SUPPORTED;
[567]1394
[963]1395 // get full path stored in resource data
1396 rc = ph->fsphGetResourceData(pfi, &rsrcData, 0);
1397 if (rc != NO_ERROR || rsrcData.ulSize == 0 || rsrcData.pData == NULL)
[959]1398 {
[963]1399 debuglocal(pRes, 9, "NdpEASet: ph->fsphGetResourceData = %d/%d %08x\n", rc, fdata.ulSize, fdata.pData);
[959]1400 return ERROR_EAS_NOT_SUPPORTED;
1401 }
[963]1402 // build full path for file
1403 buildfullpath2(szFullPath, &rsrcData, pfi);
1404 debuglocal(pRes, 9, "NdpEASet szFullPath '%s', pfi->name '%s'\n",
1405 szFullPath, pfi->pszName);
[5]1406
[963]1407 rc = helperEASet(pRes, pConn->cli, pFEAList, szFullPath);
[960]1408 debuglocal(pRes, 9, "NdpEASet %d\n", rc);
[959]1409 return rc;
[5]1410}
1411
1412int APIENTRY NdpEASize (HCONNECTION conn, NDFILEINFOL *pfi, ULONG *pulEASize)
1413{
[959]1414 Connection *pConn = (Connection *)conn;
1415 Resource *pRes = pConn->pRes;
1416 int rc = 0;
1417 FEALIST * pfealist;
1418 NDDATABUF fdata = {0};
1419 const int cbBuffer = 64*1024;
[963]1420 NDDATABUF rsrcData = {0};
1421 char szFullPath[CCHMAXPATH+1];
[5]1422
[959]1423 if (!pfi || !pulEASize)
1424 return ERROR_EAS_NOT_SUPPORTED;
[818]1425
[959]1426 if (!pRes->easupport)
1427 return ERROR_EAS_NOT_SUPPORTED;
[533]1428
[963]1429 // get full path stored in resource data
1430 rc = ph->fsphGetResourceData(pfi, &rsrcData, 0);
1431 if (rc != NO_ERROR || rsrcData.ulSize == 0 || rsrcData.pData == NULL)
[959]1432 {
[963]1433 debuglocal(pRes, 9, "NdpEASize: ph->fsphGetResourceData = %d/%d %08x\n", rc, fdata.ulSize, fdata.pData);
[959]1434 return ERROR_EAS_NOT_SUPPORTED;
1435 }
[567]1436
[959]1437 ENTER();
[5]1438
[963]1439 // build full path for file
1440 buildfullpath2(szFullPath, &rsrcData, pfi);
1441 debuglocal(pRes, 1, "NdpEASize szFullPath '%s', pfi->name '%s'\n",
1442 szFullPath, pfi->pszName);
[145]1443
[963]1444 // @todo restore use of easize from cache
[533]1445
[963]1446 debuglocal(pRes, 9, "NdpEASize in [%p] <%s> \n", pConn, szFullPath);
1447
[959]1448 char *pchBuffer = (char *)malloc(cbBuffer);
1449 if (!pchBuffer)
1450 {
1451 LEAVE();
1452 return ERROR_NOT_ENOUGH_MEMORY;
1453 }
1454
1455 do {
[963]1456 rc = smbwrp_listea(pRes, pConn->cli, szFullPath, pchBuffer, cbBuffer);
[959]1457 pfealist = (FEALIST*)pchBuffer;
1458 if (rc)
1459 {
1460 switch (rc)
1461 {
1462 case ERROR_FILE_NOT_FOUND :
1463 case ERROR_PATH_NOT_FOUND :
1464 pfealist->cbList = sizeof(pfealist->cbList); // Fall through */
1465 case ERROR_BUFFER_OVERFLOW :
1466 rc = NO_ERROR;
1467 break;
1468 default :
1469 rc = ERROR_EAS_NOT_SUPPORTED;
1470 }
1471 }
1472 *pulEASize = pfealist->cbList;
1473 } while (0);
1474
1475 free(pchBuffer);
[960]1476 debuglocal(pRes, 9, "NdpEASize <%s> %d %d\n", pfi->pszName, *pulEASize, rc);
[959]1477
1478 LEAVE();
1479 return rc;
[5]1480}
1481
1482int APIENTRY NdpSetCurrentDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szPath)
1483{
[959]1484 Connection *pConn = (Connection *)conn;
1485 Resource *pRes = pConn->pRes;
1486 int rc = 0;
1487 unsigned long action;
1488 char path[CCHMAXPATH+1] = {0};
[5]1489
[960]1490 debuglocal(pRes, 9, "NdpSetCurrentDir in [%p]\n", pConn);
[145]1491
[959]1492 ENTER();
[567]1493
[959]1494 do {
1495 rc = pathparser(pRes, pConn, szPath, path);
1496 if (rc)
1497 break;
[5]1498
[960]1499 rc = smbwrp_chdir(pRes, &pRes->srv, pConn->cli, path);
[959]1500 } while (0);
1501
[960]1502 debuglocal(pRes, 9, "NdpSetCurrentDir <%s> (%s) %d\n", szPath, path, rc);
[959]1503
1504 LEAVE();
1505 return rc;
[5]1506}
1507
1508int APIENTRY NdpCopy (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1509{
[960]1510 Connection *pConn = (Connection *)conn;
1511 Resource *pRes = pConn->pRes;
1512 debuglocal(pRes, 9, "NdpCopy <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
[959]1513 return ERROR_CANNOT_COPY;
[5]1514}
1515
1516int APIENTRY NdpCopy2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1517{
[960]1518 Connection *pConn = (Connection *)conn;
1519 Resource *pRes = pConn->pRes;
1520 debuglocal(pRes, 9, "NdpCopy2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
[959]1521 return ERROR_CANNOT_COPY;
[5]1522}
1523
1524int APIENTRY NdpForceDelete (HCONNECTION conn, NDFILEINFOL *pfi, char *szFile)
1525{
[959]1526 Connection *pConn = (Connection *)conn;
1527 Resource *pRes = pConn->pRes;
1528 int rc = 0;
1529 unsigned long action;
1530 char path[CCHMAXPATH+1] = {0};
[5]1531
[959]1532 ENTER();
[567]1533
[960]1534 debuglocal(pRes, 9, "NdpForceDelete in [%p]\n", pConn);
[145]1535
[966]1536 dircache_invalidate(pRes->pdc, szFile, 1);
[499]1537
[959]1538 do {
1539 rc = pathparser(pRes, pConn, szFile, path);
1540 if (rc)
1541 break;
[5]1542
[960]1543 rc = smbwrp_unlink(pRes, pConn->cli, path);
[959]1544 } while (0);
1545
[960]1546 debuglocal(pRes, 9, "NdpForceDelete <%s> (%s) %d\n", szFile, path, rc);
[959]1547
1548 LEAVE();
1549 return rc;
[5]1550}
1551
1552int APIENTRY NdpCreateDir (HCONNECTION conn, NDFILEINFOL *pfiparent, char *szDirName, FEALIST *pFEAList)
1553{
[959]1554 Connection *pConn = (Connection *)conn;
1555 Resource *pRes = pConn->pRes;
1556 int rc = 0;
1557 int rcEASet = 0;
1558 unsigned long action;
1559 char path[CCHMAXPATH+1] = {0};
[5]1560
[959]1561 ENTER();
[567]1562
[960]1563 debuglocal(pRes, 9, "NdpCreateDir in [%p]\n", pConn);
[145]1564
[966]1565 dircache_invalidate(pRes->pdc, szDirName, 1);
[499]1566
[959]1567 do {
1568 rc = pathparser(pRes, pConn, szDirName, path);
1569 if (rc)
1570 break;
[5]1571
[960]1572 rc = smbwrp_mkdir(pRes, pConn->cli, path);
[959]1573 } while (0);
[892]1574
[959]1575 LEAVE();
[892]1576
[959]1577 if (path && pRes->easupport)
[960]1578 rcEASet = helperEASet(pRes, pConn->cli, pFEAList, path);
[959]1579
[960]1580 debuglocal(pRes, 9, "NdpCreateDir <%s> (%s) rc=%d, EASupport=%s rc=%d\n", szDirName, path, rc, pRes->easupport?"yes":"no", rcEASet);
[959]1581
1582 return rc;
[5]1583}
1584
1585int APIENTRY NdpDeleteDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szDir)
1586{
[959]1587 Connection *pConn = (Connection *)conn;
1588 Resource *pRes = pConn->pRes;
1589 int rc = 0;
1590 unsigned long action;
1591 char path[CCHMAXPATH+1] = {0};
[5]1592
[959]1593 ENTER();
[567]1594
[960]1595 debuglocal(pRes, 9, "NdpDeleteDir in [%p]\n", pConn);
[145]1596
[966]1597 dircache_invalidate(pRes->pdc, szDir, 1);
[499]1598
[959]1599 do {
1600 rc = pathparser(pRes, pConn, szDir, path);
1601 if (rc)
1602 break;
[5]1603
[960]1604 rc = smbwrp_rmdir(pRes, pConn->cli, path);
[959]1605 } while (0);
1606
[960]1607 debuglocal(pRes, 9, "NdpDeleteDir <%s> (%s) %d\n", szDir, path, rc);
[959]1608
1609 LEAVE();
1610 return rc;
[5]1611}
1612
1613int APIENTRY NdpMove (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1614{
[959]1615 Connection *pConn = (Connection *)conn;
1616 Resource *pRes = pConn->pRes;
1617 int rc = 0;
1618 unsigned long action;
1619 char src[CCHMAXPATH+1] = {0};
1620 int l1, l2;
1621 char * p = szDst;
[5]1622
[959]1623 ENTER();
[567]1624
[960]1625 debuglocal(pRes, 9, "NdpMove in [%p] from <%s> to <%s>\n", pConn, szSrc, szDst);
[145]1626
[966]1627 dircache_invalidate(pRes->pdc, szSrc, 1);
1628 dircache_invalidate(pRes->pdc, szDst, 1);
[499]1629
[959]1630 do
1631 {
1632 rc = pathparser(pRes, pConn, szSrc, src);
1633 if (rc)
1634 break;
1635
1636 l1 = strlen(szSrc);
1637 l2 = strlen(src);
1638 if (l1 > l2)
1639 {
1640 if (ph->fsphStrNICmp(szSrc, szDst, l1 - l2))
1641 {
1642 /*
1643 * the file moved accross different shares or servers or
1644 * workgroups
1645 */
1646 rc = ERROR_WRITE_PROTECT;
1647 break;
1648 }
1649 p = szDst + l1 - l2 + 1;
1650 }
[960]1651 rc = smbwrp_rename(pRes, pConn->cli, src, p);
[959]1652 } while (0);
1653
[960]1654 debuglocal(pRes, 9, "NdpMove <%s> -> <%s> (%s) %d\n", szSrc, szDst, src, rc);
[959]1655
1656 LEAVE();
1657 return rc;
[5]1658}
1659
1660int APIENTRY NdpMove2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1661{
[960]1662 Connection *pConn = (Connection *)conn;
1663 Resource *pRes = pConn->pRes;
1664 debuglocal(pRes, 9, "NdpMove2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_WRITE_PROTECT);
[959]1665 return ERROR_WRITE_PROTECT;
[5]1666}
1667
1668
1669int APIENTRY NdpChangeCase (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1670{
[959]1671 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
[5]1672}
1673
1674int APIENTRY NdpRename (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1675{
[959]1676 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
[5]1677}
1678
1679int smbopen(Connection *pConn, char *szFileName, int flags, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1680{
[959]1681 Resource *pRes = pConn->pRes;
1682 unsigned long action;
1683 int rc = 0;
1684 char path[CCHMAXPATH+1] = {0};
[5]1685
[959]1686 ENTER();
[567]1687
[960]1688 debuglocal(pRes, 9, "smbopen in [%p] %d\n", pConn, pConn->file.fd);
[145]1689
[959]1690 if (flags & O_CREAT)
[966]1691 dircache_invalidate(pRes->pdc, szFileName, 1);
[5]1692
[959]1693 do {
1694 if (pConn->file.fd > 0)
1695 {
1696 rc = ERROR_TOO_MANY_OPEN_FILES;
1697 break;
1698 }
[5]1699
[959]1700 rc = pathparser(pRes, pConn, szFileName, path);
1701 if (rc)
1702 break;
1703
1704 strncpy(pConn->file.fullname, szFileName, sizeof(pConn->file.fullname) - 1);
1705 strncpy(pConn->file.fname, path, sizeof(pConn->file.fname) - 1);
1706 flags |= O_BINARY;
1707 switch (ulOpenMode & 3)
1708 {
1709 case OPEN_ACCESS_READONLY :
1710 flags |= O_RDONLY;
1711 break;
1712 case OPEN_ACCESS_WRITEONLY :
1713 flags |= O_WRONLY;
1714 break;
1715 case OPEN_ACCESS_READWRITE :
1716 flags |= O_RDWR;
1717 break;
1718 default :
1719 flags |= O_RDWR;
1720 }
1721
1722 pConn->file.openmode = flags;
1723 pConn->file.openattr = ulAttribute & 0x37;
1724 pConn->file.denymode = (ulOpenMode & 0x70) >> 4;
[960]1725 rc = smbwrp_open(pConn->pRes, pConn->cli, &pConn->file);
[959]1726 } while (0);
1727
[960]1728 debuglocal(pRes, 9, "smbopen <%s> (%s) %08x %08x %08x %d. file = %d\n", szFileName, path, flags, ulOpenMode, ulAttribute, rc, pConn->file.fd);
[959]1729 if (!rc && pFEAList)
1730 {
1731 int rc1 = NdpFileEASet((HCONNECTION)pConn, (NDFILEHANDLE)0, pFEAList);
[960]1732 debuglocal(pRes, 9, "smbopen NdpFileEASet %d. pFEAList->cbList %d\n", rc1, pFEAList->cbList);
[959]1733 }
1734
1735 LEAVE();
1736 return rc;
[5]1737}
1738
1739int APIENTRY NdpOpenReplace (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1740{
[959]1741 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
[5]1742}
1743
1744int APIENTRY NdpOpenReplaceL(HCONNECTION conn, NDFILEINFO *pfi, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1745{
[959]1746 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
[5]1747}
1748
1749int APIENTRY NdpOpenCreate (HCONNECTION conn, NDFILEINFOL *pfiparent, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1750{
[959]1751 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
[5]1752}
1753
1754int APIENTRY NdpOpenCreateL(HCONNECTION conn, NDFILEINFO *pfiparent, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1755{
[959]1756 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
[5]1757}
1758
1759int APIENTRY NdpOpenExisting (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulOpenMode, USHORT *pfNeedEA)
1760{
[959]1761 if (pfNeedEA)
1762 *pfNeedEA = 0; // wtf is this ?
1763 return smbopen((Connection *)conn, szFileName, 0, ulOpenMode, 0, NULL);
[5]1764}
1765
1766int APIENTRY NdpSetFileAttribute (HCONNECTION conn, NDFILEINFOL *pfi, char *szFileName, USHORT usAttr)
1767{
[959]1768 Connection *pConn = (Connection *)conn;
1769 Resource *pRes = pConn->pRes;
1770 int rc = 0;
1771 unsigned long action;
[145]1772
[959]1773 smbwrp_fileinfo finfo;
1774 char path[CCHMAXPATH+1] = {0};
[5]1775
[959]1776 ENTER();
[567]1777
[960]1778 debuglocal(pRes, 9, "NdpSetFileAttribute in [%p]\n", pConn);
[959]1779 do {
1780 rc = pathparser(pRes, pConn, szFileName, path);
1781 if (rc)
1782 break;
[5]1783
[959]1784 memset(&finfo, 0, sizeof(finfo));
1785 strncpy(finfo.fname, path, sizeof(finfo.fname) - 1);
1786 finfo.attr = usAttr & 0x37;
[960]1787 rc = smbwrp_setattr(pRes, pConn->cli, &finfo);
[959]1788 } while (0);
1789
[960]1790 debuglocal(pRes, 9, "NdpSetFileAttribute <%s> (%s) %04x %d\n", szFileName, path, usAttr, rc);
[959]1791
1792 LEAVE();
1793 return rc;
[5]1794}
1795
1796int APIENTRY NdpFlush (HRESOURCE resource)
1797{
[960]1798 Resource *pRes = (Resource *)resource;
1799 debuglocal(pRes, 9, "NdpFlush %d\n", ERROR_NOT_SUPPORTED);
[959]1800 return ERROR_NOT_SUPPORTED;
[5]1801}
1802
[959]1803/*
1804 * Called when a new thread will call the plugin.
1805 * Allows to do per thread init, like disable signals.
1806*/
[521]1807#define ND_PL_INIT_THREAD 0xFFFF0000
1808
[5]1809int APIENTRY NdpIOCTL (int type, HRESOURCE resource, char *path, int function, void *in, ULONG insize, PULONG poutlen)
1810{
[960]1811 Resource *pRes = (Resource *)resource;
[959]1812 if (function == ND_PL_INIT_THREAD)
1813 {
1814 smbwrp_initthread();
[960]1815 debuglocal(pRes, 9, "NdpIOCTL init thread\n");
[959]1816 return NO_ERROR;
1817 }
[521]1818
[960]1819 debuglocal(pRes, 9, "NdpIOCTL <%s> %d\n", path, function);
[111]1820
[959]1821 if (in && insize > 4096)
1822 {
1823 char out[4096];
1824 sprintf (out, "SAMBA IOCTL function = %d, parms [%s] insize = %d, *poutlen = %d", function, in, insize, *poutlen);
1825 *poutlen = strlen(out);
1826 strcpy (in, out);
1827 return NO_ERROR;
1828 }
[111]1829
[959]1830 return ERROR_NOT_SUPPORTED;
[5]1831}
1832
1833int APIENTRY NdpFileQueryInfo (HCONNECTION conn, NDFILEHANDLE handle, void *plist)
1834{
[959]1835 Connection *pConn = (Connection *)conn;
1836 Resource *pRes = pConn->pRes;
1837 int rc = 0;
1838 unsigned long action;
1839 smbwrp_fileinfo finfo;
[5]1840
[959]1841 ENTER();
[567]1842
[960]1843 debuglocal(pRes, 9, "NdpFileQueryInfo in [%p]\n", pConn);
[959]1844 do {
1845 if (pConn->file.fd < 0 || !*pConn->file.fname)
1846 {
1847 rc = ERROR_INVALID_HANDLE;
1848 break;
1849 }
1850 strncpy(finfo.fname, pConn->file.fname, sizeof(finfo.fname) - 1);
[960]1851 rc = smbwrp_fgetattr(pRes, pConn->cli, &pConn->file, &finfo);
[959]1852 if (!rc)
1853 {
1854 finfo.easize = -1;
[976]1855 addFindInfoL(pRes, plist, &finfo, 0, NULL);
[959]1856 }
1857 } while (0);
1858
[960]1859 debuglocal(pRes, 9, "NdpFileQueryInfo <%s> %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, rc);
[959]1860
1861 LEAVE();
1862 return rc;
[5]1863}
1864
1865int APIENTRY NdpFileEAQuery (HCONNECTION conn, NDFILEHANDLE handle, GEALIST *pGEAList, FEALIST *pFEAList)
1866{
[959]1867 Connection *pConn = (Connection *)conn;
1868 Resource *pRes = pConn->pRes;
1869 int rc = 0;
1870 unsigned long action;
1871 const int cbBuffer = 64*1024;
1872 FEALIST * pFEASrc;
[5]1873
[959]1874 if (!pFEAList)
1875 return ERROR_EAS_NOT_SUPPORTED;
1876 if (!pRes->easupport)
1877 return ERROR_EAS_NOT_SUPPORTED;
[5]1878
[960]1879 debuglocal(pRes, 9, "NdpFileEAQuery in [%p] <%s>/%d pGEAList=%08x\n", pConn, pConn->file.fname, pConn->file.fd, pGEAList);
[533]1880
[959]1881 char *pchBuffer = (char *)malloc(cbBuffer);
1882 if (!pchBuffer)
1883 return ERROR_NOT_ENOUGH_MEMORY;
[533]1884
[959]1885 ENTER();
[567]1886
[959]1887 do {
1888 if (pConn->file.fd < 0)
1889 {
1890 rc = ERROR_INVALID_HANDLE;
1891 break;
1892 }
[960]1893 rc = smbwrp_flistea(pRes, pConn->cli, &pConn->file, pchBuffer, cbBuffer);
[959]1894 pFEASrc = (FEALIST *)pchBuffer;
1895 if (rc)
1896 {
1897 switch (rc)
1898 {
1899 case ERROR_FILE_NOT_FOUND :
1900 case ERROR_PATH_NOT_FOUND :
1901 pFEAList->cbList = sizeof(pFEAList->cbList);
1902 rc = NO_ERROR;
1903 break;
1904 case ERROR_BUFFER_OVERFLOW :
1905 pFEAList->cbList = pFEASrc->cbList;
1906 break;
1907 default :
1908 rc = ERROR_EAS_NOT_SUPPORTED;
1909 }
1910 }
1911 else
[960]1912 rc = buildFEALIST(pRes, pFEASrc, pGEAList, pFEAList);
[959]1913
1914 } while (0);
1915
1916 free(pchBuffer);
[960]1917 debuglocal(pRes, 9, "NdpFileEAQuery out <%s>/%d pFEASrc->cbList=%d pFEAList->cbList=%d rc=%d\n", pConn->file.fname, pConn->file.fd, pFEASrc->cbList, pFEAList->cbList, rc);
[959]1918
1919 LEAVE();
1920 return rc;
[5]1921}
1922
1923int APIENTRY NdpFileEASet (HCONNECTION conn, NDFILEHANDLE handle, FEALIST *pFEAList)
1924{
[959]1925 Connection *pConn = (Connection *)conn;
1926 Resource *pRes = pConn->pRes;
1927 int rc = 0;
1928 unsigned long action;
[5]1929
[960]1930 debuglocal(pRes, 9, "NdpFileEASet in [%p]\n", pConn);
[5]1931
[959]1932 if (!pFEAList || pFEAList->cbList <= sizeof(long))
1933 return ERROR_EAS_NOT_SUPPORTED;
[5]1934
[959]1935 if (!pRes->easupport)
1936 return ERROR_EAS_NOT_SUPPORTED;
[567]1937
[959]1938 ENTER();
[145]1939
[959]1940 do {
1941 // got FEA there
1942 FEA * pfea;
1943 unsigned long done = sizeof(long);
1944 if (pConn->file.fd < 0)
1945 {
1946 rc = ERROR_INVALID_HANDLE;
1947 break;
1948 }
[5]1949
[959]1950 pfea = pFEAList->list;
1951 while (done < pFEAList->cbList)
1952 {
[960]1953 rc = smbwrp_fsetea(pRes, pConn->cli, &pConn->file, (char *)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
[959]1954 if (rc)
1955 break;
1956
1957 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
1958 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1959 }
1960
1961 } while (0);
1962
[960]1963 debuglocal(pRes, 9, "NdpFileEASet %d\n", rc);
[959]1964
1965 LEAVE();
1966 return rc;
[5]1967}
1968
1969int APIENTRY NdpFileEASize (HCONNECTION conn, NDFILEHANDLE handle, ULONG *pulEASize)
1970{
[959]1971 Connection *pConn = (Connection *)conn;
1972 Resource *pRes = pConn->pRes;
1973 int rc = 0;
1974 unsigned long action;
1975 char path[CCHMAXPATH+1] = {0};
1976 FEALIST * pFEAList;
1977 const int cbBuffer = 64*1024;
[5]1978
[959]1979 if (!pulEASize)
1980 return ERROR_EAS_NOT_SUPPORTED;
[5]1981
[959]1982 if (!pRes->easupport)
1983 return ERROR_EAS_NOT_SUPPORTED;
[533]1984
[960]1985 debuglocal(pRes, 9, "NdpFileEASize in [%p] <%s>/%d \n", pConn, pConn->file.fname, pConn->file.fd);
[533]1986
[959]1987 char *pchBuffer = (char *)malloc(cbBuffer);
1988 if (!pchBuffer)
1989 return ERROR_NOT_ENOUGH_MEMORY;
[567]1990
[959]1991 ENTER();
1992
1993 do {
1994 if (pConn->file.fd < 0)
1995 {
1996 rc = ERROR_INVALID_HANDLE;
1997 break;
1998 }
[960]1999 rc = smbwrp_flistea(pRes, pConn->cli, &pConn->file, pchBuffer, cbBuffer);
[959]2000 pFEAList = (FEALIST*)pchBuffer;
2001 if (rc)
2002 {
2003 switch (rc)
2004 {
2005 case ERROR_FILE_NOT_FOUND :
2006 case ERROR_PATH_NOT_FOUND :
2007 pFEAList->cbList = sizeof(pFEAList->cbList);// Fall through */
2008 case ERROR_BUFFER_OVERFLOW :
2009 rc = NO_ERROR;
2010 break;
2011 default :
2012 rc = ERROR_EAS_NOT_SUPPORTED;
2013 }
2014 }
2015 *pulEASize = pFEAList->cbList;
2016 } while (0);
2017
2018 free(pchBuffer);
[960]2019 debuglocal(pRes, 9, "NdpFileEASize %d %d\n", *pulEASize, rc);
[959]2020
2021 LEAVE();
2022 return rc;
[5]2023}
2024
2025int APIENTRY NdpFileSetInfo (HCONNECTION conn, NDFILEHANDLE handle, NDFILEINFOL *pfi)
2026{
[959]2027 Connection *pConn = (Connection *)conn;
2028 Resource *pRes = pConn->pRes;
2029 int rc = 0;
2030 unsigned long action, attrFile;
[5]2031
[959]2032 ENTER();
[567]2033
[960]2034 debuglocal(pRes, 9, "NdpFileSetInfo in [%p]\n", pConn);
[521]2035
[959]2036 // delete the dir cache
[966]2037 dircache_invalidate(pRes->pdc, pConn->file.fullname, 1);
[521]2038
[959]2039 do {
2040 if (pConn->file.fd < 0 || !*pConn->file.fname)
2041 {
2042 rc = ERROR_INVALID_HANDLE;
2043 break;
2044 }
2045 attrFile = pfi->stat.attrFile;
2046 // deferred setinfo - on closing the file
2047 pConn->file.openattr = attrFile;
[960]2048 fsphDosDateToUnixTime(pRes, pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, &(pConn->file.mtime));
2049 fsphDosDateToUnixTime(pRes, pfi->stat.fdateCreation, pfi->stat.ftimeCreation, &(pConn->file.ctime));
[959]2050 pConn->file.updatetime = 2;
[960]2051 debuglocal(pRes, 9, "NdpFileSetInfo mtime %d\n", pConn->file.mtime);
[959]2052 } while (0);
2053
[960]2054 debuglocal(pRes, 9, "NdpFileSetInfo <%s> %08x %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, attrFile, rc);
[959]2055
2056 LEAVE();
2057 return NO_ERROR;
[5]2058}
2059
2060int APIENTRY NdpFileSetFilePtrL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llOffset, ULONG ulMethod, LONGLONG *pllActual)
2061{
[959]2062 Connection *pConn = (Connection *)conn;
2063 Resource *pRes = pConn->pRes;
2064 int rc = 0;
2065 unsigned long action;
[5]2066
[959]2067 ENTER();
[567]2068
[960]2069 debuglocal(pRes, 9, "NdpFileSetFilePtrL in [%p]\n", pConn);
[145]2070
[959]2071 do {
2072 if (pConn->file.fd < 0)
2073 {
2074 rc = ERROR_INVALID_HANDLE;
2075 break;
2076 }
[5]2077
[960]2078 rc = smbwrp_lseek(pRes, pConn->cli, &pConn->file, ulMethod, llOffset);
[959]2079 if (!rc)
2080 *pllActual = pConn->file.offset;
[145]2081
[959]2082 } while (0);
2083
[960]2084 debuglocal(pRes, 9, "NdpFileSetFilePtrL <%s> %lld %lu %lld %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llOffset, ulMethod, *pllActual, rc);
[959]2085
2086 LEAVE();
2087 return rc;
[5]2088}
2089
2090int APIENTRY NdpFileSetFilePtr (HCONNECTION conn, NDFILEHANDLE handle, LONG lOffset, ULONG ulMethod, ULONG *pulActual)
2091{
[960]2092 Connection *pConn = (Connection *)conn;
[959]2093 LONGLONG llActual;
2094 int rc = NdpFileSetFilePtrL(conn, handle, lOffset, ulMethod, &llActual);
2095 *pulActual = llActual & 0xFFFFFFFF;
[960]2096 debuglocal(pConn->pRes, 9, "NdpFileSetFilePtr %ld %lu %ld %d\n", lOffset, ulMethod, *pulActual, rc);
[959]2097 return rc;
[5]2098}
2099
2100int APIENTRY NdpFileClose (HCONNECTION conn, NDFILEHANDLE handle)
2101{
[959]2102 Connection *pConn = (Connection *)conn;
2103 Resource *pRes = pConn->pRes;
2104 int rc = 0;
2105 unsigned long action;
[5]2106
[959]2107 ENTER();
[567]2108
[960]2109 debuglocal(pRes, 9, "NdpFileClose in [%p] %d <%s>\n", pConn, pConn->file.fd, pConn->file.fd < 0 ? "!null!" : pConn->file.fname);
[5]2110
[959]2111 do {
2112 if (pConn->file.fd < 0)
2113 {
2114 rc = ERROR_INVALID_HANDLE;
2115 break;
2116 }
[5]2117
[960]2118 rc = smbwrp_close(pRes, pConn->cli, &pConn->file);
[145]2119
[959]2120 } while (0);
[145]2121
[960]2122 debuglocal(pRes, 9, "NdpFileClose %d %d\n", pConn->file.fd, rc);
[959]2123 pConn->file.fd = -1;
2124
2125 LEAVE();
2126 return rc;
[5]2127}
2128
2129int APIENTRY NdpFileCommit (HCONNECTION conn, NDFILEHANDLE handle)
2130{
[960]2131 Connection *pConn = (Connection *)conn;
2132 debuglocal(pConn->pRes, 9, "NdpFileCommit %d\n", NO_ERROR);
[959]2133 return NO_ERROR;
[5]2134}
2135
2136int APIENTRY NdpFileNewSize (HCONNECTION conn, NDFILEHANDLE handle, ULONG ulLen)
2137{
[960]2138 Connection *pConn = (Connection *)conn;
[959]2139 int rc = NdpFileNewSizeL(conn, handle, ulLen);
[960]2140 debuglocal(pConn->pRes, 9, "NdpFileNewSize %ld %d\n", ulLen, rc);
[959]2141 return rc;
[5]2142}
2143
2144int APIENTRY NdpFileNewSizeL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llLen)
2145{
[959]2146 Connection *pConn = (Connection *)conn;
2147 Resource *pRes = pConn->pRes;
2148 int rc = 0;
2149 unsigned long action;
[5]2150
[959]2151 ENTER();
[567]2152
[960]2153 debuglocal(pRes, 9, "NdpFileNewSizeL in [%p]\n", pConn);
[145]2154
[959]2155 do {
2156 if (pConn->file.fd < 0)
2157 {
2158 rc = ERROR_INVALID_HANDLE;
2159 break;
2160 }
[5]2161
[960]2162 rc = smbwrp_setfilesize(pRes, pConn->cli, &pConn->file, llLen);
[5]2163
[959]2164 } while (0);
2165
[960]2166 debuglocal(pRes, 9, "NdpFileNewSizeL <%s> %lld %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llLen, rc);
[959]2167
2168 LEAVE();
2169 return rc;
[5]2170}
2171
[508]2172#define NDPSMB_READ_MAX_SIZE (65536 - 4096)
2173
[5]2174int APIENTRY NdpFileRead (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulRead, ULONG *pulActual)
2175{
[959]2176 Connection *pConn = (Connection *)conn;
2177 Resource *pRes = pConn->pRes;
2178 int rc = 0;
2179 unsigned long done = 0;
2180 unsigned long onedone;
2181 unsigned long action;
2182 ULONG ulReadCompleted = 0;
[5]2183
[959]2184 ENTER();
[567]2185
[960]2186 debuglocal(pRes, 9, "NdpFileRead in [%p]\n", pConn);
[5]2187
[959]2188 do {
2189 if (pConn->file.fd < 0)
2190 {
2191 rc = ERROR_INVALID_HANDLE;
2192 break;
2193 }
[5]2194
[959]2195 while (ulReadCompleted < ulRead)
2196 {
2197 ULONG ulActual;
2198 ULONG ulToRead = ulRead - ulReadCompleted;
[960]2199 debuglocal(pRes, 9, "NdpFileRead completed %d, to read %d\n", ulReadCompleted, ulToRead);
[508]2200
[959]2201 if (ulToRead > NDPSMB_READ_MAX_SIZE)
2202 ulToRead = NDPSMB_READ_MAX_SIZE;
[508]2203
[960]2204 rc = smbwrp_read(pRes, pConn->cli, &pConn->file, (char *)pBuffer + ulReadCompleted, ulToRead, &ulActual);
[959]2205 if (ulActual == 0 || rc != NO_ERROR)
2206 break;
[508]2207
[959]2208 ulReadCompleted += ulActual;
2209 }
2210 } while (0);
2211
2212 if (ulReadCompleted > 0)
2213 rc = NO_ERROR; // Still were able to read some data.
2214
2215 if (rc == NO_ERROR)
2216 *pulActual = ulReadCompleted;
2217
[960]2218 debuglocal(pRes, 9, "NdpFileRead <%s> %lu %lu %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead, *pulActual, rc);
[959]2219
2220 LEAVE();
2221 return rc;
[5]2222}
2223
2224int APIENTRY NdpFileWrite (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulWrite, ULONG *pulActual)
2225{
[959]2226 Connection *pConn = (Connection *)conn;
2227 Resource *pRes = pConn->pRes;
2228 int rc = 0;
2229 unsigned long done = 0;
2230 unsigned long onedone;
2231 unsigned long action;
[5]2232
[959]2233 ENTER();
[567]2234
[960]2235 debuglocal(pRes, 9, "NdpFileWrite in [%p]\n", pConn);
[145]2236
[959]2237 /*
2238 * delete the dir cache
2239 * This was moved from NdpFileClose() becasue if there are a lot files
2240 * in the tree, all are reread. The problem when moved to here is, that
2241 * the last accessed time is not refreshed. If this is needed,
2242 * a new function needs to be done to update only one file in the cache
2243 */
[966]2244 dircache_invalidate(pRes->pdc, pConn->file.fullname, 1);
[514]2245
[959]2246 do {
2247 if (pConn->file.fd < 0)
2248 {
2249 rc = ERROR_INVALID_HANDLE;
2250 break;
2251 }
[960]2252 rc = smbwrp_write(pRes, pConn->cli, &pConn->file, pBuffer, ulWrite, pulActual);
[5]2253
[959]2254 } while (0);
2255
[960]2256 debuglocal(pRes, 9, "NdpFileWrite <%s> %lu %lu %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulWrite, *pulActual, rc);
[959]2257
2258 LEAVE();
2259 return rc;
[5]2260}
Note: See TracBrowser for help on using the repository browser.