source: branches/client-2.1/src/ndpsmb.c@ 802

Last change on this file since 802 was 799, checked in by Silvan Scherrer, 12 years ago

Samba Client 2.1: remove dead debug code

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