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

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

samba client 2.1: read fixes, more caching

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