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

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

Apply changes from changeset 892 to client-3.0 branch

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