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

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

samba client 2.1: caching

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