source: trunk/client/src/ndpsmb.c@ 959

Last change on this file since 959 was 959, checked in by Silvan Scherrer, 9 years ago

samba client: remove tabs in source and beautify it completely

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