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

Last change on this file since 529 was 528, checked in by Silvan Scherrer, 15 years ago

Samba Client 2.1: more errno fixes

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