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

Last change on this file was 1014, checked in by Paul Smedley, 8 years ago

Update rc codes for EA Set/query fucntions, fixes some wps copy issues to shares that don't support EA, but the share has EA support enabled

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