source: branches/client-2.1/src/ndpsmb.c

Last change on this file was 817, checked in by Silvan Scherrer, 12 years ago

Samba Client 2.1: timestamp work and some backport from 2.2 client

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