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

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

Define type of resource required, so printers are no longer allowed. ticket:58.

  • Property svn:eol-style set to native
File size: 43.9 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 if (strcmp(share,"IPC$") == 0) return;
1015
1016 ZERO_STRUCT(finfo);
1017
1018 strncpy(finfo.fname, share, sizeof(finfo.fname) - 1);
1019 finfo.attr = aRONLY | aDIR;
1020
1021 smbwrp_dir_add("", &finfo, NULL, state);
1022}
1023
1024/****************************************************************************
1025 Interpret a long filename structure - this is mostly guesses at the moment.
1026 The length of the structure is returned
1027 The structure of a long filename depends on the info level. 260 is used
1028 by NT and 2 is used by OS/2
1029****************************************************************************/
1030// YD from libsmb\clilist.c
1031static size_t _os2_interpret_long_filename(struct cli_state *cli,
1032 int level,char *p, smbwrp_fileinfo *finfo,
1033 uint32 *p_resume_key, DATA_BLOB *p_last_name_raw, uint32 *p_last_name_raw_len)
1034{
1035 extern file_info def_finfo;
1036 int len;
1037 char *base = p;
1038 smbwrp_fileinfo finfo1;
1039
1040 if (!finfo) finfo = &finfo1;
1041
1042 if (p_resume_key) {
1043 *p_resume_key = 0;
1044 }
1045
1046 finfo->attr = def_finfo.mode;
1047 finfo->mtime = def_finfo.mtime_ts.tv_sec;
1048 finfo->atime = def_finfo.atime_ts.tv_sec;
1049 finfo->ctime = def_finfo.ctime_ts.tv_sec;
1050 strncpy(finfo->fname, def_finfo.name, sizeof(finfo->fname) - 1);
1051 debug_printf( "fname %s (serverzone %d, level %d)\n",finfo->fname, cli->serverzone, level);
1052
1053 switch (level) {
1054 case 1: /* OS/2 understands this */
1055 /* these dates are converted to GMT by
1056 make_unix_date */
1057 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1058 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1059 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1060 finfo->size = IVAL(p,16);
1061 finfo->attr = CVAL(p,24);
1062 len = CVAL(p, 26);
1063 p += 27;
1064 p += clistr_align_in(cli, p, 0);
1065 /* the len+2 below looks strange but it is
1066 important to cope with the differences
1067 between win2000 and win9x for this call
1068 (tridge) */
1069 p += clistr_pull(cli, finfo->fname, p,
1070 sizeof(finfo->fname),
1071 len+2,
1072 STR_TERMINATE);
1073 finfo->easize = -1;
1074 return PTR_DIFF(p, base);
1075
1076 case 2: /* this is what OS/2 uses mostly */
1077 /* these dates are converted to GMT by
1078 make_unix_date */
1079 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1080 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1081 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1082 finfo->size = IVAL(p,16);
1083 finfo->attr = CVAL(p,24);
1084 finfo->easize = IVAL(p,26);
1085 len = CVAL(p, 30);
1086 p += 31;
1087 /* check for unisys! */
1088 p += clistr_pull(cli, finfo->fname, p,
1089 sizeof(finfo->fname),
1090 len,
1091 STR_NOALIGN);
1092 return PTR_DIFF(p, base) + 1;
1093
1094 case 260: /* NT uses this, but also accepts 2 */
1095 {
1096 size_t namelen, slen;
1097 p += 4; /* next entry offset */
1098 if (p_resume_key) {
1099 *p_resume_key = IVAL(p,0);
1100 }
1101
1102 p += 4; /* fileindex */
1103
1104 /* Offset zero is "create time", not "change time". */
1105 p += 8;
1106 finfo->atime = interpret_long_date(p).tv_sec;
1107 p += 8;
1108 finfo->mtime = interpret_long_date(p).tv_sec;
1109 p += 8;
1110 finfo->ctime = interpret_long_date(p).tv_sec;
1111 p += 8;
1112 finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0);
1113 p += 8;
1114 p += 8; /* alloc size */
1115 finfo->attr = CVAL(p,0);
1116 p += 4;
1117 namelen = IVAL(p,0);
1118 p += 4;
1119 finfo->easize = IVAL(p,0);
1120 p += 4; /* EA size */
1121 slen = SVAL(p, 0);
1122 p += 2;
1123#if 0
1124 {
1125 /* stupid NT bugs. grr */
1126 int flags = 0;
1127 if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE;
1128 clistr_pull(cli, finfo->short_name, p,
1129 sizeof(finfo->short_name),
1130 slen, flags);
1131 }
1132#endif
1133 p += 24; /* short name? */
1134 clistr_pull(cli, finfo->fname, p,
1135 sizeof(finfo->fname),
1136 namelen, 0);
1137
1138 /* To be robust in the face of unicode conversion failures
1139 we need to copy the raw bytes of the last name seen here.
1140 Namelen doesn't include the terminating unicode null, so
1141 copy it here. */
1142#if 0
1143 if (p_last_name_raw && p_last_name_raw_len) {
1144 if (namelen + 2 > p_last_name_raw->length) {
1145 memset(p_last_name_raw->data, '\0', sizeof(p_last_name_raw->length));
1146 *p_last_name_raw_len = 0;
1147 } else {
1148 memcpy(p_last_name_raw->data, p, namelen);
1149 SSVAL(p_last_name_raw->data, namelen, 0);
1150 *p_last_name_raw_len = namelen + 2;
1151 }
1152 }
1153#endif
1154 return (size_t)IVAL(base, 0);
1155 }
1156 }
1157
1158 debuglocal(1,"Unknown long filename format %d\n",level);
1159 return (size_t)IVAL(base,0);
1160}
1161
1162/****************************************************************************
1163 Do a directory listing, calling fn on each file found.
1164 Modified from cli_list_new
1165****************************************************************************/
1166
1167static int list_files(struct cli_state *cli, const char *Mask, uint16 attribute,
1168 void (*fn)(const char*, smbwrp_fileinfo *, const char *, void *), void *state)
1169{
1170#if 1
1171 int max_matches = 1366; /* Match W2k - was 512. */
1172#else
1173 int max_matches = 512;
1174#endif
1175 int info_level;
1176 char *p, *p2;
1177 pstring mask;
1178 smbwrp_fileinfo finfo;
1179 int i;
1180 char *dirlist = NULL;
1181 int dirlist_len = 0;
1182 int total_received = -1;
1183 BOOL First = True;
1184 int ff_searchcount=0;
1185 int ff_eos=0;
1186 int ff_dir_handle=0;
1187 int loop_count = 0;
1188 char *rparam=NULL, *rdata=NULL;
1189 unsigned int param_len, data_len;
1190 uint16 setup;
1191 pstring param;
1192 const char *mnt;
1193 uint32 resume_key = 0;
1194 uint32 last_name_raw_len = 0;
1195 DATA_BLOB last_name_raw = data_blob(NULL, 2*sizeof(pstring));
1196
1197 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1198 info_level = (cli->capabilities&CAP_NT_SMBS)?260:2;
1199
1200 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, mask);
1201
1202 /* when getting a directory listing from a 2k dfs root share,
1203 we have to include the full path (\server\share\mask) here */
1204
1205 if ( cli->dfsroot )
1206 pstr_sprintf( mask, "\\%s\\%s\\%s", cli->desthost, cli->share, Mask );
1207 else
1208 pstrcpy(mask,Mask);
1209
1210 while (ff_eos == 0) {
1211 loop_count++;
1212 if (loop_count > 200) {
1213 debuglocal(0,"Error: Looping in FIND_NEXT??\n");
1214 break;
1215 }
1216
1217 if (First) {
1218 setup = TRANSACT2_FINDFIRST;
1219 SSVAL(param,0,attribute); /* attribute */
1220 SSVAL(param,2,max_matches); /* max count */
1221 SSVAL(param,4,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1222 SSVAL(param,6,info_level);
1223 SIVAL(param,8,0);
1224 p = param+12;
1225 p += clistr_push(cli, param+12, mask, sizeof(param)-12,
1226 STR_TERMINATE);
1227 } else {
1228 setup = TRANSACT2_FINDNEXT;
1229 SSVAL(param,0,ff_dir_handle);
1230 SSVAL(param,2,max_matches); /* max count */
1231 SSVAL(param,4,info_level);
1232 /* For W2K servers serving out FAT filesystems we *must* set the
1233 resume key. If it's not FAT then it's returned as zero. */
1234 SIVAL(param,6,resume_key); /* ff_resume_key */
1235 /* NB. *DON'T* use continue here. If you do it seems that W2K and bretheren
1236 can miss filenames. Use last filename continue instead. JRA */
1237 SSVAL(param,10,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1238 p = param+12;
1239 if (last_name_raw_len && (last_name_raw_len < (sizeof(param)-12))) {
1240 memcpy(p, last_name_raw.data, last_name_raw_len);
1241 p += last_name_raw_len;
1242 } else {
1243 p += clistr_push(cli, param+12, mask, sizeof(param)-12, STR_TERMINATE);
1244 }
1245 }
1246
1247 param_len = PTR_DIFF(p, param);
1248
1249 if (!cli_send_trans(cli, SMBtrans2,
1250 NULL, /* Name */
1251 -1, 0, /* fid, flags */
1252 &setup, 1, 0, /* setup, length, max */
1253 param, param_len, 10, /* param, length, max */
1254 NULL, 0,
1255#if 0
1256 /* w2k value. */
1257 MIN(16384,cli->max_xmit) /* data, length, max. */
1258#else
1259 cli->max_xmit /* data, length, max. */
1260#endif
1261 )) {
1262 break;
1263 }
1264
1265 if (!cli_receive_trans(cli, SMBtrans2,
1266 &rparam, &param_len,
1267 &rdata, &data_len) &&
1268 cli_is_dos_error(cli)) {
1269 /* we need to work around a Win95 bug - sometimes
1270 it gives ERRSRV/ERRerror temprarily */
1271 uint8 eclass;
1272 uint32 ecode;
1273
1274 SAFE_FREE(rdata);
1275 SAFE_FREE(rparam);
1276
1277 cli_dos_error(cli, &eclass, &ecode);
1278
1279 /*
1280 * OS/2 might return "no more files",
1281 * which just tells us, that searchcount is zero
1282 * in this search.
1283 * Guenter Kukkukk <linux@kukkukk.com>
1284 */
1285
1286 if (eclass == ERRDOS && ecode == ERRnofiles) {
1287 ff_searchcount = 0;
1288 cli_reset_error(cli);
1289 break;
1290 }
1291
1292 if (eclass != ERRSRV || ecode != ERRerror)
1293 break;
1294 smb_msleep(100);
1295 continue;
1296 }
1297
1298 if (cli_is_error(cli) || !rdata || !rparam)
1299 {
1300 if (First && info_level == 2)
1301 {
1302 // we have tried query ea size, but now will try without ea size
1303 info_level = 1;
1304 debuglocal(4,"list_files fallback to level %d\n", info_level);
1305 continue;
1306 }
1307 SAFE_FREE(rdata);
1308 SAFE_FREE(rparam);
1309 break;
1310 }
1311
1312 if (total_received == -1)
1313 total_received = 0;
1314
1315 /* parse out some important return info */
1316 p = rparam;
1317 if (First) {
1318 ff_dir_handle = SVAL(p,0);
1319 ff_searchcount = SVAL(p,2);
1320 ff_eos = SVAL(p,4);
1321 } else {
1322 ff_searchcount = SVAL(p,0);
1323 ff_eos = SVAL(p,2);
1324 }
1325 debuglocal(4,"list_files %d %d %d %d\n", ff_searchcount, ff_eos, "(ff_lastname)", First);
1326
1327 if (ff_searchcount == 0) {
1328 SAFE_FREE(rdata);
1329 SAFE_FREE(rparam);
1330 break;
1331 }
1332
1333 /* point to the data bytes */
1334 p = rdata;
1335
1336 memset(&finfo, 0, sizeof(finfo));
1337 finfo.easize = -1;
1338 /* we might need the lastname for continuations */
1339 for (p2=p,i=0;i<ff_searchcount;i++) {
1340 if ((info_level == 260) && (i == ff_searchcount-1)) {
1341 /* Last entry - fixup the last offset length. */
1342 SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2));
1343 }
1344 p2 += _os2_interpret_long_filename(cli,info_level,p2,&finfo,
1345 &resume_key,&last_name_raw,&last_name_raw_len);
1346
1347 if (!First && *mask && strcsequal(finfo.fname, mask)) {
1348 debuglocal(0,"Error: Looping in FIND_NEXT as name %s has already been seen?\n",
1349 finfo.fname);
1350 ff_eos = 1;
1351 break;
1352 }
1353 }
1354
1355 if (ff_searchcount > 0) {
1356 pstrcpy(mask, finfo.fname);
1357 } else {
1358 pstrcpy(mask,"");
1359 }
1360
1361 /* grab the data for later use */
1362 /* and add them to the dirlist pool */
1363 dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len);
1364
1365 if (!dirlist) {
1366 debuglocal(0,"cli_list_new: Failed to expand dirlist\n");
1367 SAFE_FREE(rdata);
1368 SAFE_FREE(rparam);
1369 break;
1370 }
1371
1372 memcpy(dirlist+dirlist_len,p,data_len);
1373 dirlist_len += data_len;
1374
1375 total_received += ff_searchcount;
1376
1377 SAFE_FREE(rdata);
1378 SAFE_FREE(rparam);
1379
1380 debuglocal(3,"received %d entries (eos=%d)\n",
1381 ff_searchcount,ff_eos);
1382
1383 if (ff_searchcount > 0)
1384 loop_count = 0;
1385
1386 First = False;
1387 }
1388
1389 mnt = cli_cm_get_mntpoint( cli );
1390
1391 /* see if the server disconnected or the connection otherwise failed */
1392 if (cli_is_error(cli)) {
1393 total_received = -1;
1394 } else {
1395 /* no connection problem. let user function add each entry */
1396 for (p=dirlist,i=0;i<total_received;i++) {
1397 p += _os2_interpret_long_filename(cli, info_level, p,
1398 &finfo,NULL,NULL,NULL);
1399 fn( mnt,&finfo, Mask, state );
1400 }
1401 }
1402
1403 /* free up the dirlist buffer and last name raw blob */
1404 SAFE_FREE(dirlist);
1405 data_blob_free(&last_name_raw);
1406 return(total_received);
1407}
1408
1409
1410/*****************************************************
1411open a directory on the server
1412*******************************************************/
1413int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1414{
1415 if (!srv || !cli || !state || !*state->mask)
1416 {
1417 return EINVAL;
1418 }
1419 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);
1420 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);
1421 if (*srv->workgroup == 0 && *srv->server_name == 0)
1422 {
1423 smbwrp_special_add(".", state);
1424 smbwrp_special_add("..", state);
1425 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1426 smbwrp_share_add, state);
1427 } else
1428 if (*srv->server_name == 0)
1429 {
1430 smbwrp_special_add(".", state);
1431 smbwrp_special_add("..", state);
1432
1433 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1434 smbwrp_share_add, state);
1435 } else
1436 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1437 {
1438 smbwrp_special_add(".", state);
1439 smbwrp_special_add("..", state);
1440
1441 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1442 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1443 {
1444 return os2cli_errno(cli);
1445 }
1446 } else
1447 if (strncmp(cli->dev,"LPT",3) == 0)
1448 {
1449 smbwrp_special_add(".", state);
1450 smbwrp_special_add("..", state);
1451 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1452 {
1453 return os2cli_errno(cli);
1454 }
1455 }
1456 else
1457 {
1458#if 0
1459 if (strcmp(path,"\\") == 0) {
1460 smbwrp_special_add(".", state);
1461 smbwrp_special_add("..", state);
1462 }
1463#endif
1464#if 0
1465 if (cli_list(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1466 smbwrp_dir_add_old, state) < 0)
1467#else
1468 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1469 smbwrp_dir_add, state) < 0)
1470#endif
1471 {
1472 return os2cli_errno(cli);
1473 }
1474 }
1475
1476 return 0;
1477}
1478
1479/*****************************************************
1480a wrapper for chdir()
1481*******************************************************/
1482int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1483{
1484 unsigned short mode = aDIR;
1485 smbwrp_fileinfo finfo = {0};
1486 if (!cli || !fname)
1487 {
1488 return EINVAL;
1489 }
1490
1491 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1492 if (smbwrp_getattr(srv, cli, &finfo))
1493 {
1494 return os2cli_errno(cli);
1495 }
1496
1497 if (!(finfo.attr & aDIR)) {
1498 return ENOTDIR;
1499 }
1500
1501 return 0;
1502}
1503
1504
1505/*****************************************************
1506a wrapper for mkdir()
1507*******************************************************/
1508int _System smbwrp_mkdir(cli_state * cli, char *fname)
1509{
1510 if (!cli || !fname)
1511 {
1512 return EINVAL;
1513 }
1514
1515 if (!cli_mkdir(cli, fname))
1516 {
1517 return os2cli_errno(cli);
1518 }
1519 return 0;
1520}
1521
1522/*****************************************************
1523a wrapper for rmdir()
1524*******************************************************/
1525int _System smbwrp_rmdir(cli_state * cli, char *fname)
1526{
1527 if (!cli || !fname)
1528 {
1529 return EINVAL;
1530 }
1531
1532 if (!cli_rmdir(cli, fname))
1533 {
1534 return os2cli_errno(cli);
1535 }
1536 return 0;
1537}
1538
1539/*****************************************************
1540set EA for a path
1541*******************************************************/
1542int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1543{
1544 if (!cli || !fname || !name)
1545 {
1546 return EINVAL;
1547 }
1548 if (!cli_set_ea_path(cli, fname, name, value, size))
1549 {
1550 return os2cli_errno(cli);
1551 }
1552 return 0;
1553}
1554
1555/*****************************************************
1556set EA for a file
1557*******************************************************/
1558int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1559{
1560 if (!cli || !file || !name)
1561 {
1562 return EINVAL;
1563 }
1564 if (!cli_set_ea_fnum(cli, file->fd, name, value, size))
1565 {
1566 return os2cli_errno(cli);
1567 }
1568 return 0;
1569}
1570
1571
1572#pragma pack(1)
1573typedef struct _FEA /* fea */
1574{
1575 unsigned char fEA; /* flags */
1576 unsigned char cbName; /* name length not including NULL */
1577 unsigned short cbValue; /* value length */
1578} FEA;
1579
1580typedef struct _FEALIST /* feal */
1581{
1582 unsigned long cbList; /* total bytes of structure including full list */
1583 FEA list[1]; /* variable length FEA structures */
1584} FEALIST;
1585#pragma pack()
1586
1587static int unilistea(cli_state * cli, char *fname, smbwrp_file *file, void * buffer, unsigned long size)
1588{
1589 int fnum, i;
1590 int gotsize = sizeof(unsigned long);
1591 size_t num_eas;
1592 struct ea_struct *ea_list = NULL;
1593 TALLOC_CTX *mem_ctx;
1594 FEA * p;
1595 FEALIST * pfealist;
1596 char * q;
1597
1598 mem_ctx = talloc_init("%d: ealist", _gettid());
1599 pfealist = (FEALIST *)buffer;
1600 pfealist->cbList = 0;
1601
1602 if (file)
1603 {
1604 if (!cli_get_ea_list_fnum(cli, file->fd, mem_ctx, &num_eas, &ea_list))
1605 {
1606 debuglocal(4,"ea_get_fnum list failed - %s\n", cli_errstr(cli));
1607 talloc_destroy(mem_ctx);
1608 return os2cli_errno(cli);
1609 }
1610 }
1611 else
1612 {
1613 if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list))
1614 {
1615 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1616 talloc_destroy(mem_ctx);
1617 return os2cli_errno(cli);
1618 }
1619 }
1620
1621 debuglocal(4,"num_eas = %d\n", num_eas);
1622
1623 // we will count that os/2 max EA size for file is 64kb
1624 p = pfealist->list;
1625 for (i = 0; i < num_eas; i++)
1626 {
1627 int namelen = strlen(ea_list[i].name);
1628 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);
1629 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1630 {
1631 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1632 continue;
1633 }
1634 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1635 if (size >= gotsize)
1636 {
1637 p->fEA = 0;
1638 p->cbName = namelen;
1639 p->cbValue = ea_list[i].value.length;
1640 q = (char *)(p + 1);
1641 strncpy(q, ea_list[i].name, namelen + 1);
1642 q += namelen + 1;
1643 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1644 p = (FEA *)(q + ea_list[i].value.length);
1645 }
1646 }
1647 pfealist->cbList = gotsize;
1648 debuglocal(4,"ret size = %d\n", gotsize);
1649
1650 talloc_destroy(mem_ctx);
1651 return 0;
1652}
1653
1654/*****************************************************
1655lists EA of a path
1656*******************************************************/
1657int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1658{
1659 if (!cli || !fname || !buffer)
1660 {
1661 return EINVAL;
1662 }
1663
1664 debuglocal(4,"EALIst for <%s>\n", fname);
1665 return unilistea(cli, fname, NULL, buffer, size);
1666}
1667
1668/*****************************************************
1669lists EA of a file
1670*******************************************************/
1671int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1672{
1673 if (!cli || !file || !buffer)
1674 {
1675 return EINVAL;
1676 }
1677
1678 debuglocal(4,"FEALIst for <%s>/%d\n", file->fname, file->fd);
1679 return unilistea(cli, NULL, file, buffer, size);
1680}
1681
1682/****************************************************************************
1683Check the space on a device.
1684****************************************************************************/
1685int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1686{
1687 int total, bsize, avail;
1688
1689 if (!cli || !pfsa)
1690 {
1691 return EINVAL;
1692 }
1693
1694 if (!cli_dskattr(cli, &bsize, &total, &avail))
1695 {
1696 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1697 return os2cli_errno(cli);
1698 }
1699
1700 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1701 total, bsize, avail);
1702
1703 // YD currently Samba return it in MB!
1704 pfsa->cSectorUnit = 1;
1705 if (bsize > 65536)
1706 {
1707 pfsa->cUnit = total*1024;
1708 pfsa->cUnitAvail = avail*1024;
1709 pfsa->cbSector = bsize/1024;
1710 }
1711 else
1712 {
1713 pfsa->cUnit = total;
1714 pfsa->cUnitAvail = avail;
1715 pfsa->cbSector = bsize;
1716 }
1717
1718 return 0;
1719}
Note: See TracBrowser for help on using the repository browser.