source: branches/client-1.5/src/smbwrp.c@ 150

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

Handle automatic reconnection, fixes for return codes.

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