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

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

samba client: adjust copyright

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