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

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

Samba Client 2.1: interim commit

  • Property svn:eol-style set to native
File size: 53.9 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 debuglocal(9, "remove me NdpEASize before fsphGetFileInfoData\n");
1356 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1357 if (rc || !fdata.ulSize || !fdata.pData)
1358 {
1359 debuglocal(9,"NdpEASize: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1360 return ERROR_EAS_NOT_SUPPORTED;
1361 }
1362
1363 debuglocal(9, "remove me NdpEASize before finfo =\n");
1364 finfo = (smbwrp_fileinfo *)fdata.pData;
1365 debuglocal(9, "remove me NdpEASize after finfo=\n");
1366 easize = finfo->easize;
1367 finfo->easize = -1;
1368 path = finfo->fname;
1369 if (easize >= 0)
1370 {
1371 *pulEASize = easize;
1372 debuglocal(9,"NdpEASize <%s> cached %d\n", path, easize);
1373 return NO_ERROR;
1374 }
1375
1376 debuglocal(9,"NdpEASize in [%p] <%s> \n", pConn, path);
1377
1378 char *pchBuffer = (char *)malloc(cbBuffer);
1379 if (!pchBuffer)
1380 return ERROR_NOT_ENOUGH_MEMORY;
1381
1382 do {
1383 rc = smbwrp_listea(pConn->cli, path, pchBuffer, cbBuffer);
1384 pfealist = (FEALIST*)pchBuffer;
1385 if (rc)
1386 {
1387 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1388 switch (rc)
1389 {
1390 case ERROR_FILE_NOT_FOUND :
1391 case ERROR_PATH_NOT_FOUND :
1392 {
1393 pfealist->cbList = sizeof(pfealist->cbList);
1394 } /* Fall through */
1395 case ERROR_BUFFER_OVERFLOW :
1396 {
1397 rc = NO_ERROR;
1398 } break;
1399 default :
1400 {
1401 rc = ERROR_EAS_NOT_SUPPORTED;
1402 }
1403 }
1404 }
1405 *pulEASize = pfealist->cbList;
1406 } while (0);
1407 free(pchBuffer);
1408 debuglocal(9,"NdpEASize <%s> %d %d\n", pfi->pszName, *pulEASize, rc);
1409
1410 return rc;
1411}
1412
1413int APIENTRY NdpSetCurrentDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szPath)
1414{
1415 Connection *pConn = (Connection *)conn;
1416 Resource *pRes = pConn->pRes;
1417 int rc = 0;
1418 unsigned long action;
1419 char path[CCHMAXPATH+1] = {0};
1420
1421 debuglocal(9,"NdpSetCurrentDir in [%p]\n", pConn);
1422
1423 do {
1424 rc = pathparser(pRes, pConn, szPath, path);
1425 if (rc)
1426 {
1427 break;
1428 }
1429
1430 rc = smbwrp_chdir(&pRes->srv, pConn->cli, path);
1431 } while (0);
1432 debuglocal(9,"NdpSetCurrentDir <%s> (%s) %d\n", szPath, path, rc);
1433
1434 return rc;
1435}
1436
1437int APIENTRY NdpCopy (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1438{
1439 debuglocal(9,"NdpCopy <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1440 return ERROR_CANNOT_COPY;
1441}
1442
1443int APIENTRY NdpCopy2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1444{
1445 debuglocal(9,"NdpCopy2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1446 return ERROR_CANNOT_COPY;
1447}
1448
1449int APIENTRY NdpForceDelete (HCONNECTION conn, NDFILEINFOL *pfi, char *szFile)
1450{
1451 Connection *pConn = (Connection *)conn;
1452 Resource *pRes = pConn->pRes;
1453 int rc = 0;
1454 unsigned long action;
1455 char path[CCHMAXPATH+1] = {0};
1456
1457 debuglocal(9,"NdpForceDelete in [%p]\n", pConn);
1458
1459 dircache_invalidate(szFile, pRes->pdc, 1);
1460
1461 do {
1462 rc = pathparser(pRes, pConn, szFile, path);
1463 if (rc)
1464 {
1465 break;
1466 }
1467
1468 rc = smbwrp_unlink(pConn->cli, path);
1469 } while (0);
1470 debuglocal(9,"NdpForceDelete <%s> (%s) %d\n", szFile, path, rc);
1471
1472 return rc;
1473}
1474
1475int APIENTRY NdpCreateDir (HCONNECTION conn, NDFILEINFOL *pfiparent, char *szDirName, FEALIST *pFEAList)
1476{
1477 Connection *pConn = (Connection *)conn;
1478 Resource *pRes = pConn->pRes;
1479 int rc = 0;
1480 unsigned long action;
1481 char path[CCHMAXPATH+1] = {0};
1482
1483 debuglocal(9,"NdpCreateDir in [%p]\n", pConn);
1484
1485 dircache_invalidate(szDirName, pRes->pdc, 1);
1486
1487 do {
1488 rc = pathparser(pRes, pConn, szDirName, path);
1489 if (rc)
1490 {
1491 break;
1492 }
1493
1494 rc = smbwrp_mkdir(pConn->cli, path);
1495 } while (0);
1496 debuglocal(9,"NdpCreateDir <%s> (%s) %d\n", szDirName, path, rc);
1497
1498 return rc;
1499}
1500
1501int APIENTRY NdpDeleteDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szDir)
1502{
1503 Connection *pConn = (Connection *)conn;
1504 Resource *pRes = pConn->pRes;
1505 int rc = 0;
1506 unsigned long action;
1507 char path[CCHMAXPATH+1] = {0};
1508
1509 debuglocal(9,"NdpDeleteDir in [%p]\n", pConn);
1510
1511 dircache_invalidate(szDir, pRes->pdc, 1);
1512
1513 do {
1514 rc = pathparser(pRes, pConn, szDir, path);
1515 if (rc)
1516 {
1517 break;
1518 }
1519
1520 rc = smbwrp_rmdir(pConn->cli, path);
1521 } while (0);
1522 debuglocal(9,"NdpDeleteDir <%s> (%s) %d\n", szDir, path, rc);
1523
1524 return rc;
1525}
1526
1527int APIENTRY NdpMove (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1528{
1529 Connection *pConn = (Connection *)conn;
1530 Resource *pRes = pConn->pRes;
1531 int rc = 0;
1532 unsigned long action;
1533 char src[CCHMAXPATH+1] = {0};
1534 int l1, l2;
1535 char * p = szDst;
1536
1537 debuglocal(9,"NdpMove in [%p] from <%s> to <%s>\n", pConn, szSrc, szDst);
1538
1539 dircache_invalidate(szSrc, pRes->pdc, 1);
1540 dircache_invalidate(szDst, pRes->pdc, 1);
1541
1542 do
1543 {
1544 rc = pathparser(pRes, pConn, szSrc, src);
1545 if (rc)
1546 {
1547 break;
1548 }
1549 l1 = strlen(szSrc);
1550 l2 = strlen(src);
1551 if (l1 > l2)
1552 {
1553 if (ph->fsphStrNICmp(szSrc, szDst, l1 - l2))
1554 {
1555 // the file moved accross different shares or servers or workgroups
1556 rc = ERROR_WRITE_PROTECT;
1557 break;
1558 }
1559 p = szDst + l1 - l2 + 1;
1560 }
1561 //pConn->mem[CCHMAXPATH + 1] = '\\';
1562 rc = smbwrp_rename(pConn->cli, src, p);
1563 } while (0);
1564 debuglocal(9,"NdpMove <%s> -> <%s> (%s) %d\n", szSrc, szDst, src, rc);
1565
1566 return rc;
1567}
1568
1569int APIENTRY NdpMove2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1570{
1571 debuglocal(9,"NdpMove2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_WRITE_PROTECT);
1572 return ERROR_WRITE_PROTECT;
1573}
1574
1575
1576int APIENTRY NdpChangeCase (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1577{
1578 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1579}
1580
1581int APIENTRY NdpRename (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1582{
1583 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1584}
1585
1586int smbopen(Connection *pConn, char *szFileName, int flags, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1587{
1588 Resource *pRes = pConn->pRes;
1589 unsigned long action;
1590 int rc = 0;
1591 char path[CCHMAXPATH+1] = {0};
1592
1593 debuglocal(9,"smbopen in [%p] %d\n", pConn, pConn->file.fd);
1594
1595 if (flags & O_CREAT)
1596 {
1597 dircache_invalidate(szFileName, pRes->pdc, 1);
1598 }
1599 do {
1600 if (pConn->file.fd > 0)
1601 {
1602 rc = ERROR_TOO_MANY_OPEN_FILES;
1603 break;
1604 }
1605
1606 rc = pathparser(pRes, pConn, szFileName, path);
1607 if (rc)
1608 {
1609 break;
1610 }
1611
1612 strncpy(pConn->file.fullname, szFileName, sizeof(pConn->file.fullname) - 1);
1613 strncpy(pConn->file.fname, path, sizeof(pConn->file.fname) - 1);
1614 flags |= O_BINARY;
1615 switch (ulOpenMode & 3)
1616 {
1617 case OPEN_ACCESS_READONLY : flags |= O_RDONLY; break;
1618 case OPEN_ACCESS_WRITEONLY : flags |= O_WRONLY; break;
1619 case OPEN_ACCESS_READWRITE : flags |= O_RDWR; break;
1620 default : flags |= O_RDWR;
1621 }
1622 pConn->file.openmode = flags;
1623 pConn->file.openattr = ulAttribute & 0x37;
1624 pConn->file.denymode = (ulOpenMode & 0x70) >> 4;
1625 rc = smbwrp_open(pConn->cli, &pConn->file);
1626 } while (0);
1627 debuglocal(9,"smbopen <%s> (%s) %08x %08x %08x %d. file = %d\n", szFileName, path, flags, ulOpenMode, ulAttribute, rc, pConn->file.fd);
1628 if (!rc && pFEAList)
1629 {
1630 int rc1 = NdpFileEASet((HCONNECTION)pConn, (NDFILEHANDLE)0, pFEAList);
1631 debuglocal(9,"smbopen NdpFileEASet %d. pFEAList->cbList %d\n", rc1, pFEAList->cbList);
1632 }
1633
1634 return rc;
1635}
1636
1637int APIENTRY NdpOpenReplace (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1638{
1639 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
1640}
1641
1642int APIENTRY NdpOpenReplaceL(HCONNECTION conn, NDFILEINFO *pfi, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1643{
1644 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
1645}
1646
1647int APIENTRY NdpOpenCreate (HCONNECTION conn, NDFILEINFOL *pfiparent, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1648{
1649// return smbopen((Connection *)conn, szFileName, O_CREAT, ulOpenMode, ulAttribute);
1650 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
1651}
1652
1653int APIENTRY NdpOpenCreateL(HCONNECTION conn, NDFILEINFO *pfiparent, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1654{
1655 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
1656}
1657
1658int APIENTRY NdpOpenExisting (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulOpenMode, USHORT *pfNeedEA)
1659{
1660 if (pfNeedEA) *pfNeedEA = 0; // wtf is this ?
1661 return smbopen((Connection *)conn, szFileName, 0, ulOpenMode, 0, NULL);
1662}
1663
1664int APIENTRY NdpSetFileAttribute (HCONNECTION conn, NDFILEINFOL *pfi, char *szFileName, USHORT usAttr)
1665{
1666 Connection *pConn = (Connection *)conn;
1667 Resource *pRes = pConn->pRes;
1668 int rc = 0;
1669 unsigned long action;
1670
1671 smbwrp_fileinfo finfo;
1672 char path[CCHMAXPATH+1] = {0};
1673
1674 debuglocal(9,"NdpSetFileAttribute in [%p]\n", pConn);
1675 do {
1676 rc = pathparser(pRes, pConn, szFileName, path);
1677 if (rc)
1678 {
1679 break;
1680 }
1681
1682 memset(&finfo, 0, sizeof(finfo));
1683 strncpy(finfo.fname, path, sizeof(finfo.fname) - 1);
1684 finfo.attr = usAttr & 0x37;
1685 rc = smbwrp_setattr(pConn->cli, &finfo);
1686 } while (0);
1687 debuglocal(9,"NdpSetFileAttribute <%s> (%s) %04x %d\n", szFileName, path, usAttr, rc);
1688
1689 return rc;
1690}
1691
1692int APIENTRY NdpFlush (HRESOURCE resource)
1693{
1694 debuglocal(9,"NdpFlush %d\n", ERROR_NOT_SUPPORTED);
1695 return ERROR_NOT_SUPPORTED;
1696}
1697
1698// Called when a new thread will call the plugin. Allows to do per thread init, like disable signals.
1699#define ND_PL_INIT_THREAD 0xFFFF0000
1700
1701int APIENTRY NdpIOCTL (int type, HRESOURCE resource, char *path, int function, void *in, ULONG insize, PULONG poutlen)
1702{
1703 if (function == ND_PL_INIT_THREAD)
1704 {
1705 smbwrp_initthread();
1706 debuglocal(9, "NdpIOCTL init thread\n");
1707 return NO_ERROR;
1708 }
1709
1710 debuglocal(9,"NdpIOCTL <%s> %d\n", path, function);
1711
1712 if (in && insize > 4096)
1713 {
1714 char out[4096];
1715 sprintf (out, "SAMBA IOCTL function = %d, parms [%s] insize = %d, *poutlen = %d", function, in, insize, *poutlen);
1716 *poutlen = strlen(out);
1717 strcpy (in, out);
1718 return NO_ERROR;
1719 }
1720
1721 return ERROR_NOT_SUPPORTED;
1722}
1723
1724int APIENTRY NdpFileQueryInfo (HCONNECTION conn, NDFILEHANDLE handle, void *plist)
1725{
1726 Connection *pConn = (Connection *)conn;
1727 Resource *pRes = pConn->pRes;
1728 int rc = 0;
1729 unsigned long action;
1730 smbwrp_fileinfo finfo;
1731
1732 debug_printf("NdpFileQueryInfo in [%p]\n", pConn);
1733 do {
1734 if (pConn->file.fd < 0 || !*pConn->file.fname)
1735 {
1736 rc = ERROR_INVALID_HANDLE;
1737 break;
1738 }
1739 strncpy(finfo.fname, pConn->file.fname, sizeof(finfo.fname) - 1);
1740 rc = smbwrp_fgetattr(pConn->cli, &pConn->file, &finfo);
1741 if (!rc)
1742 {
1743 finfo.easize = -1;
1744 getfindinfoL(pConn, plist, &finfo, 0, NULL);
1745 }
1746 } while (0);
1747 debuglocal(9,"NdpFileQueryInfo <%s> %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, rc);
1748
1749 return rc;
1750}
1751
1752int APIENTRY NdpFileEAQuery (HCONNECTION conn, NDFILEHANDLE handle, GEALIST *pGEAList, FEALIST *pFEAList)
1753{
1754 Connection *pConn = (Connection *)conn;
1755 Resource *pRes = pConn->pRes;
1756 int rc = 0;
1757 unsigned long action;
1758 const int cbBuffer = 64*1024;
1759 FEALIST * pFEASrc;
1760
1761 if (!pFEAList)
1762 {
1763 return ERROR_EAS_NOT_SUPPORTED;
1764 }
1765 if (!pRes->easupport)
1766 {
1767 return ERROR_EAS_NOT_SUPPORTED;
1768 }
1769
1770 debuglocal(9,"NdpFileEAQuery in [%p] <%s>/%d pGEAList=%08x\n", pConn, pConn->file.fname, pConn->file.fd, pGEAList);
1771
1772 char *pchBuffer = (char *)malloc(cbBuffer);
1773 if (!pchBuffer)
1774 return ERROR_NOT_ENOUGH_MEMORY;
1775
1776 do {
1777 if (pConn->file.fd < 0)
1778 {
1779 rc = ERROR_INVALID_HANDLE;
1780 break;
1781 }
1782 rc = smbwrp_flistea(pConn->cli, &pConn->file, pchBuffer, cbBuffer);
1783 pFEASrc = (FEALIST *)pchBuffer;
1784 if (rc)
1785 {
1786 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1787 switch (rc)
1788 {
1789 case ERROR_FILE_NOT_FOUND :
1790 case ERROR_PATH_NOT_FOUND :
1791 {
1792 pFEAList->cbList = sizeof(pFEAList->cbList);
1793 rc = NO_ERROR;
1794 } break;
1795 case ERROR_BUFFER_OVERFLOW :
1796 {
1797 pFEAList->cbList = pFEASrc->cbList;
1798 } break;
1799 default :
1800 {
1801 rc = ERROR_EAS_NOT_SUPPORTED;
1802 }
1803 }
1804 }
1805 else
1806 {
1807 rc = buildFEALIST(pFEASrc, pGEAList, pFEAList);
1808 }
1809 } while (0);
1810 free(pchBuffer);
1811 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);
1812
1813 return rc;
1814}
1815
1816int APIENTRY NdpFileEASet (HCONNECTION conn, NDFILEHANDLE handle, FEALIST *pFEAList)
1817{
1818 Connection *pConn = (Connection *)conn;
1819 Resource *pRes = pConn->pRes;
1820 int rc = 0;
1821 unsigned long action;
1822
1823 debuglocal(9,"NdpFileEASet in [%p]\n", pConn);
1824
1825 if (!pFEAList || pFEAList->cbList <= sizeof(long))
1826 {
1827 return ERROR_EAS_NOT_SUPPORTED;
1828 }
1829 if (!pRes->easupport)
1830 {
1831 return ERROR_EAS_NOT_SUPPORTED;
1832 }
1833
1834 do {
1835 // got FEA there
1836 FEA * pfea;
1837 unsigned long done = sizeof(long);
1838 if (pConn->file.fd < 0)
1839 {
1840 rc = ERROR_INVALID_HANDLE;
1841 break;
1842 }
1843
1844 pfea = pFEAList->list;
1845 while (done < pFEAList->cbList)
1846 {
1847 rc = smbwrp_fsetea(pConn->cli, &pConn->file, (char *)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
1848 if (rc)
1849 {
1850 break;
1851 }
1852 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
1853 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1854 }
1855
1856 } while (0);
1857 debuglocal(9,"NdpFileEASet %d\n", rc);
1858
1859 return rc;
1860}
1861
1862int APIENTRY NdpFileEASize (HCONNECTION conn, NDFILEHANDLE handle, ULONG *pulEASize)
1863{
1864 Connection *pConn = (Connection *)conn;
1865 Resource *pRes = pConn->pRes;
1866 int rc = 0;
1867 unsigned long action;
1868 char path[CCHMAXPATH+1] = {0};
1869 FEALIST * pFEAList;
1870 const int cbBuffer = 64*1024;
1871
1872 if (!pulEASize)
1873 {
1874 return ERROR_EAS_NOT_SUPPORTED;
1875 }
1876 if (!pRes->easupport)
1877 {
1878 return ERROR_EAS_NOT_SUPPORTED;
1879 }
1880
1881 debuglocal(9,"NdpFileEASize in [%p] <%s>/%d \n", pConn, pConn->file.fname, pConn->file.fd);
1882
1883 char *pchBuffer = (char *)malloc(cbBuffer);
1884 if (!pchBuffer)
1885 return ERROR_NOT_ENOUGH_MEMORY;
1886
1887 do {
1888 if (pConn->file.fd < 0)
1889 {
1890 rc = ERROR_INVALID_HANDLE;
1891 break;
1892 }
1893 rc = smbwrp_flistea(pConn->cli, &pConn->file, pchBuffer, cbBuffer);
1894 pFEAList = (FEALIST*)pchBuffer;
1895 if (rc)
1896 {
1897 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1898 switch (rc)
1899 {
1900 case ERROR_FILE_NOT_FOUND :
1901 case ERROR_PATH_NOT_FOUND :
1902 {
1903 pFEAList->cbList = sizeof(pFEAList->cbList);
1904 } /* Fall through */
1905 case ERROR_BUFFER_OVERFLOW :
1906 {
1907 rc = NO_ERROR;
1908 } break;
1909 default :
1910 {
1911 rc = ERROR_EAS_NOT_SUPPORTED;
1912 }
1913 }
1914 }
1915 *pulEASize = pFEAList->cbList;
1916 } while (0);
1917 free(pchBuffer);
1918 debuglocal(9,"NdpFileEASize %d %d\n", *pulEASize, rc);
1919
1920 return rc;
1921}
1922
1923int APIENTRY NdpFileSetInfo (HCONNECTION conn, NDFILEHANDLE handle, NDFILEINFOL *pfi)
1924{
1925 Connection *pConn = (Connection *)conn;
1926 Resource *pRes = pConn->pRes;
1927 int rc = 0;
1928 unsigned long action, attrFile;
1929
1930 debug_printf("NdpFileSetInfo in [%p]\n", pConn);
1931
1932 // delete the dir cache
1933 dircache_invalidate(pConn->file.fullname, pRes->pdc, 1);
1934
1935 do {
1936 if (pConn->file.fd < 0 || !*pConn->file.fname)
1937 {
1938 rc = ERROR_INVALID_HANDLE;
1939 break;
1940 }
1941 attrFile = pfi->stat.attrFile;
1942 // deferred setinfo - on closing the file
1943 pConn->file.openattr = attrFile;
1944 fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, &(pConn->file.mtime));
1945 debug_printf("NdpFileSetInfo mtime %d\n", pConn->file.mtime);
1946 } while (0);
1947 debuglocal(9,"NdpFileSetInfo <%s> %08x %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, attrFile, rc);
1948
1949 return NO_ERROR;
1950}
1951
1952int APIENTRY NdpFileSetFilePtrL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llOffset, ULONG ulMethod, LONGLONG *pllActual)
1953{
1954 Connection *pConn = (Connection *)conn;
1955 Resource *pRes = pConn->pRes;
1956 int rc = 0;
1957 unsigned long action;
1958
1959 debuglocal(9,"NdpFileSetFilePtrL in [%p]\n", pConn);
1960
1961 do {
1962 if (pConn->file.fd < 0)
1963 {
1964 rc = ERROR_INVALID_HANDLE;
1965 break;
1966 }
1967
1968 rc = smbwrp_lseek(pConn->cli, &pConn->file, ulMethod, llOffset);
1969 if (!rc)
1970 *pllActual = pConn->file.offset;
1971
1972 } while (0);
1973 debuglocal(9,"NdpFileSetFilePtrL <%s> %lld %lu %lld %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llOffset, ulMethod, *pllActual, rc);
1974
1975 return rc;
1976}
1977
1978int APIENTRY NdpFileSetFilePtr (HCONNECTION conn, NDFILEHANDLE handle, LONG lOffset, ULONG ulMethod, ULONG *pulActual)
1979{
1980 LONGLONG llActual;
1981 int rc = NdpFileSetFilePtrL(conn, handle, lOffset, ulMethod, &llActual);
1982 *pulActual = llActual & 0xFFFFFFFF;
1983 debuglocal(9,"NdpFileSetFilePtr %ld %lu %ld %d\n", lOffset, ulMethod, *pulActual, rc);
1984 return rc;
1985}
1986
1987int APIENTRY NdpFileClose (HCONNECTION conn, NDFILEHANDLE handle)
1988{
1989 Connection *pConn = (Connection *)conn;
1990 Resource *pRes = pConn->pRes;
1991 int rc = 0;
1992 unsigned long action;
1993
1994 debuglocal(9,"NdpFileClose in [%p] %d <%s>\n", pConn, pConn->file.fd, pConn->file.fd < 0 ? "!null!" : pConn->file.fname);
1995
1996 do {
1997 if (pConn->file.fd < 0)
1998 {
1999 rc = ERROR_INVALID_HANDLE;
2000 break;
2001 }
2002
2003 rc = smbwrp_close(pConn->cli, &pConn->file);
2004
2005 } while (0);
2006 debuglocal(9,"NdpFileClose %d %d\n", pConn->file.fd, rc);
2007
2008 pConn->file.fd = -1;
2009 return rc;
2010}
2011
2012int APIENTRY NdpFileCommit (HCONNECTION conn, NDFILEHANDLE handle)
2013{
2014 debuglocal(9,"NdpFileCommit %d\n", NO_ERROR);
2015 return NO_ERROR;
2016}
2017
2018
2019int APIENTRY NdpFileNewSize (HCONNECTION conn, NDFILEHANDLE handle, ULONG ulLen)
2020{
2021 int rc = NdpFileNewSizeL(conn, handle, ulLen);
2022 debuglocal(9,"NdpFileNewSize %ld %d\n", ulLen, rc);
2023 return rc;
2024}
2025
2026int APIENTRY NdpFileNewSizeL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llLen)
2027{
2028 Connection *pConn = (Connection *)conn;
2029 Resource *pRes = pConn->pRes;
2030 int rc = 0;
2031 unsigned long action;
2032
2033 debuglocal(9,"NdpFileNewSizeL in [%p]\n", pConn);
2034
2035 do {
2036 if (pConn->file.fd < 0)
2037 {
2038 rc = ERROR_INVALID_HANDLE;
2039 break;
2040 }
2041
2042 rc = smbwrp_setfilesize(pConn->cli, &pConn->file, llLen);
2043
2044 } while (0);
2045 debuglocal(9,"NdpFileNewSizeL <%s> %lld %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llLen, rc);
2046
2047 return rc;
2048}
2049
2050#define NDPSMB_READ_MAX_SIZE (65536 - 4096)
2051
2052int APIENTRY NdpFileRead (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulRead, ULONG *pulActual)
2053{
2054 Connection *pConn = (Connection *)conn;
2055 Resource *pRes = pConn->pRes;
2056 int rc = 0;
2057 unsigned long done = 0;
2058 unsigned long onedone;
2059 unsigned long action;
2060 ULONG ulReadCompleted = 0;
2061
2062 debuglocal(9,"NdpFileRead in [%p]\n", pConn);
2063
2064 do {
2065 if (pConn->file.fd < 0)
2066 {
2067 rc = ERROR_INVALID_HANDLE;
2068 break;
2069 }
2070 while (ulReadCompleted < ulRead)
2071 {
2072 ULONG ulActual;
2073 ULONG ulToRead = ulRead - ulReadCompleted;
2074 debuglocal(9,"NdpFileRead completed %d, to read %d\n", ulReadCompleted, ulToRead);
2075 if (ulToRead > NDPSMB_READ_MAX_SIZE)
2076 {
2077 ulToRead = NDPSMB_READ_MAX_SIZE;
2078 }
2079 rc = smbwrp_read(pConn->cli, &pConn->file, (char *)pBuffer + ulReadCompleted, ulToRead, &ulActual);
2080 if (ulActual == 0 || rc != NO_ERROR)
2081 {
2082 break;
2083 }
2084 ulReadCompleted += ulActual;
2085 }
2086 //*pulActual = ulRead;
2087 //DosSleep(0);
2088
2089 } while (0);
2090
2091 if (ulReadCompleted > 0)
2092 {
2093 rc = NO_ERROR; /* Still were able to read some data. */
2094 }
2095
2096 if (rc == NO_ERROR)
2097 {
2098 *pulActual = ulReadCompleted;
2099 }
2100
2101 debuglocal(9,"NdpFileRead <%s> %lu %lu %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead, *pulActual, rc);
2102
2103 return rc;
2104}
2105
2106int APIENTRY NdpFileWrite (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulWrite, ULONG *pulActual)
2107{
2108 Connection *pConn = (Connection *)conn;
2109 Resource *pRes = pConn->pRes;
2110 int rc = 0;
2111 unsigned long done = 0;
2112 unsigned long onedone;
2113 unsigned long action;
2114
2115 debuglocal(9,"NdpFileWrite in [%p]\n", pConn);
2116
2117 /* delete the dir cache
2118 this was moved from NdpFileClose() becasue if there are a lot files in the tree all are reread
2119 the problem when moved to here is, that last accessed time is not refreshed
2120 if this is needed, a new function needs to be done to update only one file in the cache */
2121 dircache_invalidate(pConn->file.fullname, pRes->pdc, 1);
2122
2123 do {
2124 if (pConn->file.fd < 0)
2125 {
2126 rc = ERROR_INVALID_HANDLE;
2127 break;
2128 }
2129 rc = smbwrp_write(pConn->cli, &pConn->file, pBuffer, ulWrite, pulActual);
2130
2131 } while (0);
2132 debuglocal(9,"NdpFileWrite <%s> %lu %lu %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulWrite, *pulActual, rc);
2133
2134 return rc;
2135}
2136
Note: See TracBrowser for help on using the repository browser.