source: branches/client-2.0/src/ndpsmb.c@ 497

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

samba client: caching

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