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

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

samba client 2.1: GA

  • 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 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 unsigned long action;
950 char path[CCHMAXPATH+1] = {0};
951
952 ENTER();
953
954 debuglocal(9,"NdpQueryPathInfo in [%p] <%s>\n", pConn, szPath);
955
956 // is wildcard is specified, we suppose parent dir exist, so exit immediately
957 if (ph->fsphStrChr(szPath, '*') || ph->fsphStrChr(szPath, '?'))
958 {
959 LEAVE();
960 return ERROR_FILE_NOT_FOUND;
961 }
962
963
964 do {
965 /* First check if there is information in the directory cache. */
966 unsigned long ulAge = 0;
967 if (dircache_find_path(pRes->pdc, szPath, &finfo, &ulAge))
968 {
969 if (ulAge <= 15) /* @todo configurable. */
970 {
971 rc = NO_ERROR;
972 finfo.easize = -1;
973 getfindinfoL(pConn, plist, &finfo, 0, NULL);
974 break;
975 }
976 }
977
978 rc = pathparser(pRes, pConn, szPath, path);
979 debuglocal(9,"NdpQueryPathInfo pathparser for <%s> rc=%d\n", path, rc);
980 switch (rc)
981 {
982 case NO_ERROR :
983 case ERROR_FILE_NOT_FOUND:
984 case ERROR_PATH_NOT_FOUND:
985 case ERROR_ACCESS_DENIED:
986 case ERROR_INVALID_PARAMETER:
987 {
988 break;
989 }
990 default :
991 {
992 rc = ERROR_PATH_NOT_FOUND;
993 }
994 }
995 if (rc)
996 {
997 break;
998 }
999 strncpy(finfo.fname, path, sizeof(finfo.fname) - 1);
1000 debuglocal(9,"NdpQueryPathInfo smbwrp_getattr for <%s>\n", path);
1001 rc = smbwrp_getattr( &pRes->srv, pConn->cli, &finfo);
1002 if (rc)
1003 {
1004 // remote server not available for first time?
1005 if (rc == ERROR_REM_NOT_LIST)
1006 {
1007 // free current cli resources
1008 smbwrp_disconnect( pRes, pConn->cli);
1009 // reconnect
1010 smbwrp_connect( pRes, &pConn->cli);
1011 // try file list again
1012 rc = smbwrp_getattr( &pRes->srv, pConn->cli, &finfo);
1013 debuglocal(9,"NdpQueryPathInfo remote connection lost, rc = %d\n", rc);
1014 }
1015 switch (rc)
1016 {
1017 case NO_ERROR :
1018 case ERROR_FILE_NOT_FOUND:
1019 case ERROR_PATH_NOT_FOUND:
1020 case ERROR_ACCESS_DENIED:
1021 case ERROR_INVALID_PARAMETER:
1022 case ERROR_REM_NOT_LIST:
1023 break;
1024 default :
1025 {
1026 rc = ERROR_PATH_NOT_FOUND;
1027 }
1028 }
1029 }
1030
1031 if (rc == NO_ERROR) {
1032 finfo.easize = -1;
1033 getfindinfoL(pConn, plist, &finfo, 0, NULL);
1034 }
1035 else if (rc == ERROR_FILE_NOT_FOUND)
1036 {
1037 // now try the upper path
1038 char * p = ph->fsphStrRChr(finfo.fname, '\\');
1039 if (p && p > finfo.fname)
1040 {
1041 *p = 0;
1042 rc = smbwrp_getattr( &pRes->srv, pConn->cli, &finfo);
1043 debuglocal(9,"NdpQueryPathInfo upper path in <%s>, rc = %d\n", finfo.fname, rc);
1044 if (rc == NO_ERROR)
1045 {
1046 rc = (finfo.attr & FILE_DIRECTORY) !=0 ?
1047 ERROR_FILE_NOT_FOUND:
1048 ERROR_PATH_NOT_FOUND;
1049 }
1050 else if (rc != ERROR_REM_NOT_LIST)
1051 {
1052 rc = ERROR_PATH_NOT_FOUND;
1053 }
1054 }
1055 }
1056 } while (0);
1057 debuglocal(9,"NdpQueryPathInfo <%s> (%s) %d\n", szPath, path, rc);
1058
1059 LEAVE();
1060 return rc;
1061}
1062
1063// -------------------------------------------------------------
1064
1065int APIENTRY NdpFindStart (HCONNECTION conn, void *plist, NDFILEINFOL *pfiparent, char *szPath, ULONG ulAttribute)
1066{
1067 Connection *pConn = (Connection *)conn;
1068 Resource *pRes = pConn->pRes;
1069 int rc = NO_ERROR, count = 0;
1070 unsigned long action;
1071 char *mask = "*";
1072 char dir[CCHMAXPATH+1] = {0};
1073 char path[CCHMAXPATH+1] = {0};
1074 smbwrp_fileinfo * data;
1075 NDPATHELEMENT *pel = ph->fsphNameElem(0);
1076 filelist_state state;
1077 char * p;
1078
1079 ENTER();
1080
1081 debug_printf("NdpFindStart in [%p]\n", pConn);
1082
1083 strncpy(dir, szPath, sizeof(dir) - 1);
1084 if (pel)
1085 {
1086 mask = pel->name;
1087 dir[strlen(szPath) - pel->length] = 0;
1088 }
1089 action = strlen(dir) - 1;
1090 if (dir[action] == '\\')
1091 {
1092 dir[action] = 0;
1093 }
1094 rc = pathparser(pRes, pConn, dir, path);
1095 if (rc)
1096 {
1097 return rc;
1098 }
1099 action = strlen(path) - 1;
1100 if (path[action] != '\\')
1101 {
1102 strncat(path, "\\", sizeof(path) - 1);
1103 }
1104 strcpy(dir, path);
1105 strncat(path, mask, sizeof(path) - 1);
1106
1107 // this structure will be used by libsmb callbacks, so we store here all we need
1108 // to fill netdrive structures
1109 state.pConn = pConn;
1110 state.plist = plist;
1111 state.ulAttribute = ulAttribute;
1112 strcpy( state.dir, dir);
1113 strcpy( state.dir_mask, mask);
1114 strcpy( state.mask, path);
1115 state.fullpath = szPath;
1116 /* This plugin always reads a complete directory listing and filters results
1117 * using actual mask (state.dir_mask) in getfindinfoL.
1118 * May be this was a workaround for some server bug.
1119 * If this will be changed, then directory listing cache must be changed too,
1120 * and must remember the mask, which was used to obtain a listing.
1121 * Now the directory cache saves complete directory listings and then uses them to find
1122 * information about single files.
1123 * However, with a directory cache, it is probably faster to get a full listing and
1124 * then use it to obtain info about separate files than to perform a network
1125 * list query operation using actual wild cards for each file. Some application,
1126 * for example OpenOffice, do this.
1127 */
1128 p = getlastslash(state.mask);
1129 if (p)
1130 {
1131 *(p + 1) = '*';
1132 *(p + 2) = 0;
1133 }
1134 else
1135 {
1136 strcpy(state.mask, "\\*");
1137 }
1138 debuglocal(9,"NdpFindStart: dir [%s], dir_mask [%s], mask [%s], szPath [%s]\n",
1139 state.dir, state.dir_mask, state.mask, state.fullpath);
1140 rc = smbwrp_filelist( &pRes->srv, pConn->cli, &state);
1141 // we need to handle reconnection also here, because NdpQueryPathInfo
1142 // could be called with '*' and exit then immediately (without calling libsmb)
1143 if (rc == ERROR_REM_NOT_LIST)
1144 {
1145 // free current cli resources
1146 smbwrp_disconnect( pRes, pConn->cli);
1147 // reconnect
1148 smbwrp_connect( pRes, &pConn->cli);
1149 // try file list again next loop
1150 rc = smbwrp_filelist( &pRes->srv, pConn->cli, &state);
1151 debuglocal(9,"NdpFindStart remote connection lost, rc = %d\n", rc);
1152 }
1153
1154 debuglocal(9,"NdpFindStart <%s> (%s) cnt %d %d\n", szPath, path, count, rc);
1155 LEAVE();
1156 return rc;
1157}
1158
1159int APIENTRY NdpDeletePathInfo (HRESOURCE resource, NDFILEINFOL *pfi)
1160{
1161// debuglocal(9,"NdpDeletePathInfo %d\n", 0);
1162 return NO_ERROR;
1163}
1164
1165int APIENTRY NdpRefresh (HCONNECTION conn, char *path, int tree)
1166{
1167 debuglocal(9,"NdpRefresh <%s> %d\n", path, 0);
1168 return NO_ERROR;
1169}
1170
1171int APIENTRY NdpDiscardResourceData (HRESOURCE resource, NDDATABUF *pdatabuf)
1172{
1173 // The plugin do not have to deallocate anything
1174 // because resource data did not contain any pointers
1175 // to plugins data.
1176 // Data stored by fsphSetResourceData will be
1177 // deallocated by NetDrive.
1178
1179 debuglocal(9,"NdpDicardresourceData %d\n", 0);
1180 return NO_ERROR;
1181}
1182
1183int APIENTRY NdpSetPathInfo (HCONNECTION conn, NDFILEINFOL *pfi, char *szPathName)
1184{
1185 Connection *pConn = (Connection *)conn;
1186 Resource *pRes = pConn->pRes;
1187 int rc = 0;
1188 unsigned long action;
1189 char path[CCHMAXPATH+1] = {0};
1190 smbwrp_fileinfo finfo;
1191
1192 ENTER();
1193
1194 debug_printf("NdpSetPathInfo in [%p]\n", pConn);
1195
1196 // delete the dir cache
1197 dircache_invalidate(szPathName, pRes->pdc, 1);
1198
1199 do {
1200 rc = pathparser(pRes, pConn, szPathName, path);
1201 if (rc)
1202 {
1203 break;
1204 }
1205
1206 memset(&finfo, 0, sizeof(finfo));
1207
1208 strncpy(finfo.fname, path, sizeof(finfo.fname) - 1);
1209 fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, &(finfo.mtime));
1210 finfo.attr = pfi->stat.attrFile & 0x37;
1211 rc = smbwrp_setattr(pConn->cli, &finfo);
1212 } while (0);
1213 debuglocal(9,"NdpSetPathInfo <%s> (%s) %d\n", szPathName, path, rc);
1214 LEAVE();
1215 return rc;
1216}
1217
1218int buildFEALIST(FEALIST *pFEASrc, GEALIST *pGEAList, FEALIST *pFEAList)
1219{
1220 int rc = 0;
1221 FEA * pfea;
1222 FEA * pfeadest;
1223 unsigned long size, done = sizeof(pFEAList->cbList), dsize, ddone = sizeof(pFEAList->cbList);
1224
1225 size = pFEASrc->cbList;
1226 pfea = pFEASrc->list;
1227 pfeadest = pFEAList->list;
1228 dsize = pFEAList->cbList;
1229//debuglocal(9,"buildFEALIST in destsize %d srcsize %d pGEAList=%08x pGEAList->cbList=%d\n", dsize, ddone, size, pGEAList, pGEAList ? pGEAList->cbList : 0);
1230 while (done < size)
1231 {
1232 char * name = (char *)(pfea + 1);
1233 int insert = 1;
1234 if (pGEAList && pGEAList->cbList > sizeof(pGEAList->cbList))
1235 {
1236 GEA * pgea = pGEAList->list;
1237 unsigned long size = pGEAList->cbList - sizeof(pGEAList->cbList), done = 0;
1238 insert = 0;
1239 while (done < size)
1240 {
1241//debuglocal(9,"comp <%s> <%s>\n", name, pgea->szName);
1242 if (!ph->fsphStrNCmp(name, pgea->szName, pgea->cbName))
1243 {
1244 insert = 1;
1245 break;
1246 }
1247 done += pgea->cbName + 2;
1248 pgea = (GEA *)((char *)pgea + pgea->cbName + 2);
1249 }
1250 }
1251 if (insert)
1252 {
1253 ddone += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1254 if (ddone <= dsize)
1255 {
1256 pfeadest->cbName = pfea->cbName;
1257 pfeadest->cbValue = pfea->cbValue;
1258 pfeadest->fEA = 0;
1259 strcpy((char *)(pfeadest + 1), name);
1260 memcpy((char *)(pfeadest + 1) + pfea->cbName + 1, (char *)(pfea + 1) + pfea->cbName + 1, pfea->cbValue);
1261 pfeadest = (FEA *)((char *)pFEAList + ddone);
1262 }
1263 }
1264 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1265//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);
1266 pfea = (FEA *)((char *)pFEASrc + done);
1267 }
1268 pFEAList->cbList = ddone;
1269 if (ddone > dsize && dsize > sizeof(pFEAList->cbList))
1270 {
1271 rc = ERROR_BUFFER_OVERFLOW;
1272 }
1273 debuglocal(9,"buildFEALIST rc=%d destsize=%d destdone=%d srcsize=%d pGEAList=%08x\n", rc, dsize, ddone, size, pGEAList);
1274 return rc;
1275}
1276
1277int APIENTRY NdpEAQuery (HCONNECTION conn, GEALIST *pGEAList, NDFILEINFOL *pfi, FEALIST *pFEAList)
1278{
1279 Connection *pConn = (Connection *)conn;
1280 Resource *pRes = pConn->pRes;
1281 int rc = 0;
1282 unsigned long action;
1283 char * path = NULL;
1284 FEALIST * pFEASrc;
1285 NDDATABUF fdata = {0};
1286 smbwrp_fileinfo *finfo;
1287 const int cbBuffer = 64*1024;
1288
1289 if (!pfi || !pfi->pszName || !pFEAList)
1290 {
1291 return ERROR_EAS_NOT_SUPPORTED;
1292 }
1293 if (!pRes->easupport)
1294 {
1295 return ERROR_EAS_NOT_SUPPORTED;
1296 }
1297
1298 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1299 if (rc || !fdata.ulSize || !fdata.pData)
1300 {
1301 debuglocal(9,"NdpEAQuery: ph->fsphGetFileInfoData = %d/%d %08x\n", rc, fdata.ulSize, fdata.pData);
1302 return ERROR_EAS_NOT_SUPPORTED;
1303 }
1304
1305 ENTER();
1306
1307 finfo = (smbwrp_fileinfo *)fdata.pData;
1308 path = finfo->fname;
1309
1310 debuglocal(9,"NdpEAQuery in [%p] <%s> %08x %d\n", pConn, path, pGEAList, pGEAList ? pGEAList->cbList : 0);
1311
1312 char *pchBuffer = (char *)malloc(cbBuffer);
1313 if (!pchBuffer)
1314 {
1315 LEAVE();
1316 return ERROR_NOT_ENOUGH_MEMORY;
1317 }
1318
1319 do {
1320 rc = smbwrp_listea( pConn->cli, path, pchBuffer, cbBuffer);
1321 pFEASrc = (FEALIST*) pchBuffer;
1322 if (rc)
1323 {
1324 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1325 switch (rc)
1326 {
1327 case ERROR_FILE_NOT_FOUND :
1328 case ERROR_PATH_NOT_FOUND :
1329 {
1330 pFEAList->cbList = sizeof(pFEAList->cbList);
1331 rc = NO_ERROR;
1332 } break;
1333 case ERROR_BUFFER_OVERFLOW :
1334 {
1335 pFEAList->cbList = pFEASrc->cbList;
1336 } break;
1337 default :
1338 {
1339 rc = ERROR_EAS_NOT_SUPPORTED;
1340 }
1341 }
1342 }
1343 else
1344 {
1345 rc = buildFEALIST((FEALIST *)pFEASrc, pGEAList, pFEAList);
1346 }
1347 } while (0);
1348 free(pchBuffer);
1349 debuglocal(9,"NdpEAQuery <%s> %d %d %d\n", pfi->pszName, rc, pFEASrc->cbList, pFEAList->cbList);
1350 LEAVE();
1351 return rc;
1352}
1353
1354int APIENTRY NdpEASet (HCONNECTION conn, FEALIST *pFEAList, NDFILEINFOL *pfi)
1355{
1356 Connection *pConn = (Connection *)conn;
1357 Resource *pRes = pConn->pRes;
1358 int rc = 0;
1359 char * path;
1360 unsigned long action;
1361 NDDATABUF fdata = {0};
1362 smbwrp_fileinfo *finfo;
1363
1364 debuglocal(9,"NdpEASet in [%p]\n", pConn);
1365
1366 if (!pfi || !pfi->pszName || !pFEAList || pFEAList->cbList <= sizeof(long))
1367 {
1368 return ERROR_EAS_NOT_SUPPORTED;
1369 }
1370 if (!pRes->easupport)
1371 {
1372 return ERROR_EAS_NOT_SUPPORTED;
1373 }
1374
1375 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1376 if (rc || !fdata.ulSize || !fdata.pData)
1377 {
1378 debuglocal(9,"NdpEASet: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1379 return ERROR_EAS_NOT_SUPPORTED;
1380 }
1381
1382 ENTER();
1383
1384 finfo = (smbwrp_fileinfo *)fdata.pData;
1385 path = finfo->fname;
1386
1387 do {
1388 // got FEA there
1389 FEA * pfea;
1390 unsigned long done = sizeof(long);
1391 pfea = pFEAList->list;
1392 while (done < pFEAList->cbList)
1393 {
1394 rc = smbwrp_setea(pConn->cli, path, (char*)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
1395 if (rc)
1396 {
1397 break;
1398 }
1399 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
1400 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1401 }
1402 } while (0);
1403 debuglocal(9,"NdpEASet %d\n", rc);
1404 LEAVE();
1405 return rc;
1406}
1407
1408int APIENTRY NdpEASize (HCONNECTION conn, NDFILEINFOL *pfi, ULONG *pulEASize)
1409{
1410 Connection *pConn = (Connection *)conn;
1411 Resource *pRes = pConn->pRes;
1412 int rc = 0;
1413 unsigned long action;
1414 char * path = NULL;
1415 FEALIST * pfealist;
1416 NDDATABUF fdata = {0};
1417 smbwrp_fileinfo *finfo;
1418 const int cbBuffer = 64*1024;
1419 int easize;
1420
1421 if (!pfi || !pulEASize)
1422 {
1423 return ERROR_EAS_NOT_SUPPORTED;
1424 }
1425 if (!pRes->easupport)
1426 {
1427 return ERROR_EAS_NOT_SUPPORTED;
1428 }
1429
1430 debuglocal(9, "remove me NdpEASize before fsphGetFileInfoData\n");
1431 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1432 if (rc || !fdata.ulSize || !fdata.pData)
1433 {
1434 debuglocal(9,"NdpEASize: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1435 return ERROR_EAS_NOT_SUPPORTED;
1436 }
1437
1438 ENTER();
1439
1440 debuglocal(9, "remove me NdpEASize before finfo =\n");
1441 finfo = (smbwrp_fileinfo *)fdata.pData;
1442 debuglocal(9, "remove me NdpEASize after finfo=\n");
1443 easize = finfo->easize;
1444 finfo->easize = -1;
1445 path = finfo->fname;
1446 if (easize >= 0)
1447 {
1448 *pulEASize = easize;
1449 debuglocal(9,"NdpEASize <%s> cached %d\n", path, easize);
1450 LEAVE();
1451 return NO_ERROR;
1452 }
1453
1454 debuglocal(9,"NdpEASize in [%p] <%s> \n", pConn, path);
1455
1456 char *pchBuffer = (char *)malloc(cbBuffer);
1457 if (!pchBuffer)
1458 {
1459 LEAVE();
1460 return ERROR_NOT_ENOUGH_MEMORY;
1461 }
1462
1463 do {
1464 rc = smbwrp_listea(pConn->cli, path, pchBuffer, cbBuffer);
1465 pfealist = (FEALIST*)pchBuffer;
1466 if (rc)
1467 {
1468 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1469 switch (rc)
1470 {
1471 case ERROR_FILE_NOT_FOUND :
1472 case ERROR_PATH_NOT_FOUND :
1473 {
1474 pfealist->cbList = sizeof(pfealist->cbList);
1475 } /* Fall through */
1476 case ERROR_BUFFER_OVERFLOW :
1477 {
1478 rc = NO_ERROR;
1479 } break;
1480 default :
1481 {
1482 rc = ERROR_EAS_NOT_SUPPORTED;
1483 }
1484 }
1485 }
1486 *pulEASize = pfealist->cbList;
1487 } while (0);
1488 free(pchBuffer);
1489 debuglocal(9,"NdpEASize <%s> %d %d\n", pfi->pszName, *pulEASize, rc);
1490 LEAVE();
1491 return rc;
1492}
1493
1494int APIENTRY NdpSetCurrentDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szPath)
1495{
1496 Connection *pConn = (Connection *)conn;
1497 Resource *pRes = pConn->pRes;
1498 int rc = 0;
1499 unsigned long action;
1500 char path[CCHMAXPATH+1] = {0};
1501
1502 debuglocal(9,"NdpSetCurrentDir in [%p]\n", pConn);
1503
1504 ENTER();
1505
1506 do {
1507 rc = pathparser(pRes, pConn, szPath, path);
1508 if (rc)
1509 {
1510 break;
1511 }
1512
1513 rc = smbwrp_chdir(&pRes->srv, pConn->cli, path);
1514 } while (0);
1515 debuglocal(9,"NdpSetCurrentDir <%s> (%s) %d\n", szPath, path, rc);
1516 LEAVE();
1517 return rc;
1518}
1519
1520int APIENTRY NdpCopy (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1521{
1522 debuglocal(9,"NdpCopy <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1523 return ERROR_CANNOT_COPY;
1524}
1525
1526int APIENTRY NdpCopy2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1527{
1528 debuglocal(9,"NdpCopy2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1529 return ERROR_CANNOT_COPY;
1530}
1531
1532int APIENTRY NdpForceDelete (HCONNECTION conn, NDFILEINFOL *pfi, char *szFile)
1533{
1534 Connection *pConn = (Connection *)conn;
1535 Resource *pRes = pConn->pRes;
1536 int rc = 0;
1537 unsigned long action;
1538 char path[CCHMAXPATH+1] = {0};
1539
1540 ENTER();
1541
1542 debuglocal(9,"NdpForceDelete in [%p]\n", pConn);
1543
1544 dircache_invalidate(szFile, pRes->pdc, 1);
1545
1546 do {
1547 rc = pathparser(pRes, pConn, szFile, path);
1548 if (rc)
1549 {
1550 break;
1551 }
1552
1553 rc = smbwrp_unlink(pConn->cli, path);
1554 } while (0);
1555 debuglocal(9,"NdpForceDelete <%s> (%s) %d\n", szFile, path, rc);
1556 LEAVE();
1557 return rc;
1558}
1559
1560int APIENTRY NdpCreateDir (HCONNECTION conn, NDFILEINFOL *pfiparent, char *szDirName, FEALIST *pFEAList)
1561{
1562 Connection *pConn = (Connection *)conn;
1563 Resource *pRes = pConn->pRes;
1564 int rc = 0;
1565 unsigned long action;
1566 char path[CCHMAXPATH+1] = {0};
1567
1568 ENTER();
1569
1570 debuglocal(9,"NdpCreateDir in [%p]\n", pConn);
1571
1572 dircache_invalidate(szDirName, pRes->pdc, 1);
1573
1574 do {
1575 rc = pathparser(pRes, pConn, szDirName, path);
1576 if (rc)
1577 {
1578 break;
1579 }
1580
1581 rc = smbwrp_mkdir(pConn->cli, path);
1582 } while (0);
1583 debuglocal(9,"NdpCreateDir <%s> (%s) %d\n", szDirName, path, rc);
1584 LEAVE();
1585 return rc;
1586}
1587
1588int APIENTRY NdpDeleteDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szDir)
1589{
1590 Connection *pConn = (Connection *)conn;
1591 Resource *pRes = pConn->pRes;
1592 int rc = 0;
1593 unsigned long action;
1594 char path[CCHMAXPATH+1] = {0};
1595
1596 ENTER();
1597
1598 debuglocal(9,"NdpDeleteDir in [%p]\n", pConn);
1599
1600 dircache_invalidate(szDir, pRes->pdc, 1);
1601
1602 do {
1603 rc = pathparser(pRes, pConn, szDir, path);
1604 if (rc)
1605 {
1606 break;
1607 }
1608
1609 rc = smbwrp_rmdir(pConn->cli, path);
1610 } while (0);
1611 debuglocal(9,"NdpDeleteDir <%s> (%s) %d\n", szDir, path, rc);
1612 LEAVE();
1613 return rc;
1614}
1615
1616int APIENTRY NdpMove (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1617{
1618 Connection *pConn = (Connection *)conn;
1619 Resource *pRes = pConn->pRes;
1620 int rc = 0;
1621 unsigned long action;
1622 char src[CCHMAXPATH+1] = {0};
1623 int l1, l2;
1624 char * p = szDst;
1625
1626 ENTER();
1627
1628 debuglocal(9,"NdpMove in [%p] from <%s> to <%s>\n", pConn, szSrc, szDst);
1629
1630 dircache_invalidate(szSrc, pRes->pdc, 1);
1631 dircache_invalidate(szDst, pRes->pdc, 1);
1632
1633 do
1634 {
1635 rc = pathparser(pRes, pConn, szSrc, src);
1636 if (rc)
1637 {
1638 break;
1639 }
1640 l1 = strlen(szSrc);
1641 l2 = strlen(src);
1642 if (l1 > l2)
1643 {
1644 if (ph->fsphStrNICmp(szSrc, szDst, l1 - l2))
1645 {
1646 // the file moved accross different shares or servers or workgroups
1647 rc = ERROR_WRITE_PROTECT;
1648 break;
1649 }
1650 p = szDst + l1 - l2 + 1;
1651 }
1652 //pConn->mem[CCHMAXPATH + 1] = '\\';
1653 rc = smbwrp_rename(pConn->cli, src, p);
1654 } while (0);
1655 debuglocal(9,"NdpMove <%s> -> <%s> (%s) %d\n", szSrc, szDst, src, rc);
1656 LEAVE();
1657 return rc;
1658}
1659
1660int APIENTRY NdpMove2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1661{
1662 debuglocal(9,"NdpMove2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_WRITE_PROTECT);
1663 return ERROR_WRITE_PROTECT;
1664}
1665
1666
1667int APIENTRY NdpChangeCase (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1668{
1669 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1670}
1671
1672int APIENTRY NdpRename (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1673{
1674 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1675}
1676
1677int smbopen(Connection *pConn, char *szFileName, int flags, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1678{
1679 Resource *pRes = pConn->pRes;
1680 unsigned long action;
1681 int rc = 0;
1682 char path[CCHMAXPATH+1] = {0};
1683
1684 ENTER();
1685
1686 debuglocal(9,"smbopen in [%p] %d\n", pConn, pConn->file.fd);
1687
1688 if (flags & O_CREAT)
1689 {
1690 dircache_invalidate(szFileName, pRes->pdc, 1);
1691 }
1692 do {
1693 if (pConn->file.fd > 0)
1694 {
1695 rc = ERROR_TOO_MANY_OPEN_FILES;
1696 break;
1697 }
1698
1699 rc = pathparser(pRes, pConn, szFileName, path);
1700 if (rc)
1701 {
1702 break;
1703 }
1704
1705 strncpy(pConn->file.fullname, szFileName, sizeof(pConn->file.fullname) - 1);
1706 strncpy(pConn->file.fname, path, sizeof(pConn->file.fname) - 1);
1707 flags |= O_BINARY;
1708 switch (ulOpenMode & 3)
1709 {
1710 case OPEN_ACCESS_READONLY : flags |= O_RDONLY; break;
1711 case OPEN_ACCESS_WRITEONLY : flags |= O_WRONLY; break;
1712 case OPEN_ACCESS_READWRITE : flags |= O_RDWR; break;
1713 default : flags |= O_RDWR;
1714 }
1715 pConn->file.openmode = flags;
1716 pConn->file.openattr = ulAttribute & 0x37;
1717 pConn->file.denymode = (ulOpenMode & 0x70) >> 4;
1718 rc = smbwrp_open(pConn->cli, &pConn->file);
1719 } while (0);
1720 debuglocal(9,"smbopen <%s> (%s) %08x %08x %08x %d. file = %d\n", szFileName, path, flags, ulOpenMode, ulAttribute, rc, pConn->file.fd);
1721 if (!rc && pFEAList)
1722 {
1723 int rc1 = NdpFileEASet((HCONNECTION)pConn, (NDFILEHANDLE)0, pFEAList);
1724 debuglocal(9,"smbopen NdpFileEASet %d. pFEAList->cbList %d\n", rc1, pFEAList->cbList);
1725 }
1726 LEAVE();
1727 return rc;
1728}
1729
1730int APIENTRY NdpOpenReplace (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1731{
1732 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
1733}
1734
1735int APIENTRY NdpOpenReplaceL(HCONNECTION conn, NDFILEINFO *pfi, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1736{
1737 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
1738}
1739
1740int APIENTRY NdpOpenCreate (HCONNECTION conn, NDFILEINFOL *pfiparent, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1741{
1742// return smbopen((Connection *)conn, szFileName, O_CREAT, ulOpenMode, ulAttribute);
1743 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
1744}
1745
1746int APIENTRY NdpOpenCreateL(HCONNECTION conn, NDFILEINFO *pfiparent, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1747{
1748 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
1749}
1750
1751int APIENTRY NdpOpenExisting (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulOpenMode, USHORT *pfNeedEA)
1752{
1753 if (pfNeedEA) *pfNeedEA = 0; // wtf is this ?
1754 return smbopen((Connection *)conn, szFileName, 0, ulOpenMode, 0, NULL);
1755}
1756
1757int APIENTRY NdpSetFileAttribute (HCONNECTION conn, NDFILEINFOL *pfi, char *szFileName, USHORT usAttr)
1758{
1759 Connection *pConn = (Connection *)conn;
1760 Resource *pRes = pConn->pRes;
1761 int rc = 0;
1762 unsigned long action;
1763
1764 smbwrp_fileinfo finfo;
1765 char path[CCHMAXPATH+1] = {0};
1766
1767 ENTER();
1768
1769 debuglocal(9,"NdpSetFileAttribute in [%p]\n", pConn);
1770 do {
1771 rc = pathparser(pRes, pConn, szFileName, path);
1772 if (rc)
1773 {
1774 break;
1775 }
1776
1777 memset(&finfo, 0, sizeof(finfo));
1778 strncpy(finfo.fname, path, sizeof(finfo.fname) - 1);
1779 finfo.attr = usAttr & 0x37;
1780 rc = smbwrp_setattr(pConn->cli, &finfo);
1781 } while (0);
1782 debuglocal(9,"NdpSetFileAttribute <%s> (%s) %04x %d\n", szFileName, path, usAttr, rc);
1783 LEAVE();
1784 return rc;
1785}
1786
1787int APIENTRY NdpFlush (HRESOURCE resource)
1788{
1789 debuglocal(9,"NdpFlush %d\n", ERROR_NOT_SUPPORTED);
1790 return ERROR_NOT_SUPPORTED;
1791}
1792
1793// Called when a new thread will call the plugin. Allows to do per thread init, like disable signals.
1794#define ND_PL_INIT_THREAD 0xFFFF0000
1795
1796int APIENTRY NdpIOCTL (int type, HRESOURCE resource, char *path, int function, void *in, ULONG insize, PULONG poutlen)
1797{
1798 if (function == ND_PL_INIT_THREAD)
1799 {
1800 smbwrp_initthread();
1801 debuglocal(9, "NdpIOCTL init thread\n");
1802 return NO_ERROR;
1803 }
1804
1805 debuglocal(9,"NdpIOCTL <%s> %d\n", path, function);
1806
1807 if (in && insize > 4096)
1808 {
1809 char out[4096];
1810 sprintf (out, "SAMBA IOCTL function = %d, parms [%s] insize = %d, *poutlen = %d", function, in, insize, *poutlen);
1811 *poutlen = strlen(out);
1812 strcpy (in, out);
1813 return NO_ERROR;
1814 }
1815
1816 return ERROR_NOT_SUPPORTED;
1817}
1818
1819int APIENTRY NdpFileQueryInfo (HCONNECTION conn, NDFILEHANDLE handle, void *plist)
1820{
1821 Connection *pConn = (Connection *)conn;
1822 Resource *pRes = pConn->pRes;
1823 int rc = 0;
1824 unsigned long action;
1825 smbwrp_fileinfo finfo;
1826
1827 ENTER();
1828
1829 debug_printf("NdpFileQueryInfo in [%p]\n", pConn);
1830 do {
1831 if (pConn->file.fd < 0 || !*pConn->file.fname)
1832 {
1833 rc = ERROR_INVALID_HANDLE;
1834 break;
1835 }
1836 strncpy(finfo.fname, pConn->file.fname, sizeof(finfo.fname) - 1);
1837 rc = smbwrp_fgetattr(pConn->cli, &pConn->file, &finfo);
1838 if (!rc)
1839 {
1840 finfo.easize = -1;
1841 getfindinfoL(pConn, plist, &finfo, 0, NULL);
1842 }
1843 } while (0);
1844 debuglocal(9,"NdpFileQueryInfo <%s> %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, rc);
1845 LEAVE();
1846 return rc;
1847}
1848
1849int APIENTRY NdpFileEAQuery (HCONNECTION conn, NDFILEHANDLE handle, GEALIST *pGEAList, FEALIST *pFEAList)
1850{
1851 Connection *pConn = (Connection *)conn;
1852 Resource *pRes = pConn->pRes;
1853 int rc = 0;
1854 unsigned long action;
1855 const int cbBuffer = 64*1024;
1856 FEALIST * pFEASrc;
1857
1858 if (!pFEAList)
1859 {
1860 return ERROR_EAS_NOT_SUPPORTED;
1861 }
1862 if (!pRes->easupport)
1863 {
1864 return ERROR_EAS_NOT_SUPPORTED;
1865 }
1866
1867 debuglocal(9,"NdpFileEAQuery in [%p] <%s>/%d pGEAList=%08x\n", pConn, pConn->file.fname, pConn->file.fd, pGEAList);
1868
1869 char *pchBuffer = (char *)malloc(cbBuffer);
1870 if (!pchBuffer)
1871 return ERROR_NOT_ENOUGH_MEMORY;
1872
1873 ENTER();
1874
1875 do {
1876 if (pConn->file.fd < 0)
1877 {
1878 rc = ERROR_INVALID_HANDLE;
1879 break;
1880 }
1881 rc = smbwrp_flistea(pConn->cli, &pConn->file, pchBuffer, cbBuffer);
1882 pFEASrc = (FEALIST *)pchBuffer;
1883 if (rc)
1884 {
1885 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1886 switch (rc)
1887 {
1888 case ERROR_FILE_NOT_FOUND :
1889 case ERROR_PATH_NOT_FOUND :
1890 {
1891 pFEAList->cbList = sizeof(pFEAList->cbList);
1892 rc = NO_ERROR;
1893 } break;
1894 case ERROR_BUFFER_OVERFLOW :
1895 {
1896 pFEAList->cbList = pFEASrc->cbList;
1897 } break;
1898 default :
1899 {
1900 rc = ERROR_EAS_NOT_SUPPORTED;
1901 }
1902 }
1903 }
1904 else
1905 {
1906 rc = buildFEALIST(pFEASrc, pGEAList, pFEAList);
1907 }
1908 } while (0);
1909 free(pchBuffer);
1910 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);
1911 LEAVE();
1912 return rc;
1913}
1914
1915int APIENTRY NdpFileEASet (HCONNECTION conn, NDFILEHANDLE handle, FEALIST *pFEAList)
1916{
1917 Connection *pConn = (Connection *)conn;
1918 Resource *pRes = pConn->pRes;
1919 int rc = 0;
1920 unsigned long action;
1921
1922 debuglocal(9,"NdpFileEASet in [%p]\n", pConn);
1923
1924 if (!pFEAList || pFEAList->cbList <= sizeof(long))
1925 {
1926 return ERROR_EAS_NOT_SUPPORTED;
1927 }
1928 if (!pRes->easupport)
1929 {
1930 return ERROR_EAS_NOT_SUPPORTED;
1931 }
1932
1933 ENTER();
1934
1935 do {
1936 // got FEA there
1937 FEA * pfea;
1938 unsigned long done = sizeof(long);
1939 if (pConn->file.fd < 0)
1940 {
1941 rc = ERROR_INVALID_HANDLE;
1942 break;
1943 }
1944
1945 pfea = pFEAList->list;
1946 while (done < pFEAList->cbList)
1947 {
1948 rc = smbwrp_fsetea(pConn->cli, &pConn->file, (char *)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
1949 if (rc)
1950 {
1951 break;
1952 }
1953 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
1954 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1955 }
1956
1957 } while (0);
1958 debuglocal(9,"NdpFileEASet %d\n", rc);
1959 LEAVE();
1960 return rc;
1961}
1962
1963int APIENTRY NdpFileEASize (HCONNECTION conn, NDFILEHANDLE handle, ULONG *pulEASize)
1964{
1965 Connection *pConn = (Connection *)conn;
1966 Resource *pRes = pConn->pRes;
1967 int rc = 0;
1968 unsigned long action;
1969 char path[CCHMAXPATH+1] = {0};
1970 FEALIST * pFEAList;
1971 const int cbBuffer = 64*1024;
1972
1973 if (!pulEASize)
1974 {
1975 return ERROR_EAS_NOT_SUPPORTED;
1976 }
1977 if (!pRes->easupport)
1978 {
1979 return ERROR_EAS_NOT_SUPPORTED;
1980 }
1981
1982 debuglocal(9,"NdpFileEASize in [%p] <%s>/%d \n", pConn, pConn->file.fname, pConn->file.fd);
1983
1984 char *pchBuffer = (char *)malloc(cbBuffer);
1985 if (!pchBuffer)
1986 return ERROR_NOT_ENOUGH_MEMORY;
1987
1988 ENTER();
1989
1990 do {
1991 if (pConn->file.fd < 0)
1992 {
1993 rc = ERROR_INVALID_HANDLE;
1994 break;
1995 }
1996 rc = smbwrp_flistea(pConn->cli, &pConn->file, pchBuffer, cbBuffer);
1997 pFEAList = (FEALIST*)pchBuffer;
1998 if (rc)
1999 {
2000 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2001 switch (rc)
2002 {
2003 case ERROR_FILE_NOT_FOUND :
2004 case ERROR_PATH_NOT_FOUND :
2005 {
2006 pFEAList->cbList = sizeof(pFEAList->cbList);
2007 } /* Fall through */
2008 case ERROR_BUFFER_OVERFLOW :
2009 {
2010 rc = NO_ERROR;
2011 } break;
2012 default :
2013 {
2014 rc = ERROR_EAS_NOT_SUPPORTED;
2015 }
2016 }
2017 }
2018 *pulEASize = pFEAList->cbList;
2019 } while (0);
2020 free(pchBuffer);
2021 debuglocal(9,"NdpFileEASize %d %d\n", *pulEASize, rc);
2022 LEAVE();
2023 return rc;
2024}
2025
2026int APIENTRY NdpFileSetInfo (HCONNECTION conn, NDFILEHANDLE handle, NDFILEINFOL *pfi)
2027{
2028 Connection *pConn = (Connection *)conn;
2029 Resource *pRes = pConn->pRes;
2030 int rc = 0;
2031 unsigned long action, attrFile;
2032
2033 ENTER();
2034
2035 debug_printf("NdpFileSetInfo in [%p]\n", pConn);
2036
2037 // delete the dir cache
2038 dircache_invalidate(pConn->file.fullname, pRes->pdc, 1);
2039
2040 do {
2041 if (pConn->file.fd < 0 || !*pConn->file.fname)
2042 {
2043 rc = ERROR_INVALID_HANDLE;
2044 break;
2045 }
2046 attrFile = pfi->stat.attrFile;
2047 // deferred setinfo - on closing the file
2048 pConn->file.openattr = attrFile;
2049 fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, &(pConn->file.mtime));
2050 debug_printf("NdpFileSetInfo mtime %d\n", pConn->file.mtime);
2051 } while (0);
2052 debuglocal(9,"NdpFileSetInfo <%s> %08x %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, attrFile, rc);
2053 LEAVE();
2054 return NO_ERROR;
2055}
2056
2057int APIENTRY NdpFileSetFilePtrL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llOffset, ULONG ulMethod, LONGLONG *pllActual)
2058{
2059 Connection *pConn = (Connection *)conn;
2060 Resource *pRes = pConn->pRes;
2061 int rc = 0;
2062 unsigned long action;
2063
2064 ENTER();
2065
2066 debuglocal(9,"NdpFileSetFilePtrL in [%p]\n", pConn);
2067
2068 do {
2069 if (pConn->file.fd < 0)
2070 {
2071 rc = ERROR_INVALID_HANDLE;
2072 break;
2073 }
2074
2075 rc = smbwrp_lseek(pConn->cli, &pConn->file, ulMethod, llOffset);
2076 if (!rc)
2077 *pllActual = pConn->file.offset;
2078
2079 } while (0);
2080 debuglocal(9,"NdpFileSetFilePtrL <%s> %lld %lu %lld %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llOffset, ulMethod, *pllActual, rc);
2081 LEAVE();
2082 return rc;
2083}
2084
2085int APIENTRY NdpFileSetFilePtr (HCONNECTION conn, NDFILEHANDLE handle, LONG lOffset, ULONG ulMethod, ULONG *pulActual)
2086{
2087 LONGLONG llActual;
2088 int rc = NdpFileSetFilePtrL(conn, handle, lOffset, ulMethod, &llActual);
2089 *pulActual = llActual & 0xFFFFFFFF;
2090 debuglocal(9,"NdpFileSetFilePtr %ld %lu %ld %d\n", lOffset, ulMethod, *pulActual, rc);
2091 return rc;
2092}
2093
2094int APIENTRY NdpFileClose (HCONNECTION conn, NDFILEHANDLE handle)
2095{
2096 Connection *pConn = (Connection *)conn;
2097 Resource *pRes = pConn->pRes;
2098 int rc = 0;
2099 unsigned long action;
2100
2101 ENTER();
2102
2103 debuglocal(9,"NdpFileClose in [%p] %d <%s>\n", pConn, pConn->file.fd, pConn->file.fd < 0 ? "!null!" : pConn->file.fname);
2104
2105 do {
2106 if (pConn->file.fd < 0)
2107 {
2108 rc = ERROR_INVALID_HANDLE;
2109 break;
2110 }
2111
2112 rc = smbwrp_close(pConn->cli, &pConn->file);
2113
2114 } while (0);
2115 debuglocal(9,"NdpFileClose %d %d\n", pConn->file.fd, rc);
2116
2117 pConn->file.fd = -1;
2118 LEAVE();
2119 return rc;
2120}
2121
2122int APIENTRY NdpFileCommit (HCONNECTION conn, NDFILEHANDLE handle)
2123{
2124 debuglocal(9,"NdpFileCommit %d\n", NO_ERROR);
2125 return NO_ERROR;
2126}
2127
2128
2129int APIENTRY NdpFileNewSize (HCONNECTION conn, NDFILEHANDLE handle, ULONG ulLen)
2130{
2131 int rc = NdpFileNewSizeL(conn, handle, ulLen);
2132 debuglocal(9,"NdpFileNewSize %ld %d\n", ulLen, rc);
2133 return rc;
2134}
2135
2136int APIENTRY NdpFileNewSizeL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llLen)
2137{
2138 Connection *pConn = (Connection *)conn;
2139 Resource *pRes = pConn->pRes;
2140 int rc = 0;
2141 unsigned long action;
2142
2143 ENTER();
2144
2145 debuglocal(9,"NdpFileNewSizeL in [%p]\n", pConn);
2146
2147 do {
2148 if (pConn->file.fd < 0)
2149 {
2150 rc = ERROR_INVALID_HANDLE;
2151 break;
2152 }
2153
2154 rc = smbwrp_setfilesize(pConn->cli, &pConn->file, llLen);
2155
2156 } while (0);
2157 debuglocal(9,"NdpFileNewSizeL <%s> %lld %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llLen, rc);
2158 LEAVE();
2159 return rc;
2160}
2161
2162#define NDPSMB_READ_MAX_SIZE (65536 - 4096)
2163
2164int APIENTRY NdpFileRead (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulRead, ULONG *pulActual)
2165{
2166 Connection *pConn = (Connection *)conn;
2167 Resource *pRes = pConn->pRes;
2168 int rc = 0;
2169 unsigned long done = 0;
2170 unsigned long onedone;
2171 unsigned long action;
2172 ULONG ulReadCompleted = 0;
2173
2174 ENTER();
2175
2176 debuglocal(9,"NdpFileRead in [%p]\n", pConn);
2177
2178 do {
2179 if (pConn->file.fd < 0)
2180 {
2181 rc = ERROR_INVALID_HANDLE;
2182 break;
2183 }
2184 while (ulReadCompleted < ulRead)
2185 {
2186 ULONG ulActual;
2187 ULONG ulToRead = ulRead - ulReadCompleted;
2188 debuglocal(9,"NdpFileRead completed %d, to read %d\n", ulReadCompleted, ulToRead);
2189 if (ulToRead > NDPSMB_READ_MAX_SIZE)
2190 {
2191 ulToRead = NDPSMB_READ_MAX_SIZE;
2192 }
2193 rc = smbwrp_read(pConn->cli, &pConn->file, (char *)pBuffer + ulReadCompleted, ulToRead, &ulActual);
2194 if (ulActual == 0 || rc != NO_ERROR)
2195 {
2196 break;
2197 }
2198 ulReadCompleted += ulActual;
2199 }
2200 //*pulActual = ulRead;
2201 //DosSleep(0);
2202
2203 } while (0);
2204
2205 if (ulReadCompleted > 0)
2206 {
2207 rc = NO_ERROR; /* Still were able to read some data. */
2208 }
2209
2210 if (rc == NO_ERROR)
2211 {
2212 *pulActual = ulReadCompleted;
2213 }
2214
2215 debuglocal(9,"NdpFileRead <%s> %lu %lu %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead, *pulActual, rc);
2216 LEAVE();
2217 return rc;
2218}
2219
2220int APIENTRY NdpFileWrite (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulWrite, ULONG *pulActual)
2221{
2222 Connection *pConn = (Connection *)conn;
2223 Resource *pRes = pConn->pRes;
2224 int rc = 0;
2225 unsigned long done = 0;
2226 unsigned long onedone;
2227 unsigned long action;
2228
2229 ENTER();
2230
2231 debuglocal(9,"NdpFileWrite in [%p]\n", pConn);
2232
2233 /* delete the dir cache
2234 this was moved from NdpFileClose() becasue if there are a lot files in the tree all are reread
2235 the problem when moved to here is, that last accessed time is not refreshed
2236 if this is needed, a new function needs to be done to update only one file in the cache */
2237 dircache_invalidate(pConn->file.fullname, pRes->pdc, 1);
2238
2239 do {
2240 if (pConn->file.fd < 0)
2241 {
2242 rc = ERROR_INVALID_HANDLE;
2243 break;
2244 }
2245 rc = smbwrp_write(pConn->cli, &pConn->file, pBuffer, ulWrite, pulActual);
2246
2247 } while (0);
2248 debuglocal(9,"NdpFileWrite <%s> %lu %lu %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulWrite, *pulActual, rc);
2249 LEAVE();
2250 return rc;
2251}
2252
Note: See TracBrowser for help on using the repository browser.