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

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

Samba Client 2.1: degug changes, attemp to fix the trap

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