source: branches/client-3.0/src/smbwrp.c@ 891

Last change on this file since 891 was 887, checked in by Yuri Dario, 10 years ago

Fix return code check from samba library, fixes crash in EAs handling when not supported by server.

  • Property svn:eol-style set to native
File size: 30.0 KB
Line 
1/*
2 Netdrive Samba client plugin
3 samba library wrappers
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 "includes.h"
22#include "rpc_client/cli_pipe.h"
23#include "librpc/gen_ndr/ndr_srvsvc_c.h"
24#include "libsmb/libsmb.h"
25#include "libsmb/clirap.h"
26#include "trans2.h"
27#include "smbwrp.h"
28
29/*
30 * Wrapper for cli_errno to return not connected error on negative fd
31 * Now returns an OS/2 return code instead of lerrno.
32 */
33int os2cli_errno(cli_state * cli)
34{
35 if (cli->fd == -1)
36 {
37 return maperror( ENOTCONN);
38 }
39 return maperror(cli_errno(cli));
40}
41
42void smbwrp_Logging()
43{
44 char slogfile[_MAX_PATH +1] = {0};
45 char slogfilename[] = "log.smbc";
46 char *env = getenv("LOGFILES");
47 if (env != NULL)
48 {
49 strncpy(slogfile, env, sizeof(slogfile) -1);
50 strncat(slogfile, "\\", sizeof(slogfile) - strlen(slogfile) -1);
51 strncat(slogfile, slogfilename, sizeof(slogfile) - strlen(slogfile) -1);
52 }
53 else
54 {
55 strncpy(slogfile, slogfilename, sizeof(slogfile) -1);
56 }
57
58 // init samba for debug messages
59 setup_logging(slogfile, false);
60 lp_set_logfile(slogfile);
61 debug_parse_levels("10");
62
63}
64const char * smbwrp_getVersion()
65{
66 return samba_version_string();
67}
68
69int _System smbwrp_getclisize(void)
70{
71 return sizeof(struct cli_state);
72}
73
74/*****************************************************
75initialise structures
76*******************************************************/
77int _System smbwrp_init(void)
78{
79 static int initialised = 0;
80 char *p;
81
82 if (initialised)
83 {
84 return 0;
85 }
86 initialised = 1;
87
88 lp_set_in_client(true); /* Make sure that we tell lp_load we are client */
89
90 load_case_tables();
91
92 if (!lp_load(get_dyn_CONFIGFILE(),true,false,false,true)) {
93 debuglocal(0,("The initial smb.conf is missing, defaults are used!\n"));
94 }
95
96 load_interfaces();
97
98 if (!init_names())
99 {
100 return 1;
101 }
102
103 if (writeLog())
104 {
105 smbwrp_Logging();
106 }
107
108/*
109 if ((p=smbw_getshared("RESOLVE_ORDER"))) {
110 lp_set_name_resolve_order(p);
111 }
112*/
113 return 0;
114
115}
116
117void smbwrp_initthread(void)
118{
119 /*
120 Block SIGPIPE (from lib/util_sock.c: write())
121 It is not needed and should not stop execution
122 */
123 BlockSignals(True, SIGPIPE);
124}
125
126#if 0
127/*****************************************************
128remove redundent stuff from a filename
129*******************************************************/
130void clean_fname(char *name)
131{
132 char *p, *p2;
133 int l;
134 int modified = 1;
135
136 if (!name) return;
137
138 while (modified) {
139 modified = 0;
140
141 if ((p=strstr(name,"/./"))) {
142 modified = 1;
143 while (*p) {
144 p[0] = p[2];
145 p++;
146 }
147 }
148
149 if ((p=strstr(name,"//"))) {
150 modified = 1;
151 while (*p) {
152 p[0] = p[1];
153 p++;
154 }
155 }
156
157 if (strcmp(name,"/../")==0) {
158 modified = 1;
159 name[1] = 0;
160 }
161
162 if ((p=strstr(name,"/../"))) {
163 modified = 1;
164 for (p2=(p>name?p-1:p);p2>name;p2--) {
165 if (p2[0] == '/') break;
166 }
167 while (*p2) {
168 p2[0] = p2[3];
169 p2++;
170 }
171 }
172
173 if (strcmp(name,"/..")==0) {
174 modified = 1;
175 name[1] = 0;
176 }
177
178 l = strlen(name);
179 p = l>=3?(name+l-3):name;
180 if (strcmp(p,"/..")==0) {
181 modified = 1;
182 for (p2=p-1;p2>name;p2--) {
183 if (p2[0] == '/') break;
184 }
185 if (p2==name) {
186 p[0] = '/';
187 p[1] = 0;
188 } else {
189 p2[0] = 0;
190 }
191 }
192
193 l = strlen(name);
194 p = l>=2?(name+l-2):name;
195 if (strcmp(p,"/.")==0) {
196 if (p == name) {
197 p[1] = 0;
198 } else {
199 p[0] = 0;
200 }
201 }
202
203 if (strncmp(p=name,"./",2) == 0) {
204 modified = 1;
205 do {
206 p[0] = p[2];
207 } while (*p++);
208 }
209
210 l = strlen(p=name);
211 if (l > 1 && p[l-1] == '/') {
212 modified = 1;
213 p[l-1] = 0;
214 }
215 }
216}
217#endif
218
219/*****************************************************
220return a connection to a server
221*******************************************************/
222int _System smbwrp_connect( Resource* pRes, cli_state ** cli)
223{
224 smbwrp_server * srv = &pRes->srv;
225 char * server = srv->server_name;
226 char * share = *(srv->share_name) ? srv->share_name : "IPC$";
227 char * workgroup = srv->workgroup;
228 struct nmb_name called, calling;
229 char *p, *server_n = server;
230 fstring group;
231 struct sockaddr_storage ss;
232 struct cli_state * c;
233 char* dev_type;
234 int loginerror = 0;
235 NTSTATUS status;
236
237 zero_sockaddr(&ss);
238
239 debuglocal(1,"Connecting to \\\\%s:*********@%s:%s\\%s. Master %s:%d\n", srv->username, workgroup, server, share, srv->master, srv->ifmastergroup);
240
241 if (!*server) {
242 struct sockaddr_storage sip;
243
244 if (*workgroup)
245 {
246 if (!find_master_ip(workgroup, &sip)) {
247 return 1;
248 }
249 fstrcpy(group, inet_ntoa(sip.sin_addr));
250 server_n = group;
251 } else
252 if (*srv->master)
253 {
254 if (srv->ifmastergroup)
255 {
256 if (!find_master_ip(srv->master, &sip)) {
257 return 11;
258 }
259 strncpy(srv->master, inet_ntoa(sip.sin_addr), sizeof(srv->master) - 1);
260 srv->ifmastergroup = 0;
261 }
262 server_n = srv->master;
263 } else
264 {
265 return 10;
266 }
267 }
268
269 make_nmb_name(&calling, global_myname(), 0x0);
270// make_nmb_name(&calling, "WORK", 0x0); // this machine name
271 make_nmb_name(&called , server_n, 0x20);
272
273 again:
274 zero_sockaddr(&ss);
275
276 /* have to open a new connection */
277 if (!(c=cli_initialise()))
278 {
279 return 2;
280 }
281
282 cli_set_timeout(c, 10000); /* 10 seconds. */
283
284 if (pRes->krb5support == 1)
285 {
286 debuglocal(1,"Kerberos support enabled\n");
287 c->use_kerberos = True;
288 }
289
290 if (!NT_STATUS_IS_OK(cli_connect(c, server_n, &ss)))
291 {
292 return 3;
293 }
294
295 if (!cli_session_request(c, &calling, &called)) {
296 cli_shutdown(c);
297 if (strcmp(called.name, "*SMBSERVER")) {
298 make_nmb_name(&called , "*SMBSERVER", 0x20);
299 goto again;
300 }
301 return 4;
302 }
303
304 debuglocal(4," session request ok\n");
305
306 if (!NT_STATUS_IS_OK(cli_negprot(c))) {
307 cli_shutdown(c);
308 return 5;
309 }
310
311 debuglocal(4," session setuping for <%s>/<********> in <%s> %08x %08x %08x\n", srv->username, workgroup, c->protocol, c->sec_mode, c->capabilities);
312
313 if (!NT_STATUS_IS_OK(cli_session_setup(c, srv->username,
314 srv->password, strlen(srv->password),
315 srv->password, strlen(srv->password),
316 workgroup))) {
317 debuglocal(4,"%s/******** login failed\n", srv->username);
318 loginerror = 1; // save the login error
319
320 /* try an anonymous login if it failed */
321 if (!NT_STATUS_IS_OK(cli_session_setup(c, "", "", 0,"", 0, workgroup))) {
322 debuglocal(4,"Anonymous login failed\n");
323 cli_shutdown(c);
324 return 6;
325 }
326 debuglocal(4,"Anonymous login successful\n");
327 status = cli_init_creds(c, "", lp_workgroup(), "");
328 } else {
329 status = cli_init_creds(c, srv->username, workgroup, srv->password);
330 }
331
332 if (!NT_STATUS_IS_OK(status)) {
333 debuglocal(4,"cli_init_creds() failed\n");
334 cli_shutdown(c);
335 // if loginerror is != 0 means normal login failed, but anonymous login worked
336 if (loginerror !=0)
337 return 6;
338 else
339 return 7;
340 }
341
342 debuglocal(4," session setup ok. Sending tconx <%s> <********>\n", share);
343
344 // YD ticket:58 we need to check resource type to avoid connecting to printers.
345 // dev type is set to IPC for IPC$, A: for everything else (printers use LPT1:)
346 if (!strcmp( share, "IPC$"))
347 dev_type = "IPC";
348 else
349 dev_type = "A:";
350
351 if (!NT_STATUS_IS_OK(cli_tcon_andx(c, share, dev_type,
352 srv->password, strlen(srv->password)+1))) {
353 cli_shutdown(c);
354 // if loginerror is != 0 means normal login failed, but anonymous login worked
355 if (loginerror !=0)
356 return 6;
357 else
358 return 7;
359 }
360
361 debuglocal(4," tconx ok. cli caps %08x\n", c->capabilities);
362
363 // save cli_state pointer
364 *cli = c;
365
366 return 0;
367}
368
369/*****************************************************
370close a connection to a server
371*******************************************************/
372void _System smbwrp_disconnect( Resource* pRes, cli_state * cli)
373{
374 if (pRes && cli)
375 {
376 // this call will free all buffers, close handles and free cli mem
377 cli_shutdown( cli);
378 }
379}
380
381
382
383/*****************************************************
384a wrapper for open()
385*******************************************************/
386int _System smbwrp_open(cli_state * cli, smbwrp_file * file)
387{
388 uint16_t fd = 0;
389
390 if (!cli || !file || !*file->fname)
391 {
392 return maperror(EINVAL);
393 }
394 if (file->denymode < DENY_ALL || file->denymode > DENY_NONE)
395 {
396 file->denymode = DENY_NONE;
397 }
398
399 debuglocal(4,"cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
400 if (!NT_STATUS_IS_OK(cli_open(cli, file->fname, file->openmode, file->denymode, &fd)))
401 {
402 return os2cli_errno(cli);
403 }
404 file->fd = fd;
405 file->updatetime = 0;
406 file->offset = 0;
407 return 0;
408}
409
410/*****************************************************
411a wrapper for read()
412*******************************************************/
413int _System smbwrp_read(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
414{
415 int ret;
416
417 if (!cli || !file || !buf || !result)
418 {
419 return maperror(EINVAL);
420 }
421
422 *result = 0;
423 ret = cli_read(cli, file->fd, buf, file->offset, count);
424 if (ret == -1)
425 {
426 return os2cli_errno(cli);
427 }
428
429 file->offset += ret;
430 *result = ret;
431 return 0;
432}
433
434
435
436/*****************************************************
437a wrapper for write()
438*******************************************************/
439int _System smbwrp_write(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
440{
441 NTSTATUS status;
442 size_t ret;
443
444 if (!cli || !file || !buf || !result)
445 {
446 return maperror(EINVAL);
447 }
448
449 *result = 0;
450//debuglocal(1,("Write %x %d %lld %d", cli, file->fd, file->offset, count));
451 status = cli_writeall(cli, file->fd, 0, buf, file->offset, count, &ret);
452 if (!NT_STATUS_IS_OK(status)) {
453 return os2cli_errno(cli);
454 }
455
456 file->updatetime = 1;
457 file->offset += ret;
458 *result = ret;
459 return 0;
460}
461
462/*****************************************************
463a wrapper for close()
464*******************************************************/
465int _System smbwrp_close(cli_state * cli, smbwrp_file * file)
466{
467 int rc = 0;
468 if (!cli || !file)
469 {
470 return maperror(EINVAL);
471 }
472
473 debuglocal(4,"smpwrp_close updatetime: %d\n", file->updatetime);
474
475 if (file->updatetime == 1)
476 {
477 file->mtime = time(NULL);
478 debuglocal(4,"cli_close new mtime %lu\n", file->mtime);
479 }
480
481 if (!NT_STATUS_IS_OK(cli_close(cli, file->fd)))
482 {
483 rc = os2cli_errno(cli);
484 }
485
486 if (!rc && (file->openattr || file->mtime || file->ctime))
487 {
488 debuglocal(4,"Set pathinfo on close %s %08x %d %d\n", file->fname, file->openattr, file->mtime, file->ctime);
489 if (!NT_STATUS_IS_OK(cli_setpathinfo_basic(cli, file->fname, file->ctime, 0, file->mtime, 0, file->openattr)))
490 {
491 debuglocal(4,"Set pathinfo on close failed %d\n", os2cli_errno(cli));
492 //rc = os2cli_errno(cli);
493 }
494 }
495
496 file->openattr = 0;
497 file->mtime = 0;
498 file->ctime = 0;
499 file->updatetime = 0;
500 file->fd = -1;
501 file->offset = 0;
502 *file->fname = 0;
503 return rc;
504}
505
506int _System smbwrp_setfilesize(cli_state * cli, smbwrp_file * file, long long newsize)
507{
508 int rc = 0;
509 if (!cli || !file)
510 {
511 return maperror(EINVAL);
512 }
513
514 debuglocal(4,"cli_setnewfilesize(%s) %lld\n", file->fname, newsize);
515 if (!NT_STATUS_IS_OK(cli_ftruncate(cli, file->fd, newsize)))
516 {
517 if (newsize)
518 {
519 rc = os2cli_errno(cli);
520 }
521
522 if (!NT_STATUS_IS_OK(cli_close(cli, file->fd)))
523 {
524 return os2cli_errno(cli);
525 }
526 uint16_t fd = 0;
527 file->fd = -1;
528 file->offset = 0;
529 file->openmode &= ~(O_CREAT | O_EXCL);
530 file->openmode |= O_TRUNC;
531 debuglocal(4,"cli_setnewfileszie : cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
532 if (!NT_STATUS_IS_OK(cli_open(cli, file->fname, file->openmode, file->denymode, &fd)))
533 {
534 return os2cli_errno(cli);
535 }
536 file->fd = fd;
537 }
538 return 0;
539}
540
541/*****************************************************
542a wrapper for rename()
543*******************************************************/
544int _System smbwrp_rename(cli_state * cli, char *oldname, char *newname)
545{
546 if (!cli || !oldname || !newname)
547 {
548 return maperror(EINVAL);
549 }
550
551 debuglocal(1,"Rename <%s> -> <%s>\n", oldname, newname);
552 if (!NT_STATUS_IS_OK(cli_rename(cli, oldname, newname)))
553 {
554 return os2cli_errno(cli);
555 }
556 return 0;
557}
558
559
560/*****************************************************
561a wrapper for chmod()
562*******************************************************/
563int _System smbwrp_setattr(cli_state * cli, smbwrp_fileinfo *finfo)
564{
565 if (!cli || !finfo || !*finfo->fname)
566 {
567 return maperror(EINVAL);
568 }
569
570debuglocal(4,"Setting on <%s> attr %04x, time %lu (timezone /%lu\n", finfo->fname, finfo->attr, finfo->mtime, finfo->mtime + get_time_zone(finfo->mtime));
571 // we already have gmt time, so no need to add timezone
572 // if (!cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime + (finfo->mtime == 0 ? 0 : get_time_zone(finfo->mtime)))
573 if (!NT_STATUS_IS_OK(cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime))
574 && !NT_STATUS_IS_OK(cli_setatr(cli, finfo->fname, finfo->attr, 0)))
575 {
576 return os2cli_errno(cli);
577 }
578 return 0;
579}
580
581/*****************************************************
582a wrapper for unlink()
583*******************************************************/
584int _System smbwrp_unlink(cli_state * cli, const char *fname)
585{
586 if (!cli || !fname)
587 {
588 return maperror(EINVAL);
589 }
590#if 0
591 if (strncmp(cli->dev, "LPT", 3) == 0)
592 {
593 int job = smbw_stat_printjob(cli, fname, NULL, NULL);
594 if (job == -1)
595 {
596 goto failed;
597 }
598 if (cli_printjob_del(cli, job) != 0)
599 {
600 goto failed;
601 }
602 } else
603#endif
604 if (!NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN)))
605 {
606 return os2cli_errno(cli);
607 }
608 return 0;
609}
610
611/*****************************************************
612a wrapper for lseek()
613*******************************************************/
614int _System smbwrp_lseek(cli_state * cli, smbwrp_file * file, int whence, long long offset)
615{
616 off_t size;
617 if (!cli || !file)
618 {
619 return maperror(EINVAL);
620 }
621
622 debuglocal(4,"lseek %d %lld %lld\n", whence, offset, file->offset);
623
624 switch (whence) {
625 case SEEK_SET:
626 if (offset < 0)
627 {
628 return maperror(EINVAL);
629 }
630 file->offset = offset;
631 break;
632 case SEEK_CUR:
633 file->offset += offset;
634 break;
635 case SEEK_END:
636 if (offset > 0)
637 {
638 return maperror(EINVAL);
639 }
640 if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(cli, file->fd,
641 NULL, &size, NULL, NULL, NULL,
642 NULL, NULL)) &&
643 !NT_STATUS_IS_OK(cli_getattrE(cli, file->fd,
644 NULL, &size, NULL, NULL, NULL)))
645 {
646 return os2cli_errno(cli);
647 }
648 file->offset = size + offset;
649 break;
650 default: return maperror(EINVAL);
651 }
652
653 return 0;
654}
655
656/*****************************************************
657try to do a QPATHINFO and if that fails then do a getatr
658this is needed because win95 sometimes refuses the qpathinfo
659*******************************************************/
660int _System smbwrp_getattr(smbwrp_server *srv, cli_state * cli, smbwrp_fileinfo *finfo)
661{
662 SMB_INO_T ino = 0;
663 struct timespec ctime;
664 struct timespec mtime;
665 struct timespec atime;
666
667 if (!cli || !finfo || !*finfo->fname)
668 {
669 return maperror(EINVAL);
670 }
671 debuglocal(4,"getattr %d %d <%s>\n", cli->capabilities & CAP_NOPATHINFO2, cli->capabilities & CAP_NT_SMBS, finfo->fname);
672 if (!(cli->capabilities & CAP_NOPATHINFO2) &&
673 NT_STATUS_IS_OK(cli_qpathinfo2(cli, finfo->fname, &ctime, &atime, &mtime, NULL,
674 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino)))
675 {
676 finfo->attr &= 0x7F;
677 finfo->ctime = convert_timespec_to_time_t(ctime);
678 finfo->atime = convert_timespec_to_time_t(atime);
679 finfo->mtime = convert_timespec_to_time_t(mtime);
680 return 0;
681 }
682
683 if (cli->fd == -1)
684 {
685 /* fd == -1 means the connection is broken */
686 return maperror(ENOTCONN);
687 }
688
689 /* If the path is not on a share (it is a workgroup or a server),
690 * then cli_qpathinfo2 obviously fails. Return some fake information
691 * about the directory.
692 */
693 if ( *srv->server_name == 0
694 || (strcmp(cli->dev,"IPC") == 0)
695 || *srv->share_name == 0
696 || (stricmp(srv->share_name,"IPC$") == 0)
697 || (strncmp(cli->dev,"LPT",3) == 0)
698 )
699 {
700 debuglocal(4,"getattr not a share.\n");
701 *(time_t *)&finfo->ctime = time (NULL);
702 *(time_t *)&finfo->atime = time (NULL);
703 *(time_t *)&finfo->mtime = time (NULL);
704 finfo->size = 0;
705 finfo->easize = 0;
706 finfo->attr = aDIR;
707 return 0;
708 }
709
710 /* if this is NT then don't bother with the getatr */
711 if (cli->capabilities & CAP_NT_SMBS && !(cli->capabilities & CAP_NOPATHINFO2))
712 {
713 int ret = cli_errno(cli);
714 // cli_qpathinfo* reports EINVAL when path of given file not exists
715 // thus there is no real situation when EINVAL should be returned to
716 // client at this point, we just replace it to ENOTDIR
717 if (ret == EINVAL)
718 {
719 ret = ENOTDIR;
720 }
721 return maperror(ret);
722 }
723
724 if (NT_STATUS_IS_OK(cli_getatr(cli, finfo->fname, (unsigned short *)&finfo->attr, &finfo->size, (time_t *)&finfo->mtime)))
725 {
726//debuglocal(2,("gotattr1 %08x <%s>\n", finfo->attr, finfo->fname));
727 finfo->mtime -= get_time_zone(finfo->mtime);
728 finfo->atime = finfo->atime; //was mtime
729 finfo->ctime = finfo->ctime; //was mtime
730 cli->capabilities &= CAP_NOPATHINFO2;
731 return 0;
732 }
733 return os2cli_errno(cli);
734}
735
736/*****************************************************
737try to do a QPATHINFO and if that fails then do a getatr
738this is needed because win95 sometimes refuses the qpathinfo
739*******************************************************/
740int _System smbwrp_fgetattr(cli_state * cli, smbwrp_file *file, smbwrp_fileinfo *finfo)
741{
742 struct timespec ctime;
743 struct timespec mtime;
744 struct timespec atime;
745 SMB_INO_T ino = 0;
746
747 if (!cli || !file || !finfo)
748 {
749 return maperror(EINVAL);
750 }
751
752 strncpy(finfo->fname, file->fname, sizeof(finfo->fname) - 1);
753 if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(cli, file->fd,
754 (unsigned short *)&finfo->attr, (off_t *)&finfo->size, &ctime, &atime, &mtime, NULL,
755 &ino)))
756 {
757 if (!NT_STATUS_IS_OK(cli_getattrE(cli, file->fd,
758 (unsigned short *)&finfo->attr, (&finfo->size), (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime)))
759 {
760 return os2cli_errno(cli);
761 }
762 else
763 {
764 finfo->ctime -= get_time_zone(finfo->ctime);
765 finfo->atime -= get_time_zone(finfo->atime);
766 finfo->mtime -= get_time_zone(finfo->mtime);
767 }
768 }
769 else
770 {
771 finfo->ctime = convert_timespec_to_time_t(ctime);
772 finfo->atime = convert_timespec_to_time_t(atime);
773 finfo->mtime = convert_timespec_to_time_t(mtime);
774 }
775
776 return 0;
777}
778
779// =============================DIRECTORY ROUTINES============================
780
781/*****************************************************
782add a entry to a directory listing
783*******************************************************/
784static void smbwrp_dir_add(const char* mnt, smbwrp_fileinfo *finfo, const char *mask, void *state)
785{
786 if (state && finfo)
787 {
788 filelist_state * st = (filelist_state *)state;
789 char fullname[ _MAX_PATH] = {0};
790 debuglocal(8,"adding <%s> %d %d %d\n", finfo->fname, sizeof(st->finfo), st->datalen, sizeof(st->finfo.fname));
791 memcpy(&st->finfo, finfo, sizeof(st->finfo));
792 strncpy(fullname, st->dir, strlen(st->dir));
793 strncat(fullname, finfo->fname, sizeof(fullname) - strlen(fullname) -1);
794 strncpy(st->finfo.fname, fullname, sizeof(st->finfo.fname));
795 getfindinfoL( st->pConn, st->plist, &st->finfo, st->ulAttribute, st->dir_mask);
796 }
797}
798
799static void smbwrp_special_add(const char * name, void * state)
800{
801 smbwrp_fileinfo finfo = {0};
802
803 if (!name)
804 {
805 return;
806 }
807
808 ZERO_STRUCT(finfo);
809
810 strncpy(finfo.fname, name, sizeof(finfo.fname) - 1);
811 finfo.attr = aRONLY | aDIR;
812
813 smbwrp_dir_add("", &finfo, NULL, state);
814}
815
816static void smbwrp_printjob_add(struct print_job_info *job, void * state)
817{
818 smbwrp_fileinfo finfo = {0};
819
820 ZERO_STRUCT(finfo);
821
822//printf("Printjob <%s>\n", job->name);
823
824 strncpy(finfo.fname, job->name, sizeof(finfo.fname) - 1);
825 finfo.mtime = job->t - get_time_zone(job->t);
826 finfo.atime = finfo.atime; //was mtime
827 finfo.ctime = finfo.ctime; //was mtime
828 finfo.attr = aRONLY;
829 finfo.size = job->size;
830
831 smbwrp_dir_add("", &finfo, NULL, state);
832}
833
834static void smbwrp_share_add(const char *share, uint32 type,
835 const char *comment, void *state)
836{
837 smbwrp_fileinfo finfo = {0};
838
839 // strip administrative names and printers from list
840 if (type == STYPE_PRINTQ || strcmp(share,"IPC$") == 0) return;
841
842 ZERO_STRUCT(finfo);
843
844 strncpy(finfo.fname, share, sizeof(finfo.fname) - 1);
845 finfo.attr = aRONLY | aDIR;
846
847 smbwrp_dir_add("", &finfo, NULL, state);
848}
849
850/****************************************************************************
851 Do a directory listing, calling fn on each file found.
852 Modified from cli_list
853****************************************************************************/
854static int list_files(struct cli_state *cli, const char *mask, uint16 attribute,
855 void (*fn)(const char *, smbwrp_fileinfo *, const char *,
856 void *), void *state)
857{
858 TALLOC_CTX *frame = talloc_stackframe();
859 struct event_context *ev;
860 struct tevent_req *req;
861 NTSTATUS status = NT_STATUS_NO_MEMORY;
862 struct file_info *finfo;
863 size_t i, num_finfo;
864 uint16_t info_level;
865 void *dircachectx = NULL;
866 smbwrp_fileinfo wrpfinfo;
867
868 /* Try to get the listing from cache. */
869 if (dircache_list_files(fn, state, &num_finfo))
870 {
871 /* Got from cache. */
872 return(num_finfo);
873 }
874
875 if (cli_has_async_calls(cli)) {
876 /*
877 * Can't use sync call while an async call is in flight
878 */
879 status = NT_STATUS_INVALID_PARAMETER;
880 goto fail;
881 }
882 ev = event_context_init(frame);
883 if (ev == NULL) {
884 goto fail;
885 }
886
887 info_level = (cli->capabilities & CAP_NT_SMBS)
888 ? SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_EA_SIZE;
889
890 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, mask);
891
892 req = cli_list_send(frame, ev, cli, mask, attribute, info_level);
893 if (req == NULL) {
894 goto fail;
895 }
896 if (!tevent_req_poll(req, ev)) {
897 status = map_nt_error_from_unix(errno);
898 goto fail;
899 }
900
901 status = cli_list_recv(req, frame, &finfo, &num_finfo);
902 if (!NT_STATUS_IS_OK(status)) {
903 goto fail;
904 }
905
906 dircachectx = dircache_write_begin(state, num_finfo);
907
908 debuglocal(4,"list_files: got %d files\n", num_finfo);
909
910
911 for (i=0; i<num_finfo; i++) {
912 //as samba and this client have different finfo, we need to convert
913 memset(&wrpfinfo, 0, sizeof(wrpfinfo));
914 wrpfinfo.size = finfo[i].size;
915 wrpfinfo.attr = finfo[i].mode;
916 wrpfinfo.ctime = convert_timespec_to_time_t(finfo[i].ctime_ts);
917 wrpfinfo.mtime = convert_timespec_to_time_t(finfo[i].mtime_ts);
918 wrpfinfo.atime = convert_timespec_to_time_t(finfo[i].atime_ts);
919 wrpfinfo.easize = finfo[i].easize;
920 strncpy(wrpfinfo.fname, finfo[i].name, sizeof(wrpfinfo.fname) -1);
921
922 fn(cli->dfs_mountpoint, &wrpfinfo, mask, state);
923 // Also add the entry to the cache.
924 dircache_write_entry(dircachectx, &wrpfinfo);
925 }
926
927 dircache_write_end(dircachectx);
928 fail:
929 TALLOC_FREE(frame);
930 return num_finfo;
931}
932
933/*****************************************************
934open a directory on the server
935*******************************************************/
936int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
937{
938 if (!srv || !cli || !state || !*state->mask)
939 {
940 return maperror(EINVAL);
941 }
942 debuglocal(1,"Filelist <%s> on master <%s> wgrp <%s> server <%s> share <%s> clidev <%s>\n", state->mask, srv->master, srv->workgroup, srv->server_name, srv->share_name, cli->dev);
943 if (*srv->workgroup == 0 && *srv->server_name == 0)
944 {
945 smbwrp_special_add(".", state);
946 smbwrp_special_add("..", state);
947 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
948 smbwrp_share_add, state);
949 } else
950 if (*srv->server_name == 0)
951 {
952 smbwrp_special_add(".", state);
953 smbwrp_special_add("..", state);
954
955 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
956 smbwrp_share_add, state);
957 } else
958 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
959 {
960 smbwrp_special_add(".", state);
961 smbwrp_special_add("..", state);
962
963 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
964 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
965 {
966 return os2cli_errno(cli);
967 }
968 } else
969 if (strncmp(cli->dev,"LPT",3) == 0)
970 {
971 smbwrp_special_add(".", state);
972 smbwrp_special_add("..", state);
973 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
974 {
975 return os2cli_errno(cli);
976 }
977 }
978 else
979 {
980 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
981 smbwrp_dir_add, state) < 0)
982 {
983 return os2cli_errno(cli);
984 }
985 }
986
987 return 0;
988}
989
990/*****************************************************
991a wrapper for chdir()
992*******************************************************/
993int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
994{
995 unsigned short mode = aDIR;
996 smbwrp_fileinfo finfo = {0};
997 if (!cli || !fname)
998 {
999 return maperror(EINVAL);
1000 }
1001
1002 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1003 if (smbwrp_getattr(srv, cli, &finfo))
1004 {
1005 return os2cli_errno(cli);
1006 }
1007
1008 if (!(finfo.attr & aDIR)) {
1009 return maperror(ENOTDIR);
1010 }
1011
1012 return 0;
1013}
1014
1015
1016/*****************************************************
1017a wrapper for mkdir()
1018*******************************************************/
1019int _System smbwrp_mkdir(cli_state * cli, char *fname)
1020{
1021 if (!cli || !fname)
1022 {
1023 return maperror(EINVAL);
1024 }
1025
1026 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname)))
1027 {
1028 return os2cli_errno(cli);
1029 }
1030 return 0;
1031}
1032
1033/*****************************************************
1034a wrapper for rmdir()
1035*******************************************************/
1036int _System smbwrp_rmdir(cli_state * cli, char *fname)
1037{
1038 if (!cli || !fname)
1039 {
1040 return maperror(EINVAL);
1041 }
1042
1043 if (!NT_STATUS_IS_OK(cli_rmdir(cli, fname)))
1044 {
1045 return os2cli_errno(cli);
1046 }
1047 return 0;
1048}
1049
1050/*****************************************************
1051set EA for a path
1052*******************************************************/
1053int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1054{
1055 if (!cli || !fname || !name)
1056 {
1057 return maperror(EINVAL);
1058 }
1059 if (!NT_STATUS_IS_OK(cli_set_ea_path(cli, fname, name, value, size)))
1060 {
1061 return os2cli_errno(cli);
1062 }
1063 return 0;
1064}
1065
1066/*****************************************************
1067set EA for a file
1068*******************************************************/
1069int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1070{
1071 if (!cli || !file || !name)
1072 {
1073 return maperror(EINVAL);
1074 }
1075 if (!NT_STATUS_IS_OK(cli_set_ea_fnum(cli, file->fd, name, value, size)))
1076 {
1077 return os2cli_errno(cli);
1078 }
1079 return 0;
1080}
1081
1082
1083#pragma pack(1)
1084typedef struct _FEA /* fea */
1085{
1086 unsigned char fEA; /* flags */
1087 unsigned char cbName; /* name length not including NULL */
1088 unsigned short cbValue; /* value length */
1089} FEA;
1090
1091typedef struct _FEALIST /* feal */
1092{
1093 unsigned long cbList; /* total bytes of structure including full list */
1094 FEA list[1]; /* variable length FEA structures */
1095} FEALIST;
1096#pragma pack()
1097
1098static int unilistea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1099{
1100 int fnum, i;
1101 int gotsize = sizeof(unsigned long);
1102 size_t num_eas;
1103 struct ea_struct *ea_list = NULL;
1104 TALLOC_CTX *mem_ctx;
1105 FEA * p;
1106 FEALIST * pfealist;
1107 char * q;
1108
1109 mem_ctx = talloc_init("%d: ealist", _gettid());
1110 pfealist = (FEALIST *)buffer;
1111 pfealist->cbList = 0;
1112
1113 if (!NT_STATUS_IS_OK(cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)))
1114 {
1115 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1116 talloc_destroy(mem_ctx);
1117 return os2cli_errno(cli);
1118 }
1119
1120 debuglocal(4,"num_eas = %d\n", num_eas);
1121
1122 // we will count that os/2 max EA size for file is 64kb
1123 p = pfealist->list;
1124 for (i = 0; i < num_eas; i++)
1125 {
1126 int namelen = strlen(ea_list[i].name);
1127 debuglocal(4, "%d Got EA <%s> with namelen %d, size %d. Gross %d. Buf %d\n", i, ea_list[i].name, namelen, ea_list[i].value.length, gotsize, size);
1128 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1129 {
1130 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1131 continue;
1132 }
1133 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1134 if (size >= gotsize)
1135 {
1136 p->fEA = 0;
1137 p->cbName = namelen;
1138 p->cbValue = ea_list[i].value.length;
1139 q = (char *)(p + 1);
1140 strncpy(q, ea_list[i].name, namelen + 1);
1141 q += namelen + 1;
1142 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1143 p = (FEA *)(q + ea_list[i].value.length);
1144 }
1145 }
1146 pfealist->cbList = gotsize;
1147 debuglocal(4,"ret size = %d\n", gotsize);
1148
1149 talloc_destroy(mem_ctx);
1150 return 0;
1151}
1152
1153/*****************************************************
1154lists EA of a path
1155*******************************************************/
1156int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1157{
1158 if (!cli || !fname || !buffer)
1159 {
1160 return maperror(EINVAL);
1161 }
1162
1163 debuglocal(4,"EALIst for <%s>\n", fname);
1164 return unilistea(cli, fname, buffer, size);
1165}
1166
1167/*****************************************************
1168lists EA of a file
1169*******************************************************/
1170int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1171{
1172 if (!cli || !file || !buffer)
1173 {
1174 return maperror(EINVAL);
1175 }
1176
1177 debuglocal(4,"FEALIst for <%s>\n", file->fname);
1178 return unilistea(cli, file->fname, buffer, size);
1179}
1180
1181/****************************************************************************
1182Check the space on a device.
1183****************************************************************************/
1184int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1185{
1186 int total, bsize, avail;
1187
1188 if (!cli || !pfsa)
1189 {
1190 return maperror(EINVAL);
1191 }
1192
1193 if (!NT_STATUS_IS_OK(cli_dskattr(cli, &bsize, &total, &avail)))
1194 {
1195 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1196 return os2cli_errno(cli);
1197 }
1198
1199 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1200 total, bsize, avail);
1201
1202 // YD currently Samba return it in MB!
1203 pfsa->cSectorUnit = 1;
1204 if (bsize >= 65536)
1205 {
1206 pfsa->cUnit = total*1024;
1207 pfsa->cUnitAvail = avail*1024;
1208 pfsa->cbSector = bsize/1024;
1209 }
1210 else
1211 {
1212 pfsa->cUnit = total;
1213 pfsa->cUnitAvail = avail;
1214 pfsa->cbSector = bsize;
1215 }
1216
1217 return 0;
1218}
1219
Note: See TracBrowser for help on using the repository browser.