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

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

Another use of smbwrp_echo

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