source: trunk/client/src/ndpsmb.c@ 567

Last change on this file since 567 was 567, checked in by Silvan Scherrer, 14 years ago

Samba Client 2.1: crash fix

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