source: branches/client-3.0/src/ndpsmb.c@ 930

Last change on this file since 930 was 930, checked in by Paul Smedley, 9 years ago

Add support to enable Kerberos support, and make the plugin connect using kerberos when it's enabled

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