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

Last change on this file since 727 was 727, checked in by Silvan Scherrer, 13 years ago

Samba Client 2.1: prevent crash like in ticket 204

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