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

Last change on this file since 104 was 75, checked in by Paul Smedley, 18 years ago

return generated path info for workgroups and servers instead of an error code.

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