source: branches/client-1.5/src/ndpsmb.c@ 546

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

sambaclient 1.5: attemp to fix tz problems fixes ticket:56

  • Property svn:eol-style set to native
File size: 50.1 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
226static PLUGINHELPERTABLE2L *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
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, q = NULL;
477
478 t = 0;
479 rc = ph->fsphQueryUlongProperty (properties, "MASTERTYPE", &t);
480 if (!rc)
481 {
482 if (t > 1)
483 {
484 rc = ERROR_INVALID_PARAMETER;
485 }
486 else
487 {
488 pRes->srv.ifmastergroup = t;
489 }
490 }
491
492 t = 0;
493 rc = ph->fsphQueryUlongProperty (properties, "EASUPPORT", &t);
494 if (!rc)
495 {
496 if (t > 1)
497 {
498 rc = ERROR_INVALID_PARAMETER;
499 }
500 else
501 {
502 pRes->easupport = t;
503 }
504 }
505
506 return rc;
507}
508
509int iftestpath(char * path)
510{
511 char * p = path;
512 if (!path)
513 {
514 return 0;
515 }
516 while ((p = ph->fsphStrChr(p, 'A')) != NULL)
517 {
518 if (ph->fsphStrNCmp(p, "A.+,;=[].B", 10) == 0)
519 {
520 return 1;
521 }
522 p++;
523 }
524 return 0;
525}
526
527int pathparser(Resource *pRes, Connection * pConn, char * path, char * result)
528{
529 int rootlevel;
530 int rc = NO_ERROR;
531 if (!pRes || !path || !result)
532 {
533 return ERROR_INVALID_PARAMETER;
534 }
535 // handle special case when someone wants to test support of LFN or smth similar
536 if (iftestpath(path))
537 {
538 StrCpy(result, "\\A.+,;=[].B");
539 return NO_ERROR;
540 }
541
542 rootlevel = pRes->rootlevel;
543 if (*path == '\\') path++;
544
545 if (rootlevel < 3)
546 {
547 char * p;
548 // flag: 1 parameters changed, reconnection required, 0 do nothing
549 int newlevel = 0;
550 // use a temporary resource to test disconnection/reconnection
551 Resource tmpRes;
552 // copy exising data
553 memcpy( &tmpRes, pRes, sizeof( tmpRes));
554 // pointer to new connection fields
555 smbwrp_server * tmp = &tmpRes.srv;
556 if (rootlevel == 0)
557 {
558 p = ph->fsphStrChr(path, '\\');
559 if (!p)
560 {
561 p = path + StrLen(path);
562 }
563 if (StrLen(tmp->workgroup) != p - path
564 || (p == path || ph->fsphStrNICmp(path, tmp->workgroup, p - path)))
565 {
566 StrNCpy(tmp->workgroup, path, p - path);
567 tmp->workgroup[p - path] = 0;
568 newlevel = 1;
569 }
570 path = *p == '\\' ? p + 1 : p;
571 rootlevel = 1;
572 }
573 if (rootlevel == 1) // root path starts from server name
574 {
575 p = ph->fsphStrChr(path, '\\');
576 if (!p)
577 {
578 p = path + StrLen(path);
579 }
580 if (StrLen(tmp->server_name) != p - path
581 || (p == path || ph->fsphStrNICmp(path, tmp->server_name, p - path)))
582 {
583 StrNCpy(tmp->server_name, path, p - path);
584 tmp->server_name[p - path] = 0;
585 newlevel = 1;
586 }
587 path = *p == '\\' ? p + 1 : p;
588 rootlevel = 2;
589 }
590 if (rootlevel == 2) // root path starts from share name
591 {
592 p = ph->fsphStrChr(path, '\\');
593 if (!p)
594 {
595 p = path + StrLen(path);
596 }
597 if (StrLen(tmp->share_name) != (p - path)
598 || (p == path || ph->fsphStrNICmp(path, tmp->share_name, p - path)))
599 {
600 StrNCpy(tmp->share_name, path, p - path);
601 tmp->share_name[p - path] = 0;
602 newlevel = 1;
603 }
604 path = *p == '\\' ? p + 1 : p;
605 }
606 if (newlevel)
607 {
608 // reconnect to server here, first test new connection
609 cli_state* tmp_cli = NULL;
610 rc = smbwrp_connect( &tmpRes, &tmp_cli);
611 if (!rc)
612 {
613 // new connection is ok, disconnect old one
614 cli_state* cli = pConn->cli;
615 smbwrp_disconnect( pRes, cli);
616 // save tmp data structure
617 memcpy( pRes, &tmpRes, sizeof( tmpRes));
618 // save new connection handle
619 pConn->cli = tmp_cli;
620 }
621 }
622 }
623
624 StrCpy(result, "\\");
625 StrNCat(result, path, CCHMAXPATH);
626
627 return rc;
628}
629
630
631// -------------------------------------------------------------
632
633/* check if the requested resource is available */
634static int checkMountResource( Resource* pRes)
635{
636 int rc;
637 unsigned long action;
638 cli_state* cli = NULL;
639 smbwrp_file file;
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 MemSet(&pRes->srv, 0, sizeof(pRes->srv));
730 free(pRes);
731 debuglocal(9,"NdpFreeResource %d\n", NO_ERROR);
732 return NO_ERROR;
733}
734
735// -------------------------------------------------------------
736
737int APIENTRY NdpRsrcCompare (HRESOURCE resource, HRESOURCE resource2)
738{
739 Resource *pRes = (Resource *)resource;
740 Resource *pRes2 = (Resource *)resource2;
741 int rc = ND_RSRC_DIFFERENT;
742
743 debuglocal(9,"NdpRsrcCompare in\n");
744 if (ph->fsphStrICmp(pRes->srv.server_name, pRes2->srv.server_name) == 0
745 && ph->fsphStrICmp(pRes->srv.share_name, pRes2->srv.share_name) == 0
746 && ph->fsphStrICmp(pRes->srv.username, pRes2->srv.username) == 0
747 && ph->fsphStrICmp(pRes->srv.workgroup, pRes2->srv.workgroup) == 0)
748 {
749 // resources are equal
750 rc = ND_RSRC_EQUAL;
751 }
752
753 debuglocal(9,"NdpRsrcCompare %d\n", rc);
754
755 return rc;
756}
757
758int APIENTRY NdpRsrcUpdate (HRESOURCE resource, HRESOURCE resource2)
759{
760 // do nothing
761 debuglocal(9,"NdpRsrcUpdate %d\n", NO_ERROR);
762 return NO_ERROR;
763}
764
765int APIENTRY NdpRsrcQueryInfo (HRESOURCE resource, ULONG *pulFlags, void *pdata, ULONG insize, ULONG *poutlen)
766{
767 Resource *pRes = (Resource *)resource;
768 int rc = NO_ERROR;
769 char s[4096];
770
771 debuglocal(9,"NdpRsrcQueryInfo in\n");
772
773 switch (pRes->rootlevel)
774 {
775 case 0:
776 {
777 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s \\\\@%s", ifL ? "64" : "32", pRes->srv.username);
778 } break;
779 case 1:
780 {
781 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s %s: \\\\@%s", ifL ? "64" : "32", pRes->srv.workgroup, pRes->srv.username);
782 } break;
783 case 2:
784 {
785 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);
786 } break;
787 default:
788 {
789 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);
790 } break;
791 }
792 *poutlen = StrLen(s) + 1;
793 if (*poutlen > insize)
794 {
795 rc = ERROR_BUFFER_OVERFLOW;
796 }
797 else
798 {
799 MemCpy(pdata, s, *poutlen);
800 }
801
802 debuglocal(9,"NdpRsrcQueryInfo %d\n", rc);
803
804 return rc;
805}
806
807int APIENTRY NdpRsrcQueryFSAttach (HRESOURCE resource, void *pdata, ULONG insize, ULONG *poutlen)
808{
809 ULONG ulDummy = 0;
810 /* just return the resource info string */
811 return NdpRsrcQueryInfo (resource, &ulDummy, pdata, insize, poutlen);
812}
813
814int APIENTRY NdpRsrcQueryFSAllocate (HRESOURCE resource, NDFSALLOCATE *pfsa)
815{
816 Resource *pRes = (Resource *)resource;
817 int rc = NO_ERROR, rc1;
818 unsigned long action = 0;
819 smbwrp_file file;
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
966 rc = pathparser(pRes, pConn, szPath, path);
967 debuglocal(9,"NdpQueryPathInfo pathparser for <%s> rc=%d\n", path, rc);
968 switch (rc)
969 {
970 case NO_ERROR :
971 case ERROR_FILE_NOT_FOUND:
972 case ERROR_PATH_NOT_FOUND:
973 case ERROR_ACCESS_DENIED:
974 case ERROR_INVALID_PARAMETER:
975 {
976 break;
977 }
978 default :
979 {
980 rc = ERROR_PATH_NOT_FOUND;
981 }
982 }
983 if (rc)
984 {
985 break;
986 }
987 StrNCpy(finfo.fname, path, sizeof(finfo.fname) - 1);
988 debuglocal(9,"NdpQueryPathInfo smbwrp_getattr for <%s>\n", path);
989 rc = smbwrp_getattr( &pRes->srv, pConn->cli, &finfo);
990 if (rc)
991 {
992 // remote server not available for first time?
993 if (rc == ERROR_REM_NOT_LIST && retry == 0)
994 {
995 // free current cli resources
996 smbwrp_disconnect( pRes, pConn->cli);
997 // reconnect
998 smbwrp_connect( pRes, &pConn->cli);
999 // try file list again
1000 rc = smbwrp_getattr( &pRes->srv, pConn->cli, &finfo);
1001 debuglocal(9,"NdpQueryPathInfo remote connection lost, retry rc = %d\n", rc);
1002 }
1003 switch (rc)
1004 {
1005 case NO_ERROR :
1006 case ERROR_FILE_NOT_FOUND:
1007 case ERROR_PATH_NOT_FOUND:
1008 case ERROR_ACCESS_DENIED:
1009 case ERROR_INVALID_PARAMETER:
1010 case ERROR_REM_NOT_LIST:
1011 break;
1012 default :
1013 {
1014 rc = ERROR_PATH_NOT_FOUND;
1015 }
1016 }
1017 }
1018 else
1019 {
1020 finfo.easize = -1;
1021 getfindinfoL(pConn, plist, &finfo, 0, NULL);
1022 }
1023 if (rc == ERROR_FILE_NOT_FOUND)
1024 {
1025 // now try the upper path
1026 char * p = ph->fsphStrChr(finfo.fname, '\\');
1027 if (p && p > finfo.fname)
1028 {
1029 *p = 0;
1030 rc = smbwrp_getattr( &pRes->srv, pConn->cli, &finfo);
1031 if (rc)
1032 {
1033 debuglocal(9,"NdpQueryPathInfo upper path in <%s>, retry = %d\n", finfo.fname, retry);
1034 rc = rc ? ERROR_PATH_NOT_FOUND : ERROR_INVALID_PARAMETER;
1035 }
1036 }
1037 }
1038 } while (0);
1039 debuglocal(9,"NdpQueryPathInfo <%s> (%s) %d\n", szPath, path, rc);
1040
1041 return rc;
1042}
1043
1044// -------------------------------------------------------------
1045
1046int APIENTRY NdpFindStart (HCONNECTION conn, void *plist, NDFILEINFOL *pfiparent, char *szPath, ULONG ulAttribute)
1047{
1048 Connection *pConn = (Connection *)conn;
1049 Resource *pRes = pConn->pRes;
1050 int rc = NO_ERROR, count = 0;
1051 unsigned long action;
1052 char *mask = "*";
1053 char dir[CCHMAXPATH+1] = {0};
1054 char path[CCHMAXPATH+1] = {0};
1055 smbwrp_fileinfo * data;
1056 NDPATHELEMENT *pel = ph->fsphNameElem(0);
1057 filelist_state state;
1058 char * p;
1059
1060 debug_printf("NdpFindStart in\n");
1061
1062 StrNCpy(dir, szPath, sizeof(dir) - 1);
1063 if (pel)
1064 {
1065 mask = pel->name;
1066 dir[StrLen(szPath) - pel->length] = 0;
1067 }
1068 action = StrLen(dir) - 1;
1069 if (dir[action] == '\\')
1070 {
1071 dir[action] = 0;
1072 }
1073 rc = pathparser(pRes, pConn, dir, path);
1074 if (rc)
1075 {
1076 return rc;
1077 }
1078 action = StrLen(path) - 1;
1079 if (path[action] != '\\')
1080 {
1081 StrNCat(path, "\\", sizeof(path) - 1);
1082 }
1083 StrCpy(dir, path);
1084 StrNCat(path, mask, sizeof(path) - 1);
1085
1086 // this structure will be used by libsmb callbacks, so we store here all we need
1087 // to fill netdrive structures
1088 state.pConn = pConn;
1089 state.plist = plist;
1090 state.ulAttribute = ulAttribute;
1091 strcpy( state.dir, dir);
1092 strcpy( state.dir_mask, mask);
1093 strcpy( state.mask, path);
1094 p = getlastslash(state.mask);
1095 if (p)
1096 {
1097 *(p + 1) = '*';
1098 *(p + 2) = 0;
1099 }
1100 else
1101 {
1102 strcpy(state.mask, "\\*");
1103 }
1104 rc = smbwrp_filelist( &pRes->srv, pConn->cli, &state);
1105 // we need to handle reconnection also here, because NdpQueryPathInfo
1106 // could be called with '*' and exit then immediately (without calling libsmb)
1107 if (rc == ERROR_REM_NOT_LIST)
1108 {
1109 // free current cli resources
1110 smbwrp_disconnect( pRes, pConn->cli);
1111 // reconnect
1112 smbwrp_connect( pRes, &pConn->cli);
1113 // try file list again next loop
1114 rc = smbwrp_filelist( &pRes->srv, pConn->cli, &state);
1115 debuglocal(9,"NdpFindStart remote connection lost, retry rc = %d\n", rc);
1116 }
1117
1118 debuglocal(9,"NdpFindStart <%s> (%s) cnt %d %d\n", szPath, path, count, rc);
1119
1120 return rc;
1121}
1122
1123int APIENTRY NdpDeletePathInfo (HRESOURCE resource, NDFILEINFOL *pfi)
1124{
1125// debuglocal(9,"NdpDeletePathInfo %d\n", 0);
1126 return NO_ERROR;
1127}
1128
1129int APIENTRY NdpRefresh (HCONNECTION conn, char *path, int tree)
1130{
1131 debuglocal(9,"NdpRefresh <%s> %d\n", path, 0);
1132 return NO_ERROR;
1133}
1134
1135int APIENTRY NdpDiscardResourceData (HRESOURCE resource, NDDATABUF *pdatabuf)
1136{
1137 // The plugin do not have to deallocate anything
1138 // because resource data did not contain any pointers
1139 // to plugins data.
1140 // Data stored by fsphSetResourceData will be
1141 // deallocated by NetDrive.
1142
1143 debuglocal(9,"NdpDicardresourceData %d\n", 0);
1144 return NO_ERROR;
1145}
1146
1147int APIENTRY NdpSetPathInfo (HCONNECTION conn, NDFILEINFOL *pfi, char *szPathName)
1148{
1149 Connection *pConn = (Connection *)conn;
1150 Resource *pRes = pConn->pRes;
1151 int rc = 0;
1152 unsigned long action;
1153 char path[CCHMAXPATH+1] = {0};
1154 smbwrp_fileinfo finfo;
1155
1156 debug_printf("NdpSetPathInfo in FIXME\n");
1157
1158 do {
1159 rc = pathparser(pRes, pConn, szPathName, path);
1160 if (rc)
1161 {
1162 break;
1163 }
1164
1165 MemSet(&finfo, 0, sizeof(finfo));
1166
1167 StrNCpy(finfo.fname, path, sizeof(finfo.fname) - 1);
1168 fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, &(finfo.mtime));
1169 finfo.attr = pfi->stat.attrFile & 0x37;
1170 rc = smbwrp_setattr(pConn->cli, &finfo);
1171 } while (0);
1172 debuglocal(9,"NdpSetPathInfo <%s> (%s) %d\n", szPathName, path, rc);
1173
1174 return rc;
1175}
1176
1177int buildFEALIST(FEALIST *pFEASrc, GEALIST *pGEAList, FEALIST *pFEAList)
1178{
1179 int rc = 0;
1180 FEA * pfea;
1181 FEA * pfeadest;