source: branches/samba-3.0/source/ndpsmb/smbwrp.c@ 291

Last change on this file since 291 was 129, checked in by Yuri Dario, 17 years ago

Strip also printer shares from server enumeration. ticket:58.

  • Property svn:eol-style set to native
File size: 44.0 KB
Line 
1#include "includes.h"
2
3#include "smbwrp.h"
4
5#ifndef DEBUG_PRINTF
6#define debug_printf( ...)
7#endif
8
9static int
10net_share_enum_rpc(struct cli_state *cli,
11 void (*fn)(const char *name,
12 uint32 type,
13 const char *comment,
14 void *state),
15 void *state)
16{
17 int i;
18 WERROR result;
19 ENUM_HND enum_hnd;
20 uint32 info_level = 1;
21 uint32 preferred_len = 0xffffffff;
22 uint32 type;
23 SRV_SHARE_INFO_CTR ctr;
24 fstring name = "";
25 fstring comment = "";
26 void *mem_ctx;
27 struct rpc_pipe_client *pipe_hnd;
28 NTSTATUS nt_status;
29
30 /* Open the server service pipe */
31 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &nt_status);
32 if (!pipe_hnd) {
33 DEBUG(1, ("net_share_enum_rpc pipe open fail!\n"));
34 return -1;
35 }
36
37 /* Allocate a context for parsing and for the entries in "ctr" */
38 mem_ctx = talloc_init("libsmbclient: net_share_enum_rpc");
39 if (mem_ctx == NULL) {
40 DEBUG(0, ("out of memory for net_share_enum_rpc!\n"));
41 cli_rpc_pipe_close(pipe_hnd);
42 return -1;
43 }
44
45 /* Issue the NetShareEnum RPC call and retrieve the response */
46 init_enum_hnd(&enum_hnd, 0);
47 result = rpccli_srvsvc_net_share_enum(pipe_hnd,
48 mem_ctx,
49 info_level,
50 &ctr,
51 preferred_len,
52 &enum_hnd);
53
54 /* Was it successful? */
55 if (!W_ERROR_IS_OK(result) || ctr.num_entries == 0) {
56 /* Nope. Go clean up. */
57 goto done;
58 }
59
60 /* For each returned entry... */
61 for (i = 0; i < ctr.num_entries; i++) {
62
63 /* pull out the share name */
64 rpcstr_pull_unistr2_fstring(
65 name, &ctr.share.info1[i].info_1_str.uni_netname);
66
67 /* pull out the share's comment */
68 rpcstr_pull_unistr2_fstring(
69 comment, &ctr.share.info1[i].info_1_str.uni_remark);
70
71 /* Get the type value */
72 type = ctr.share.info1[i].info_1.type;
73
74 /* Add this share to the list */
75 (*fn)(name, type, comment, state);
76 }
77
78done:
79 /* Close the server service pipe */
80 cli_rpc_pipe_close(pipe_hnd);
81
82 /* Free all memory which was allocated for this request */
83 TALLOC_FREE(mem_ctx);
84
85 /* Tell 'em if it worked */
86 return W_ERROR_IS_OK(result) ? 0 : -1;
87}
88
89/*
90 * Wrapper for cli_errno to return not connected error on negative fd
91 */
92int os2cli_errno(cli_state * cli)
93{
94 if (cli->fd == -1)
95 {
96 return ENOTCONN;
97 }
98 return cli_errno(cli);
99}
100
101int _System smbwrp_getclisize(void)
102{
103 return sizeof(struct cli_state);
104}
105
106/*****************************************************
107initialise structures
108*******************************************************/
109int _System smbwrp_init(void)
110{
111 static int initialised = 0;
112 char *p;
113 pstring line;
114
115 if (initialised)
116 {
117 return 0;
118 }
119 initialised = 1;
120
121 load_case_tables();
122
123 init_globals( True);
124
125 load_interfaces();
126
127 if (!init_names())
128 {
129 return 1;
130 }
131
132/*
133 if ((p=smbw_getshared("RESOLVE_ORDER"))) {
134 lp_set_name_resolve_order(p);
135 }
136*/
137 return 0;
138
139}
140
141#if 0
142/*****************************************************
143remove redundent stuff from a filename
144*******************************************************/
145void clean_fname(char *name)
146{
147 char *p, *p2;
148 int l;
149 int modified = 1;
150
151 if (!name) return;
152
153 while (modified) {
154 modified = 0;
155
156 if ((p=strstr(name,"/./"))) {
157 modified = 1;
158 while (*p) {
159 p[0] = p[2];
160 p++;
161 }
162 }
163
164 if ((p=strstr(name,"//"))) {
165 modified = 1;
166 while (*p) {
167 p[0] = p[1];
168 p++;
169 }
170 }
171
172 if (strcmp(name,"/../")==0) {
173 modified = 1;
174 name[1] = 0;
175 }
176
177 if ((p=strstr(name,"/../"))) {
178 modified = 1;
179 for (p2=(p>name?p-1:p);p2>name;p2--) {
180 if (p2[0] == '/') break;
181 }
182 while (*p2) {
183 p2[0] = p2[3];
184 p2++;
185 }
186 }
187
188 if (strcmp(name,"/..")==0) {
189 modified = 1;
190 name[1] = 0;
191 }
192
193 l = strlen(name);
194 p = l>=3?(name+l-3):name;
195 if (strcmp(p,"/..")==0) {
196 modified = 1;
197 for (p2=p-1;p2>name;p2--) {
198 if (p2[0] == '/') break;
199 }
200 if (p2==name) {
201 p[0] = '/';
202 p[1] = 0;
203 } else {
204 p2[0] = 0;
205 }
206 }
207
208 l = strlen(name);
209 p = l>=2?(name+l-2):name;
210 if (strcmp(p,"/.")==0) {
211 if (p == name) {
212 p[1] = 0;
213 } else {
214 p[0] = 0;
215 }
216 }
217
218 if (strncmp(p=name,"./",2) == 0) {
219 modified = 1;
220 do {
221 p[0] = p[2];
222 } while (*p++);
223 }
224
225 l = strlen(p=name);
226 if (l > 1 && p[l-1] == '/') {
227 modified = 1;
228 p[l-1] = 0;
229 }
230 }
231}
232#endif
233
234
235/****************************************************************************
236send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
237****************************************************************************/
238BOOL cli_qpathinfo3(struct cli_state *cli, const char *fname,
239 time_t *c_time, time_t *a_time, time_t *m_time,
240 time_t *w_time, off_t *size, uint16 *mode,
241 SMB_INO_T *ino)
242{
243 unsigned int data_len = 0;
244 unsigned int param_len = 0;
245 uint16 setup = TRANSACT2_QPATHINFO;
246 pstring param;
247 char *rparam=NULL, *rdata=NULL;
248 char *p;
249
250 p = param;
251 memset(p, 0, 6);
252 SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);
253 p += 6;
254 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
255
256 param_len = PTR_DIFF(p, param);
257
258 if (!cli_send_trans(cli, SMBtrans2,
259 NULL, /* name */
260 -1, 0, /* fid, flags */
261 &setup, 1, 0, /* setup, length, max */
262 param, param_len, 10, /* param, length, max */
263 NULL, data_len, cli->max_xmit /* data, length, max */
264 )) {
265 return False;
266 }
267
268 if (!cli_receive_trans(cli, SMBtrans2,
269 &rparam, &param_len,
270 &rdata, &data_len)) {
271 return False;
272 }
273
274 if (!rdata || data_len < 22) {
275 return False;
276 }
277
278 if (c_time) {
279 *c_time = convert_timespec_to_time_t(interpret_long_date(rdata+0));
280 }
281 if (a_time) {
282 *a_time = convert_timespec_to_time_t(interpret_long_date(rdata+8));
283 }
284 if (m_time) {
285 *m_time = convert_timespec_to_time_t(interpret_long_date(rdata+16));
286 }
287 if (w_time) {
288 *w_time = convert_timespec_to_time_t(interpret_long_date(rdata+24));
289 }
290 if (mode) {
291 *mode = SVAL(rdata, 32);
292 }
293 if (size) {
294 *size = IVAL2_TO_SMB_BIG_UINT(rdata, 48);
295 }
296 if (ino) {
297 *ino = IVAL(rdata, 64);
298 }
299
300 SAFE_FREE(rdata);
301 SAFE_FREE(rparam);
302 return True;
303}
304
305/****************************************************************************
306send a qfileinfo call
307****************************************************************************/
308BOOL cli_qfileinfo3(struct cli_state *cli, int fnum,
309 uint16 *mode, off_t *size,
310 time_t *c_time, time_t *a_time, time_t *m_time,
311 time_t *w_time, SMB_INO_T *ino)
312{
313 unsigned int data_len = 0;
314 unsigned int param_len = 0;
315 uint16 setup = TRANSACT2_QFILEINFO;
316 pstring param;
317 char *rparam=NULL, *rdata=NULL;
318
319 /* if its a win95 server then fail this - win95 totally screws it
320 up */
321 if (cli->win95) return False;
322
323 param_len = 4;
324
325 memset(param, 0, param_len);
326 SSVAL(param, 0, fnum);
327 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
328
329 if (!cli_send_trans(cli, SMBtrans2,
330 NULL, /* name */
331 -1, 0, /* fid, flags */
332 &setup, 1, 0, /* setup, length, max */
333 param, param_len, 2, /* param, length, max */
334 NULL, data_len, cli->max_xmit /* data, length, max */
335 )) {
336 return False;
337 }
338
339 if (!cli_receive_trans(cli, SMBtrans2,
340 &rparam, &param_len,
341 &rdata, &data_len)) {
342 return False;
343 }
344
345 if (!rdata || data_len < 68) {
346 return False;
347 }
348
349 if (c_time) {
350 *c_time = convert_timespec_to_time_t(interpret_long_date(rdata+0));
351 }
352 if (a_time) {
353 *a_time = convert_timespec_to_time_t(interpret_long_date(rdata+8));
354 }
355 if (m_time) {
356 *m_time = convert_timespec_to_time_t(interpret_long_date(rdata+16));
357 }
358 if (w_time) {
359 *w_time = convert_timespec_to_time_t(interpret_long_date(rdata+24));
360 }
361 if (mode) {
362 *mode = SVAL(rdata, 32);
363 }
364 if (size) {
365 *size = IVAL2_TO_SMB_BIG_UINT(rdata, 48);
366 }
367 if (ino) {
368 *ino = IVAL(rdata, 64);
369 }
370
371 SAFE_FREE(rdata);
372 SAFE_FREE(rparam);
373 return True;
374}
375
376/*****************************************************
377return a connection to a server
378*******************************************************/
379int _System smbwrp_connect(smbwrp_server * srv, struct cli_state ** cli, int krb5support)
380{
381 char * server = srv->server_name;
382 char * share = *(srv->share_name) ? srv->share_name : "IPC$";
383 char * workgroup = srv->workgroup;
384 struct nmb_name called, calling;
385 char *p, *server_n = server;
386 fstring group;
387 struct in_addr ip;
388 NTSTATUS rc;
389 struct cli_state * c;
390 char* dev_type;
391
392 zero_ip(&ip);
393
394 debuglocal(1,"Connecting to \\\\%s:*********@%s:%s\\%s. Master %s:%d\n", srv->username, workgroup, server, share, srv->master, srv->ifmastergroup);
395
396 if (!*server) {
397 struct in_addr sip;
398
399 if (*workgroup)
400 {
401 if (!find_master_ip(workgroup, &sip)) {
402 return 1;
403 }
404 fstrcpy(group, inet_ntoa(sip));
405 server_n = group;
406 } else
407 if (*srv->master)
408 {
409 if (srv->ifmastergroup)
410 {
411 if (!find_master_ip(srv->master, &sip)) {
412 return 11;
413 }
414 strncpy(srv->master, inet_ntoa(sip), sizeof(srv->master) - 1);
415 srv->ifmastergroup = 0;
416 }
417 server_n = srv->master;
418 } else
419 {
420 return 10;
421 }
422 }
423
424 make_nmb_name(&calling, global_myname(), 0x0);
425// make_nmb_name(&calling, "WORK", 0x0); // this machine name
426 make_nmb_name(&called , server_n, 0x20);
427
428 again:
429 zero_ip(&ip);
430
431 /* have to open a new connection */
432 if (!(c=cli_initialise()))
433 {
434 return 2;
435 }
436
437 if (!NT_STATUS_IS_OK(cli_connect(c, server_n, &ip)))
438 {
439 return 3;
440 }
441
442 if (krb5support == 1){
443 debuglocal(1,"Kerberos support enabled\n");
444 c->use_kerberos = True;}
445
446 if (!cli_session_request(c, &calling, &called)) {
447 cli_shutdown(c);
448 if (strcmp(called.name, "*SMBSERVER")) {
449 make_nmb_name(&called , "*SMBSERVER", 0x20);
450 goto again;
451 }
452 return 4;
453 }
454
455 debuglocal(4," session request ok\n");
456
457 if (!cli_negprot(c)) {
458 cli_shutdown(c);
459 return 5;
460 }
461
462 debuglocal(4," session setuping for <%s>/<********> in <%s> %08x %08x %08x\n", srv->username, workgroup, c->protocol, c->sec_mode, c->capabilities);
463
464 if (!NT_STATUS_IS_OK(cli_session_setup(c, srv->username,
465 srv->password, strlen(srv->password),
466 srv->password, strlen(srv->password),
467 workgroup))) {
468 debuglocal(4,"%s/******** login failed\n", srv->username);
469 /* try an anonymous login if it failed */
470 if (!NT_STATUS_IS_OK(cli_session_setup(c, "", "", 1,"", 0, workgroup))) {
471 debuglocal(4,"Anonymous login failed");
472 cli_shutdown(c);
473 return 6;
474 }
475 }
476
477 debuglocal(4," session setup ok. Sending tconx <%s> <********>\n", share);
478
479 // YD ticket:58 we need to check resource type to avoid connecting to printers.
480 // dev type is set to IPC for IPC$, A: for everything else (printers use LPT1:)
481 if (!strcmp( share, "IPC$"))
482 dev_type = "IPC";
483 else
484 dev_type = "A:";
485
486 if (!cli_send_tconX(c, share, dev_type,
487 srv->password, strlen(srv->password)+1)) {
488 cli_shutdown(c);
489 return 7;
490 }
491
492 debuglocal(4," tconx ok. cli caps %08x\n", c->capabilities);
493
494 // copy back cli_state
495 *cli = c;
496
497// srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
498
499 return 0;
500}
501
502/*****************************************************
503close a connection to a server
504*******************************************************/
505void _System smbwrp_disconnect(struct cli_state ** cli)
506{
507 if (cli)
508 {
509 // this call will free all buffers, close handles and free cli mem
510 cli_shutdown(*cli);
511 // set to zero because no longer valid
512 *cli = 0;
513 }
514}
515
516
517
518/*****************************************************
519a wrapper for open()
520*******************************************************/
521int _System smbwrp_open(cli_state * cli, smbwrp_file * file)
522{
523 int fd = -1;
524
525 if (!cli || !file || !*file->fname)
526 {
527 return EINVAL;
528 }
529 if (file->denymode < DENY_ALL || file->denymode > DENY_NONE)
530 {
531 file->denymode = DENY_NONE;
532 }
533
534 debuglocal(4,"cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
535 file->fd = cli_open(cli, file->fname, file->openmode, file->denymode);
536 if (file->fd == -1)
537 {
538 return os2cli_errno(cli);
539 }
540 if (file->openmode & (O_WRONLY | O_RDWR | O_TRUNC | O_CREAT))
541 {
542 time_t t;
543 file->mtime = time(NULL);
544 t = get_time_zone(file->mtime);
545 debuglocal(4,"cli_open mtime %lu %lu\n", file->mtime, t);
546 file->mtime -= t;
547 }
548 file->offset = 0;
549 return 0;
550}
551
552/*****************************************************
553a wrapper for read()
554*******************************************************/
555int _System smbwrp_read(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
556{
557 int ret;
558
559 if (!cli || !file || !buf || !result)
560 {
561 return EINVAL;
562 }
563
564 *result = 0;
565 ret = cli_read(cli, file->fd, buf, file->offset, count);
566 if (ret == -1)
567 {
568 return os2cli_errno(cli);
569 }
570
571 file->offset += ret;
572 *result = ret;
573 return 0;
574}
575
576
577
578/*****************************************************
579a wrapper for write()
580*******************************************************/
581int _System smbwrp_write(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
582{
583 int ret;
584
585 if (!cli || !file || !buf || !result)
586 {
587 return EINVAL;
588 }
589
590 *result = 0;
591//debuglocal(1,("Write %x %d %lld %d", cli, file->fd, file->offset, count));
592 ret = cli_write(cli, file->fd, 0, buf, file->offset, count);
593 if (ret == -1)
594 {
595 return os2cli_errno(cli);
596 }
597
598 file->offset += ret;
599 *result = ret;
600 return 0;
601}
602
603/*****************************************************
604a wrapper for close()
605*******************************************************/
606int _System smbwrp_close(cli_state * cli, smbwrp_file * file)
607{
608 int rc = 0;
609 if (!cli || !file)
610 {
611 return EINVAL;
612 }
613
614
615 if (!cli_close(cli, file->fd))
616 {
617 return os2cli_errno(cli);
618 }
619 file->fd = -1;
620 file->offset = 0;
621 if (file->openattr || file->mtime)
622 {
623 debuglocal(4,"Set attr on close %s %08x %d %d\n", file->fname, file->openattr, file->mtime, file->mtime);
624 if (!cli_setatr(cli, file->fname, file->openattr, file->mtime))
625 {
626 debuglocal(4,"Set attr on close failed %d\n", os2cli_errno(cli));
627 //rc = os2cli_errno(cli);
628 }
629 file->openattr = 0;
630 file->mtime = 0;
631 }
632 *file->fname = 0;
633 return rc;
634}
635
636/*****************************************************
637a wrapper for setfilesize()
638*******************************************************/
639int cli_setfilenewsize(struct cli_state *cli, int fnum, off_t newsize)
640{
641 unsigned int data_len = 8;
642 unsigned int param_len = 6;
643 uint16 setup = TRANSACT2_SETFILEINFO;
644 pstring param;
645 char *rparam=NULL, *rdata=NULL;
646
647 memset(param, 0, param_len);
648 SSVAL(param,0,fnum);
649 SSVAL(param,2,SMB_SET_FILE_END_OF_FILE_INFO);
650
651 if (!cli_send_trans(cli, SMBtrans2,
652 NULL, /* name */
653 -1, 0, /* fid, flags */
654 &setup, 1, 0, /* setup, length, max */
655 param, param_len, 2, /* param, length, max */
656 (char *)&newsize, sizeof(newsize), cli->max_xmit /* data, length, max */
657 )) {
658 return False;
659 }
660
661 if (!cli_receive_trans(cli, SMBtrans2,
662 &rparam, &param_len,
663 &rdata, &data_len)) {
664 return False;
665 }
666
667 SAFE_FREE(rdata);
668 SAFE_FREE(rparam);
669
670 return True;
671}
672
673int _System smbwrp_setfilesize(cli_state * cli, smbwrp_file * file, long long newsize)
674{
675 int rc = 0;
676 if (!cli || !file)
677 {
678 return EINVAL;
679 }
680
681 debuglocal(4,"cli_setnewfileszie(%s) %lld\n", file->fname, newsize);
682 if (!cli_setfilenewsize(cli, file->fd, newsize))
683 {
684 if (newsize)
685 {
686 rc = os2cli_errno(cli);
687 }
688
689 if (!cli_close(cli, file->fd))
690 {
691 return os2cli_errno(cli);
692 }
693 file->fd = -1;
694 file->offset = 0;
695 file->openmode &= ~(O_CREAT | O_EXCL);
696 file->openmode |= O_TRUNC;
697 debuglocal(4,"cli_setnewfileszie : cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
698 file->fd = cli_open(cli, file->fname, file->openmode, file->denymode);
699 if (file->fd == -1)
700 {
701 return os2cli_errno(cli);
702 }
703 }
704 return 0;
705}
706
707/*****************************************************
708a wrapper for rename()
709*******************************************************/
710int _System smbwrp_rename(cli_state * cli, char *oldname, char *newname)
711{
712 if (!cli || !oldname || !newname)
713 {
714 return EINVAL;
715 }
716
717 debuglocal(1,"Rename <%s> -> <%s>\n", oldname, newname);
718 //cli_unlink(cli, newname);
719// if (!cli_rename(cli, oldname, newname) && !cli_ntrename(cli, oldname, newname))
720 if (!cli_rename(cli, oldname, newname))
721 {
722 return os2cli_errno(cli);
723 }
724 return 0;
725}
726
727
728/*****************************************************
729a wrapper for chmod()
730*******************************************************/
731int _System smbwrp_setattr(cli_state * cli, smbwrp_fileinfo *finfo)
732{
733 if (!cli || !finfo || !*finfo->fname)
734 {
735 return EINVAL;
736 }
737
738debuglocal(4,"Setting on <%s> attr %04x, time %lu/%lu\n", finfo->fname, finfo->attr, finfo->mtime, finfo->mtime + get_time_zone(finfo->mtime));
739 if (!cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime + (finfo->mtime == 0 ? 0 : get_time_zone(finfo->mtime)))
740 && !cli_setatr(cli, finfo->fname, finfo->attr, 0))
741 {
742 return os2cli_errno(cli);
743 }
744 return 0;
745}
746
747/*****************************************************
748a wrapper for unlink()
749*******************************************************/
750int _System smbwrp_unlink(cli_state * cli, const char *fname)
751{
752 if (!cli || !fname)
753 {
754 return EINVAL;
755 }
756#if 0
757 if (strncmp(cli->dev, "LPT", 3) == 0)
758 {
759 int job = smbw_stat_printjob(cli, fname, NULL, NULL);
760 if (job == -1)
761 {
762 goto failed;
763 }
764 if (cli_printjob_del(cli, job) != 0)
765 {
766 goto failed;
767 }
768 } else
769#endif
770 if (!cli_unlink(cli, fname))
771 {
772 return os2cli_errno(cli);
773 }
774 return 0;
775}
776
777/*****************************************************
778a wrapper for lseek()
779*******************************************************/
780int _System smbwrp_lseek(cli_state * cli, smbwrp_file * file, int whence, long long offset)
781{
782 off_t size;
783 if (!cli || !file)
784 {
785 return EINVAL;
786 }
787
788 debuglocal(4,"lseek %d %lld %lld\n", whence, offset, file->offset);
789
790 switch (whence) {
791 case SEEK_SET:
792 if (offset < 0)
793 {
794 return EINVAL;
795 }
796 file->offset = offset;
797 break;
798 case SEEK_CUR:
799 file->offset += offset;
800 break;
801 case SEEK_END:
802 if (offset > 0)
803 {
804 return EINVAL;
805 }
806 if (!cli_qfileinfo3(cli, file->fd,
807 NULL, &size, NULL, NULL, NULL,
808 NULL, NULL) &&
809 !cli_getattrE(cli, file->fd,
810 NULL, (SMB_BIG_UINT *)&size, NULL, NULL, NULL))
811 {
812 return os2cli_errno(cli);
813 }
814 file->offset = size + offset;
815 break;
816 default: return EINVAL;
817 }
818
819 return 0;
820}
821
822/*****************************************************
823try to do a QPATHINFO and if that fails then do a getatr
824this is needed because win95 sometimes refuses the qpathinfo
825*******************************************************/
826int _System smbwrp_getattr(smbwrp_server *srv, cli_state * cli, smbwrp_fileinfo *finfo)
827{
828 SMB_INO_T ino = 0;
829 if (!cli || !finfo || !*finfo->fname)
830 {
831 return EINVAL;
832 }
833 debug_printf( "smbwrp_getattr\n");
834 debuglocal(4,"getattr %d %d <%s>\n", cli->capabilities & CAP_NOPATHINFO2, cli->capabilities & CAP_NT_SMBS, finfo->fname);
835 if (!(cli->capabilities & CAP_NOPATHINFO2) &&
836 cli_qpathinfo3(cli, finfo->fname, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,
837 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino))
838 {
839 finfo->attr &= 0x7F;
840//debuglocal(2,("gotattr %08x <%s>\n", finfo->attr, finfo->fname));
841// finfo->ctime -= get_time_zone(finfo->ctime);
842// finfo->atime -= get_time_zone(finfo->atime);
843// finfo->mtime -= get_time_zone(finfo->mtime);
844 return 0;
845 }
846//debuglocal(2,("getattr rc1 %d\n", os2cli_errno(cli)));
847
848 /* If the path is not on a share (it is a workgroup or a server),
849 * then cli_qpathinfo3 obviously fails. Return some fake information
850 * about the directory.
851 */
852 if ( *srv->server_name == 0
853 || (strcmp(cli->dev,"IPC") == 0)
854 || *srv->share_name == 0
855 || (stricmp(srv->share_name,"IPC$") == 0)
856 || (strncmp(cli->dev,"LPT",3) == 0)
857 )
858 {
859 debuglocal(4,"getattr not a share.\n");
860 *(time_t *)&finfo->ctime = time (NULL);
861 *(time_t *)&finfo->atime = time (NULL);
862 *(time_t *)&finfo->mtime = time (NULL);
863 finfo->size = 0;
864 finfo->easize = 0;
865 finfo->attr = aDIR;
866 return 0;
867 }
868
869 /* if this is NT then don't bother with the getatr */
870 if (cli->capabilities & CAP_NT_SMBS && !(cli->capabilities & CAP_NOPATHINFO2))
871 {
872 int rc = os2cli_errno(cli);
873 // cli_qpathinfo* reports EINVAL when path of given file not exists
874 // thus there is no real situation when EINVAL should be returned to
875 // client at this point, we just replace it to ENOTDIR
876 if (rc == EINVAL)
877 {
878 rc = ENOTDIR;
879 }
880 return rc;
881 }
882
883 if (cli_getatr(cli, finfo->fname, (unsigned short *)&finfo->attr, &finfo->size, (time_t *)&finfo->mtime))
884 {
885//debuglocal(2,("gotattr1 %08x <%s>\n", finfo->attr, finfo->fname));
886 finfo->mtime -= get_time_zone(finfo->mtime);
887 finfo->atime = finfo->atime; //was mtime
888 finfo->ctime = finfo->ctime; //was mtime
889 cli->capabilities &= CAP_NOPATHINFO2;
890 return 0;
891 }
892 return os2cli_errno(cli);
893}
894
895/*****************************************************
896try to do a QPATHINFO and if that fails then do a getatr
897this is needed because win95 sometimes refuses the qpathinfo
898*******************************************************/
899int _System smbwrp_fgetattr(cli_state * cli, smbwrp_file *file, smbwrp_fileinfo *finfo)
900{
901 SMB_INO_T ino = 0;
902 if (!cli || !file || !finfo)
903 {
904 return EINVAL;
905 }
906
907 strncpy(finfo->fname, file->fname, sizeof(finfo->fname) - 1);
908 if (!cli_qfileinfo3(cli, file->fd,
909 (unsigned short *)&finfo->attr, (off_t *)&finfo->size, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,
910 &ino))
911 {
912 if (!cli_getattrE(cli, file->fd,
913 (unsigned short *)&finfo->attr, (SMB_BIG_UINT *)(&finfo->size), (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime))
914 {
915 return os2cli_errno(cli);
916 }
917 else
918 {
919 finfo->ctime -= get_time_zone(finfo->ctime);
920 finfo->atime -= get_time_zone(finfo->atime);
921 finfo->mtime -= get_time_zone(finfo->mtime);
922 }
923 }
924 else
925 {
926// finfo->ctime -= get_time_zone(finfo->ctime);
927// finfo->atime -= get_time_zone(finfo->atime);
928// finfo->mtime -= get_time_zone(finfo->mtime);
929 }
930
931 return 0;
932}
933
934// =============================DIRECTORY ROUTINES============================
935
936/*****************************************************
937add a entry to a directory listing
938*******************************************************/
939static void smbwrp_dir_add(const char* mnt, smbwrp_fileinfo *finfo, const char *mask, void *state)
940{
941 if (state && finfo)
942 {
943 filelist_state * st = (filelist_state *)state;
944 if (st->add_dir_entry)
945 {
946debuglocal(8,"adding <%s> %d %d\n", finfo->fname, sizeof(st->finfo), st->datalen);
947 memcpy(&st->finfo, finfo, sizeof(st->finfo));
948 st->add_dir_entry(state);
949 }
950 }
951}
952
953#if 0
954static void smbwrp_dir_add_old(struct file_info *finfo, const char *mask, void *state)
955{
956 if (state && finfo)
957 {
958 filelist_state * st = (filelist_state *)state;
959 if (st->add_dir_entry)
960 {
961 strncpy(st->finfo.fname, finfo->name, sizeof(st->finfo.fname) - 1);
962 st->finfo.size = finfo->size;
963 st->finfo.easize = -1;
964 st->finfo.attr = finfo->mode;
965 st->finfo.ctime = finfo->ctime_ts.tv_sec - get_time_zone(finfo->ctime_ts.tv_sec);
966 st->finfo.mtime = finfo->mtime_ts.tv_sec - get_time_zone(finfo->mtime_ts.tv_sec);
967 st->finfo.atime = finfo->atime_ts.tv_sec - get_time_zone(finfo->atime_ts.tv_sec);
968 st->add_dir_entry(state);
969 }
970 }
971}
972#endif
973
974static void smbwrp_special_add(const char * name, void * state)
975{
976 smbwrp_fileinfo finfo = {0};
977
978 if (!name)
979 {
980 return;
981 }
982
983 ZERO_STRUCT(finfo);
984
985 strncpy(finfo.fname, name, sizeof(finfo.fname) - 1);
986 finfo.attr = aRONLY | aDIR;
987
988 smbwrp_dir_add("", &finfo, NULL, state);
989}
990
991static void smbwrp_printjob_add(struct print_job_info *job, void * state)
992{
993 smbwrp_fileinfo finfo = {0};
994
995 ZERO_STRUCT(finfo);
996
997//printf("Printjob <%s>\n", job->name);
998
999 strncpy(finfo.fname, job->name, sizeof(finfo.fname) - 1);
1000 finfo.mtime = job->t - get_time_zone(job->t);
1001 finfo.atime = finfo.atime; //was mtime
1002 finfo.ctime = finfo.ctime; //was mtime
1003 finfo.attr = aRONLY;
1004 finfo.size = job->size;
1005
1006 smbwrp_dir_add("", &finfo, NULL, state);
1007}
1008
1009static void smbwrp_share_add(const char *share, uint32 type,
1010 const char *comment, void *state)
1011{
1012 smbwrp_fileinfo finfo = {0};
1013
1014 // strip administrative names and printers from list
1015 if (type == STYPE_PRINTQ || strcmp(share,"IPC$") == 0) return;
1016
1017 ZERO_STRUCT(finfo);
1018
1019 strncpy(finfo.fname, share, sizeof(finfo.fname) - 1);
1020 finfo.attr = aRONLY | aDIR;
1021
1022 smbwrp_dir_add("", &finfo, NULL, state);
1023}
1024
1025/****************************************************************************
1026 Interpret a long filename structure - this is mostly guesses at the moment.
1027 The length of the structure is returned
1028 The structure of a long filename depends on the info level. 260 is used
1029 by NT and 2 is used by OS/2
1030****************************************************************************/
1031// YD from libsmb\clilist.c
1032static size_t _os2_interpret_long_filename(struct cli_state *cli,
1033 int level,char *p, smbwrp_fileinfo *finfo,
1034 uint32 *p_resume_key, DATA_BLOB *p_last_name_raw, uint32 *p_last_name_raw_len)
1035{
1036 extern file_info def_finfo;
1037 int len;
1038 char *base = p;
1039 smbwrp_fileinfo finfo1;
1040
1041 if (!finfo) finfo = &finfo1;
1042
1043 if (p_resume_key) {
1044 *p_resume_key = 0;
1045 }
1046
1047 finfo->attr = def_finfo.mode;
1048 finfo->mtime = def_finfo.mtime_ts.tv_sec;
1049 finfo->atime = def_finfo.atime_ts.tv_sec;
1050 finfo->ctime = def_finfo.ctime_ts.tv_sec;
1051 strncpy(finfo->fname, def_finfo.name, sizeof(finfo->fname) - 1);
1052 debug_printf( "fname %s (serverzone %d, level %d)\n",finfo->fname, cli->serverzone, level);
1053
1054 switch (level) {
1055 case 1: /* OS/2 understands this */
1056 /* these dates are converted to GMT by
1057 make_unix_date */
1058 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1059 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1060 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1061 finfo->size = IVAL(p,16);
1062 finfo->attr = CVAL(p,24);
1063 len = CVAL(p, 26);
1064 p += 27;
1065 p += clistr_align_in(cli, p, 0);
1066 /* the len+2 below looks strange but it is
1067 important to cope with the differences
1068 between win2000 and win9x for this call
1069 (tridge) */
1070 p += clistr_pull(cli, finfo->fname, p,
1071 sizeof(finfo->fname),
1072 len+2,
1073 STR_TERMINATE);
1074 finfo->easize = -1;
1075 return PTR_DIFF(p, base);
1076
1077 case 2: /* this is what OS/2 uses mostly */
1078 /* these dates are converted to GMT by
1079 make_unix_date */
1080 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1081 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1082 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1083 finfo->size = IVAL(p,16);
1084 finfo->attr = CVAL(p,24);
1085 finfo->easize = IVAL(p,26);
1086 len = CVAL(p, 30);
1087 p += 31;
1088 /* check for unisys! */
1089 p += clistr_pull(cli, finfo->fname, p,
1090 sizeof(finfo->fname),
1091 len,
1092 STR_NOALIGN);
1093 return PTR_DIFF(p, base) + 1;
1094
1095 case 260: /* NT uses this, but also accepts 2 */
1096 {
1097 size_t namelen, slen;
1098 p += 4; /* next entry offset */
1099 if (p_resume_key) {
1100 *p_resume_key = IVAL(p,0);
1101 }
1102
1103 p += 4; /* fileindex */
1104
1105 /* Offset zero is "create time", not "change time". */
1106 p += 8;
1107 finfo->atime = interpret_long_date(p).tv_sec;
1108 p += 8;
1109 finfo->mtime = interpret_long_date(p).tv_sec;
1110 p += 8;
1111 finfo->ctime = interpret_long_date(p).tv_sec;
1112 p += 8;
1113 finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0);
1114 p += 8;
1115 p += 8; /* alloc size */
1116 finfo->attr = CVAL(p,0);
1117 p += 4;
1118 namelen = IVAL(p,0);
1119 p += 4;
1120 finfo->easize = IVAL(p,0);
1121 p += 4; /* EA size */
1122 slen = SVAL(p, 0);
1123 p += 2;
1124#if 0
1125 {
1126 /* stupid NT bugs. grr */
1127 int flags = 0;
1128 if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE;
1129 clistr_pull(cli, finfo->short_name, p,
1130 sizeof(finfo->short_name),
1131 slen, flags);
1132 }
1133#endif
1134 p += 24; /* short name? */
1135 clistr_pull(cli, finfo->fname, p,
1136 sizeof(finfo->fname),
1137 namelen, 0);
1138
1139 /* To be robust in the face of unicode conversion failures
1140 we need to copy the raw bytes of the last name seen here.
1141 Namelen doesn't include the terminating unicode null, so
1142 copy it here. */
1143#if 0
1144 if (p_last_name_raw && p_last_name_raw_len) {
1145 if (namelen + 2 > p_last_name_raw->length) {
1146 memset(p_last_name_raw->data, '\0', sizeof(p_last_name_raw->length));
1147 *p_last_name_raw_len = 0;
1148 } else {
1149 memcpy(p_last_name_raw->data, p, namelen);
1150 SSVAL(p_last_name_raw->data, namelen, 0);
1151 *p_last_name_raw_len = namelen + 2;
1152 }
1153 }
1154#endif
1155 return (size_t)IVAL(base, 0);
1156 }
1157 }
1158
1159 debuglocal(1,"Unknown long filename format %d\n",level);
1160 return (size_t)IVAL(base,0);
1161}
1162
1163/****************************************************************************
1164 Do a directory listing, calling fn on each file found.
1165 Modified from cli_list_new
1166****************************************************************************/
1167
1168static int list_files(struct cli_state *cli, const char *Mask, uint16 attribute,
1169 void (*fn)(const char*, smbwrp_fileinfo *, const char *, void *), void *state)
1170{
1171#if 1
1172 int max_matches = 1366; /* Match W2k - was 512. */
1173#else
1174 int max_matches = 512;
1175#endif
1176 int info_level;
1177 char *p, *p2;
1178 pstring mask;
1179 smbwrp_fileinfo finfo;
1180 int i;
1181 char *dirlist = NULL;
1182 int dirlist_len = 0;
1183 int total_received = -1;
1184 BOOL First = True;
1185 int ff_searchcount=0;
1186 int ff_eos=0;
1187 int ff_dir_handle=0;
1188 int loop_count = 0;
1189 char *rparam=NULL, *rdata=NULL;
1190 unsigned int param_len, data_len;
1191 uint16 setup;
1192 pstring param;
1193 const char *mnt;
1194 uint32 resume_key = 0;
1195 uint32 last_name_raw_len = 0;
1196 DATA_BLOB last_name_raw = data_blob(NULL, 2*sizeof(pstring));
1197
1198 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1199 info_level = (cli->capabilities&CAP_NT_SMBS)?260:2;
1200
1201 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, mask);
1202
1203 /* when getting a directory listing from a 2k dfs root share,
1204 we have to include the full path (\server\share\mask) here */
1205
1206 if ( cli->dfsroot )
1207 pstr_sprintf( mask, "\\%s\\%s\\%s", cli->desthost, cli->share, Mask );
1208 else
1209 pstrcpy(mask,Mask);
1210
1211 while (ff_eos == 0) {
1212 loop_count++;
1213 if (loop_count > 200) {
1214 debuglocal(0,"Error: Looping in FIND_NEXT??\n");
1215 break;
1216 }
1217
1218 if (First) {
1219 setup = TRANSACT2_FINDFIRST;
1220 SSVAL(param,0,attribute); /* attribute */
1221 SSVAL(param,2,max_matches); /* max count */
1222 SSVAL(param,4,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1223 SSVAL(param,6,info_level);
1224 SIVAL(param,8,0);
1225 p = param+12;
1226 p += clistr_push(cli, param+12, mask, sizeof(param)-12,
1227 STR_TERMINATE);
1228 } else {
1229 setup = TRANSACT2_FINDNEXT;
1230 SSVAL(param,0,ff_dir_handle);
1231 SSVAL(param,2,max_matches); /* max count */
1232 SSVAL(param,4,info_level);
1233 /* For W2K servers serving out FAT filesystems we *must* set the
1234 resume key. If it's not FAT then it's returned as zero. */
1235 SIVAL(param,6,resume_key); /* ff_resume_key */
1236 /* NB. *DON'T* use continue here. If you do it seems that W2K and bretheren
1237 can miss filenames. Use last filename continue instead. JRA */
1238 SSVAL(param,10,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1239 p = param+12;
1240 if (last_name_raw_len && (last_name_raw_len < (sizeof(param)-12))) {
1241 memcpy(p, last_name_raw.data, last_name_raw_len);
1242 p += last_name_raw_len;
1243 } else {
1244 p += clistr_push(cli, param+12, mask, sizeof(param)-12, STR_TERMINATE);
1245 }
1246 }
1247
1248 param_len = PTR_DIFF(p, param);
1249
1250 if (!cli_send_trans(cli, SMBtrans2,
1251 NULL, /* Name */
1252 -1, 0, /* fid, flags */
1253 &setup, 1, 0, /* setup, length, max */
1254 param, param_len, 10, /* param, length, max */
1255 NULL, 0,
1256#if 0
1257 /* w2k value. */
1258 MIN(16384,cli->max_xmit) /* data, length, max. */
1259#else
1260 cli->max_xmit /* data, length, max. */
1261#endif
1262 )) {
1263 break;
1264 }
1265
1266 if (!cli_receive_trans(cli, SMBtrans2,
1267 &rparam, &param_len,
1268 &rdata, &data_len) &&
1269 cli_is_dos_error(cli)) {
1270 /* we need to work around a Win95 bug - sometimes
1271 it gives ERRSRV/ERRerror temprarily */
1272 uint8 eclass;
1273 uint32 ecode;
1274
1275 SAFE_FREE(rdata);
1276 SAFE_FREE(rparam);
1277
1278 cli_dos_error(cli, &eclass, &ecode);
1279
1280 /*
1281 * OS/2 might return "no more files",
1282 * which just tells us, that searchcount is zero
1283 * in this search.
1284 * Guenter Kukkukk <linux@kukkukk.com>
1285 */
1286
1287 if (eclass == ERRDOS && ecode == ERRnofiles) {
1288 ff_searchcount = 0;
1289 cli_reset_error(cli);
1290 break;
1291 }
1292
1293 if (eclass != ERRSRV || ecode != ERRerror)
1294 break;
1295 smb_msleep(100);
1296 continue;
1297 }
1298
1299 if (cli_is_error(cli) || !rdata || !rparam)
1300 {
1301 if (First && info_level == 2)
1302 {
1303 // we have tried query ea size, but now will try without ea size
1304 info_level = 1;
1305 debuglocal(4,"list_files fallback to level %d\n", info_level);
1306 continue;
1307 }
1308 SAFE_FREE(rdata);
1309 SAFE_FREE(rparam);
1310 break;
1311 }
1312
1313 if (total_received == -1)
1314 total_received = 0;
1315
1316 /* parse out some important return info */
1317 p = rparam;
1318 if (First) {
1319 ff_dir_handle = SVAL(p,0);
1320 ff_searchcount = SVAL(p,2);
1321 ff_eos = SVAL(p,4);
1322 } else {
1323 ff_searchcount = SVAL(p,0);
1324 ff_eos = SVAL(p,2);
1325 }
1326 debuglocal(4,"list_files %d %d %d %d\n", ff_searchcount, ff_eos, "(ff_lastname)", First);
1327
1328 if (ff_searchcount == 0) {
1329 SAFE_FREE(rdata);
1330 SAFE_FREE(rparam);
1331 break;
1332 }
1333
1334 /* point to the data bytes */
1335 p = rdata;
1336
1337 memset(&finfo, 0, sizeof(finfo));
1338 finfo.easize = -1;
1339 /* we might need the lastname for continuations */
1340 for (p2=p,i=0;i<ff_searchcount;i++) {
1341 if ((info_level == 260) && (i == ff_searchcount-1)) {
1342 /* Last entry - fixup the last offset length. */
1343 SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2));
1344 }
1345 p2 += _os2_interpret_long_filename(cli,info_level,p2,&finfo,
1346 &resume_key,&last_name_raw,&last_name_raw_len);
1347
1348 if (!First && *mask && strcsequal(finfo.fname, mask)) {
1349 debuglocal(0,"Error: Looping in FIND_NEXT as name %s has already been seen?\n",
1350 finfo.fname);
1351 ff_eos = 1;
1352 break;
1353 }
1354 }
1355
1356 if (ff_searchcount > 0) {
1357 pstrcpy(mask, finfo.fname);
1358 } else {
1359 pstrcpy(mask,"");
1360 }
1361
1362 /* grab the data for later use */
1363 /* and add them to the dirlist pool */
1364 dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len);
1365
1366 if (!dirlist) {
1367 debuglocal(0,"cli_list_new: Failed to expand dirlist\n");
1368 SAFE_FREE(rdata);
1369 SAFE_FREE(rparam);
1370 break;
1371 }
1372
1373 memcpy(dirlist+dirlist_len,p,data_len);
1374 dirlist_len += data_len;
1375
1376 total_received += ff_searchcount;
1377
1378 SAFE_FREE(rdata);
1379 SAFE_FREE(rparam);
1380
1381 debuglocal(3,"received %d entries (eos=%d)\n",
1382 ff_searchcount,ff_eos);
1383
1384 if (ff_searchcount > 0)
1385 loop_count = 0;
1386
1387 First = False;
1388 }
1389
1390 mnt = cli_cm_get_mntpoint( cli );
1391
1392 /* see if the server disconnected or the connection otherwise failed */
1393 if (cli_is_error(cli)) {
1394 total_received = -1;
1395 } else {
1396 /* no connection problem. let user function add each entry */
1397 for (p=dirlist,i=0;i<total_received;i++) {
1398 p += _os2_interpret_long_filename(cli, info_level, p,
1399 &finfo,NULL,NULL,NULL);
1400 fn( mnt,&finfo, Mask, state );
1401 }
1402 }
1403
1404 /* free up the dirlist buffer and last name raw blob */
1405 SAFE_FREE(dirlist);
1406 data_blob_free(&last_name_raw);
1407 return(total_received);
1408}
1409
1410
1411/*****************************************************
1412open a directory on the server
1413*******************************************************/
1414int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1415{
1416 if (!srv || !cli || !state || !*state->mask)
1417 {
1418 return EINVAL;
1419 }
1420 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);
1421 debug_printf( "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);
1422 if (*srv->workgroup == 0 && *srv->server_name == 0)
1423 {
1424 smbwrp_special_add(".", state);
1425 smbwrp_special_add("..", state);
1426 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1427 smbwrp_share_add, state);
1428 } else
1429 if (*srv->server_name == 0)
1430 {
1431 smbwrp_special_add(".", state);
1432 smbwrp_special_add("..", state);
1433
1434 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1435 smbwrp_share_add, state);
1436 } else
1437 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1438 {
1439 smbwrp_special_add(".", state);
1440 smbwrp_special_add("..", state);
1441
1442 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1443 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1444 {
1445 return os2cli_errno(cli);
1446 }
1447 } else
1448 if (strncmp(cli->dev,"LPT",3) == 0)
1449 {
1450 smbwrp_special_add(".", state);
1451 smbwrp_special_add("..", state);
1452 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1453 {
1454 return os2cli_errno(cli);
1455 }
1456 }
1457 else
1458 {
1459#if 0
1460 if (strcmp(path,"\\") == 0) {
1461 smbwrp_special_add(".", state);
1462 smbwrp_special_add("..", state);
1463 }
1464#endif
1465#if 0
1466 if (cli_list(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1467 smbwrp_dir_add_old, state) < 0)
1468#else
1469 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1470 smbwrp_dir_add, state) < 0)
1471#endif
1472 {
1473 return os2cli_errno(cli);
1474 }
1475 }
1476
1477 return 0;
1478}
1479
1480/*****************************************************
1481a wrapper for chdir()
1482*******************************************************/
1483int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1484{
1485 unsigned short mode = aDIR;
1486 smbwrp_fileinfo finfo = {0};
1487 if (!cli || !fname)
1488 {
1489 return EINVAL;
1490 }
1491
1492 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1493 if (smbwrp_getattr(srv, cli, &finfo))
1494 {
1495 return os2cli_errno(cli);
1496 }
1497
1498 if (!(finfo.attr & aDIR)) {
1499 return ENOTDIR;
1500 }
1501
1502 return 0;
1503}
1504
1505
1506/*****************************************************
1507a wrapper for mkdir()
1508*******************************************************/
1509int _System smbwrp_mkdir(cli_state * cli, char *fname)
1510{
1511 if (!cli || !fname)
1512 {
1513 return EINVAL;
1514 }
1515
1516 if (!cli_mkdir(cli, fname))
1517 {
1518 return os2cli_errno(cli);
1519 }
1520 return 0;
1521}
1522
1523/*****************************************************
1524a wrapper for rmdir()
1525*******************************************************/
1526int _System smbwrp_rmdir(cli_state * cli, char *fname)
1527{
1528 if (!cli || !fname)
1529 {
1530 return EINVAL;
1531 }
1532
1533 if (!cli_rmdir(cli, fname))
1534 {
1535 return os2cli_errno(cli);
1536 }
1537 return 0;
1538}
1539
1540/*****************************************************
1541set EA for a path
1542*******************************************************/
1543int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1544{
1545 if (!cli || !fname || !name)
1546 {
1547 return EINVAL;
1548 }
1549 if (!cli_set_ea_path(cli, fname, name, value, size))
1550 {
1551 return os2cli_errno(cli);
1552 }
1553 return 0;
1554}
1555
1556/*****************************************************
1557set EA for a file
1558*******************************************************/
1559int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1560{
1561 if (!cli || !file || !name)
1562 {
1563 return EINVAL;
1564 }
1565 if (!cli_set_ea_fnum(cli, file->fd, name, value, size))
1566 {
1567 return os2cli_errno(cli);
1568 }
1569 return 0;
1570}
1571
1572
1573#pragma pack(1)
1574typedef struct _FEA /* fea */
1575{
1576 unsigned char fEA; /* flags */
1577 unsigned char cbName; /* name length not including NULL */
1578 unsigned short cbValue; /* value length */
1579} FEA;
1580
1581typedef struct _FEALIST /* feal */
1582{
1583 unsigned long cbList; /* total bytes of structure including full list */
1584 FEA list[1]; /* variable length FEA structures */
1585} FEALIST;
1586#pragma pack()
1587
1588static int unilistea(cli_state * cli, char *fname, smbwrp_file *file, void * buffer, unsigned long size)
1589{
1590 int fnum, i;
1591 int gotsize = sizeof(unsigned long);
1592 size_t num_eas;
1593 struct ea_struct *ea_list = NULL;
1594 TALLOC_CTX *mem_ctx;
1595 FEA * p;
1596 FEALIST * pfealist;
1597 char * q;
1598
1599 mem_ctx = talloc_init("%d: ealist", _gettid());
1600 pfealist = (FEALIST *)buffer;
1601 pfealist->cbList = 0;
1602
1603 if (file)
1604 {
1605 if (!cli_get_ea_list_fnum(cli, file->fd, mem_ctx, &num_eas, &ea_list))
1606 {
1607 debuglocal(4,"ea_get_fnum list failed - %s\n", cli_errstr(cli));
1608 talloc_destroy(mem_ctx);
1609 return os2cli_errno(cli);
1610 }
1611 }
1612 else
1613 {
1614 if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list))
1615 {
1616 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1617 talloc_destroy(mem_ctx);
1618 return os2cli_errno(cli);
1619 }
1620 }
1621
1622 debuglocal(4,"num_eas = %d\n", num_eas);
1623
1624 // we will count that os/2 max EA size for file is 64kb
1625 p = pfealist->list;
1626 for (i = 0; i < num_eas; i++)
1627 {
1628 int namelen = strlen(ea_list[i].name);
1629 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);
1630 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1631 {
1632 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1633 continue;
1634 }
1635 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1636 if (size >= gotsize)
1637 {
1638 p->fEA = 0;
1639 p->cbName = namelen;
1640 p->cbValue = ea_list[i].value.length;
1641 q = (char *)(p + 1);
1642 strncpy(q, ea_list[i].name, namelen + 1);
1643 q += namelen + 1;
1644 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1645 p = (FEA *)(q + ea_list[i].value.length);
1646 }
1647 }
1648 pfealist->cbList = gotsize;
1649 debuglocal(4,"ret size = %d\n", gotsize);
1650
1651 talloc_destroy(mem_ctx);
1652 return 0;
1653}
1654
1655/*****************************************************
1656lists EA of a path
1657*******************************************************/
1658int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1659{
1660 if (!cli || !fname || !buffer)
1661 {
1662 return EINVAL;
1663 }
1664
1665 debuglocal(4,"EALIst for <%s>\n", fname);
1666 return unilistea(cli, fname, NULL, buffer, size);
1667}
1668
1669/*****************************************************
1670lists EA of a file
1671*******************************************************/
1672int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1673{
1674 if (!cli || !file || !buffer)
1675 {
1676 return EINVAL;
1677 }
1678
1679 debuglocal(4,"FEALIst for <%s>/%d\n", file->fname, file->fd);
1680 return unilistea(cli, NULL, file, buffer, size);
1681}
1682
1683/****************************************************************************
1684Check the space on a device.
1685****************************************************************************/
1686int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1687{
1688 int total, bsize, avail;
1689
1690 if (!cli || !pfsa)
1691 {
1692 return EINVAL;
1693 }
1694
1695 if (!cli_dskattr(cli, &bsize, &total, &avail))
1696 {
1697 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1698 return os2cli_errno(cli);
1699 }
1700
1701 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1702 total, bsize, avail);
1703
1704 // YD currently Samba return it in MB!
1705 pfsa->cSectorUnit = 1;
1706 if (bsize > 65536)
1707 {
1708 pfsa->cUnit = total*1024;
1709 pfsa->cUnitAvail = avail*1024;
1710 pfsa->cbSector = bsize/1024;
1711 }
1712 else
1713 {
1714 pfsa->cUnit = total;
1715 pfsa->cUnitAvail = avail;
1716 pfsa->cbSector = bsize;
1717 }
1718
1719 return 0;
1720}
Note: See TracBrowser for help on using the repository browser.