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

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

Do not print password in smbcd logs

  • Property svn:eol-style set to native
File size: 43.3 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, int krb5support)
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. Master %s:%d\n", srv->username, 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
437 if (krb5support == 1){
438 debuglocal(1,"Kerberos support enabled\n");
439 c->use_kerberos = True;}
440
441 if (!cli_session_request(c, &calling, &called)) {
442 cli_shutdown(c);
443 if (strcmp(called.name, "*SMBSERVER")) {
444 make_nmb_name(&called , "*SMBSERVER", 0x20);
445 goto again;
446 }
447 return 4;
448 }
449
450 debuglocal(4," session request ok\n");
451
452 if (!cli_negprot(c)) {
453 cli_shutdown(c);
454 return 5;
455 }
456
457 debuglocal(4," session setuping for <%s>/<********> in <%s> %08x %08x %08x\n", srv->username, workgroup, c->protocol, c->sec_mode, c->capabilities);
458
459 if (!NT_STATUS_IS_OK(cli_session_setup(c, srv->username,
460 srv->password, strlen(srv->password),
461 srv->password, strlen(srv->password),
462 workgroup))) {
463 debuglocal(4,"%s/******** login failed\n", srv->username);
464 /* try an anonymous login if it failed */
465 if (!NT_STATUS_IS_OK(cli_session_setup(c, "", "", 1,"", 0, workgroup))) {
466 debuglocal(4,"Anonymous login failed");
467 cli_shutdown(c);
468 return 6;
469 }
470 }
471
472 debuglocal(4," session setup ok. Sending tconx <%s> <********>\n", share);
473
474 if (!cli_send_tconX(c, share, "?????",
475 srv->password, strlen(srv->password)+1)) {
476 cli_shutdown(c);
477 return 7;
478 }
479
480 debuglocal(4," tconx ok. cli caps %08x\n", c->capabilities);
481
482 // copy back cli_state
483 *cli = c;
484
485// srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
486
487 return 0;
488}
489
490/*****************************************************
491close a connection to a server
492*******************************************************/
493void _System smbwrp_disconnect(struct cli_state ** cli)
494{
495 if (cli)
496 {
497 // this call will free all buffers, close handles and free cli mem
498 cli_shutdown(*cli);
499 // set to zero because no longer valid
500 *cli = 0;
501 }
502}
503
504
505
506/*****************************************************
507a wrapper for open()
508*******************************************************/
509int _System smbwrp_open(cli_state * cli, smbwrp_file * file)
510{
511 int fd = -1;
512
513 if (!cli || !file || !*file->fname)
514 {
515 return EINVAL;
516 }
517 if (file->denymode < DENY_ALL || file->denymode > DENY_NONE)
518 {
519 file->denymode = DENY_NONE;
520 }
521
522 debuglocal(4,"cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
523 file->fd = cli_open(cli, file->fname, file->openmode, file->denymode);
524 if (file->fd == -1)
525 {
526 return os2cli_errno(cli);
527 }
528 if (file->openmode & (O_WRONLY | O_RDWR | O_TRUNC | O_CREAT))
529 {
530 time_t t;
531 file->mtime = time(NULL);
532 t = get_time_zone(file->mtime);
533 debuglocal(4,"cli_open mtime %lu %lu\n", file->mtime, t);
534 file->mtime -= t;
535 }
536 file->offset = 0;
537 return 0;
538}
539
540/*****************************************************
541a wrapper for read()
542*******************************************************/
543int _System smbwrp_read(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
544{
545 int ret;
546
547 if (!cli || !file || !buf || !result)
548 {
549 return EINVAL;
550 }
551
552 *result = 0;
553 ret = cli_read(cli, file->fd, buf, file->offset, count);
554 if (ret == -1)
555 {
556 return os2cli_errno(cli);
557 }
558
559 file->offset += ret;
560 *result = ret;
561 return 0;
562}
563
564
565
566/*****************************************************
567a wrapper for write()
568*******************************************************/
569int _System smbwrp_write(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
570{
571 int ret;
572
573 if (!cli || !file || !buf || !result)
574 {
575 return EINVAL;
576 }
577
578 *result = 0;
579//debuglocal(1,("Write %x %d %lld %d", cli, file->fd, file->offset, count));
580 ret = cli_write(cli, file->fd, 0, buf, file->offset, count);
581 if (ret == -1)
582 {
583 return os2cli_errno(cli);
584 }
585
586 file->offset += ret;
587 *result = ret;
588 return 0;
589}
590
591/*****************************************************
592a wrapper for close()
593*******************************************************/
594int _System smbwrp_close(cli_state * cli, smbwrp_file * file)
595{
596 int rc = 0;
597 if (!cli || !file)
598 {
599 return EINVAL;
600 }
601
602
603 if (!cli_close(cli, file->fd))
604 {
605 return os2cli_errno(cli);
606 }
607 file->fd = -1;
608 file->offset = 0;
609 if (file->openattr || file->mtime)
610 {
611 debuglocal(4,"Set attr on close %s %08x %d %d\n", file->fname, file->openattr, file->mtime, file->mtime + get_time_zone(file->mtime));
612 if (!cli_setatr(cli, file->fname, file->openattr, file->mtime + get_time_zone(file->mtime)))
613 {
614 debuglocal(4,"Set attr on close failed %d\n", os2cli_errno(cli));
615 //rc = os2cli_errno(cli);
616 }
617 file->openattr = 0;
618 file->mtime = 0;
619 }
620 *file->fname = 0;
621 return rc;
622}
623
624/*****************************************************
625a wrapper for setfilesize()
626*******************************************************/
627int cli_setfilenewsize(struct cli_state *cli, int fnum, off_t newsize)
628{
629 unsigned int data_len = 8;
630 unsigned int param_len = 6;
631 uint16 setup = TRANSACT2_SETFILEINFO;
632 pstring param;
633 char *rparam=NULL, *rdata=NULL;
634
635 memset(param, 0, param_len);
636 SSVAL(param,0,fnum);
637 SSVAL(param,2,SMB_SET_FILE_END_OF_FILE_INFO);
638
639 if (!cli_send_trans(cli, SMBtrans2,
640 NULL, /* name */
641 -1, 0, /* fid, flags */
642 &setup, 1, 0, /* setup, length, max */
643 param, param_len, 2, /* param, length, max */
644 (char *)&newsize, sizeof(newsize), cli->max_xmit /* data, length, max */
645 )) {
646 return False;
647 }
648
649 if (!cli_receive_trans(cli, SMBtrans2,
650 &rparam, &param_len,
651 &rdata, &data_len)) {
652 return False;
653 }
654
655 SAFE_FREE(rdata);
656 SAFE_FREE(rparam);
657
658 return True;
659}
660
661int _System smbwrp_setfilesize(cli_state * cli, smbwrp_file * file, long long newsize)
662{
663 int rc = 0;
664 if (!cli || !file)
665 {
666 return EINVAL;
667 }
668
669 debuglocal(4,"cli_setnewfileszie(%s) %lld\n", file->fname, newsize);
670 if (!cli_setfilenewsize(cli, file->fd, newsize))
671 {
672 if (newsize)
673 {
674 rc = os2cli_errno(cli);
675 }
676
677 if (!cli_close(cli, file->fd))
678 {
679 return os2cli_errno(cli);
680 }
681 file->fd = -1;
682 file->offset = 0;
683 file->openmode &= ~(O_CREAT | O_EXCL);
684 file->openmode |= O_TRUNC;
685 debuglocal(4,"cli_setnewfileszie : cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
686 file->fd = cli_open(cli, file->fname, file->openmode, file->denymode);
687 if (file->fd == -1)
688 {
689 return os2cli_errno(cli);
690 }
691 }
692 return 0;
693}
694
695/*****************************************************
696a wrapper for rename()
697*******************************************************/
698int _System smbwrp_rename(cli_state * cli, char *oldname, char *newname)
699{
700 if (!cli || !oldname || !newname)
701 {
702 return EINVAL;
703 }
704
705 debuglocal(1,"Rename <%s> -> <%s>\n", oldname, newname);
706 //cli_unlink(cli, newname);
707// if (!cli_rename(cli, oldname, newname) && !cli_ntrename(cli, oldname, newname))
708 if (!cli_rename(cli, oldname, newname))
709 {
710 return os2cli_errno(cli);
711 }
712 return 0;
713}
714
715
716/*****************************************************
717a wrapper for chmod()
718*******************************************************/
719int _System smbwrp_setattr(cli_state * cli, smbwrp_fileinfo *finfo)
720{
721 if (!cli || !finfo || !*finfo->fname)
722 {
723 return EINVAL;
724 }
725
726debuglocal(4,"Setting on <%s> attr %04x, time %lu/%lu\n", finfo->fname, finfo->attr, finfo->mtime, finfo->mtime + get_time_zone(finfo->mtime));
727 if (!cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime + (finfo->mtime == 0 ? 0 : get_time_zone(finfo->mtime)))
728 && !cli_setatr(cli, finfo->fname, finfo->attr, 0))
729 {
730 return os2cli_errno(cli);
731 }
732 return 0;
733}
734
735/*****************************************************
736a wrapper for unlink()
737*******************************************************/
738int _System smbwrp_unlink(cli_state * cli, const char *fname)
739{
740 if (!cli || !fname)
741 {
742 return EINVAL;
743 }
744#if 0
745 if (strncmp(cli->dev, "LPT", 3) == 0)
746 {
747 int job = smbw_stat_printjob(cli, fname, NULL, NULL);
748 if (job == -1)
749 {
750 goto failed;
751 }
752 if (cli_printjob_del(cli, job) != 0)
753 {
754 goto failed;
755 }
756 } else
757#endif
758 if (!cli_unlink(cli, fname))
759 {
760 return os2cli_errno(cli);
761 }
762 return 0;
763}
764
765/*****************************************************
766a wrapper for lseek()
767*******************************************************/
768int _System smbwrp_lseek(cli_state * cli, smbwrp_file * file, int whence, long long offset)
769{
770 off_t size;
771 if (!cli || !file)
772 {
773 return EINVAL;
774 }
775
776 debuglocal(4,"lseek %d %lld %lld\n", whence, offset, file->offset);
777
778 switch (whence) {
779 case SEEK_SET:
780 if (offset < 0)
781 {
782 return EINVAL;
783 }
784 file->offset = offset;
785 break;
786 case SEEK_CUR:
787 file->offset += offset;
788 break;
789 case SEEK_END:
790 if (offset > 0)
791 {
792 return EINVAL;
793 }
794 if (!cli_qfileinfo3(cli, file->fd,
795 NULL, &size, NULL, NULL, NULL,
796 NULL, NULL) &&
797 !cli_getattrE(cli, file->fd,
798 NULL, (SMB_BIG_UINT *)&size, NULL, NULL, NULL))
799 {
800 return os2cli_errno(cli);
801 }
802 file->offset = size + offset;
803 break;
804 default: return EINVAL;
805 }
806
807 return 0;
808}
809
810/*****************************************************
811try to do a QPATHINFO and if that fails then do a getatr
812this is needed because win95 sometimes refuses the qpathinfo
813*******************************************************/
814int _System smbwrp_getattr(smbwrp_server *srv, cli_state * cli, smbwrp_fileinfo *finfo)
815{
816 SMB_INO_T ino = 0;
817 if (!cli || !finfo || !*finfo->fname)
818 {
819 return EINVAL;
820 }
821 debuglocal(4,"getattr %d %d <%s>\n", cli->capabilities & CAP_NOPATHINFO2, cli->capabilities & CAP_NT_SMBS, finfo->fname);
822 if (!(cli->capabilities & CAP_NOPATHINFO2) &&
823 cli_qpathinfo3(cli, finfo->fname, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,
824 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino))
825 {
826 finfo->attr &= 0x7F;
827//debuglocal(2,("gotattr %08x <%s>\n", finfo->attr, finfo->fname));
828// finfo->ctime -= get_time_zone(finfo->ctime);
829// finfo->atime -= get_time_zone(finfo->atime);
830// finfo->mtime -= get_time_zone(finfo->mtime);
831 return 0;
832 }
833//debuglocal(2,("getattr rc1 %d\n", os2cli_errno(cli)));
834
835 /* If the path is not on a share (it is a workgroup or a server),
836 * then cli_qpathinfo3 obviously fails. Return some fake information
837 * about the directory.
838 */
839 if ( *srv->server_name == 0
840 || (strcmp(cli->dev,"IPC") == 0)
841 || *srv->share_name == 0
842 || (stricmp(srv->share_name,"IPC$") == 0)
843 || (strncmp(cli->dev,"LPT",3) == 0)
844 )
845 {
846 debuglocal(4,"getattr not a share.\n");
847 *(time_t *)&finfo->ctime = time (NULL);
848 *(time_t *)&finfo->atime = time (NULL);
849 *(time_t *)&finfo->mtime = time (NULL);
850 finfo->size = 0;
851 finfo->easize = 0;
852 finfo->attr = aDIR;
853 return 0;
854 }
855
856 /* if this is NT then don't bother with the getatr */
857 if (cli->capabilities & CAP_NT_SMBS && !(cli->capabilities & CAP_NOPATHINFO2))
858 {
859 int rc = os2cli_errno(cli);
860 // cli_qpathinfo* reports EINVAL when path of given file not exists
861 // thus there is no real situation when EINVAL should be returned to
862 // client at this point, we just replace it to ENOTDIR
863 if (rc == EINVAL)
864 {
865 rc = ENOTDIR;
866 }
867 return rc;
868 }
869
870 if (cli_getatr(cli, finfo->fname, (unsigned short *)&finfo->attr, (size_t *)&finfo->size, (time_t *)&finfo->mtime))
871 {
872//debuglocal(2,("gotattr1 %08x <%s>\n", finfo->attr, finfo->fname));
873 finfo->mtime -= get_time_zone(finfo->mtime);
874 finfo->atime = finfo->atime; //was mtime
875 finfo->ctime = finfo->ctime; //was mtime
876 cli->capabilities &= CAP_NOPATHINFO2;
877 return 0;
878 }
879 return os2cli_errno(cli);
880}
881
882/*****************************************************
883try to do a QPATHINFO and if that fails then do a getatr
884this is needed because win95 sometimes refuses the qpathinfo
885*******************************************************/
886int _System smbwrp_fgetattr(cli_state * cli, smbwrp_file *file, smbwrp_fileinfo *finfo)
887{
888 SMB_INO_T ino = 0;
889 if (!cli || !file || !finfo)
890 {
891 return EINVAL;
892 }
893
894 strncpy(finfo->fname, file->fname, sizeof(finfo->fname) - 1);
895 if (!cli_qfileinfo3(cli, file->fd,
896 (unsigned short *)&finfo->attr, (off_t *)&finfo->size, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,
897 &ino))
898 {
899 if (!cli_getattrE(cli, file->fd,
900 (unsigned short *)&finfo->attr, (SMB_BIG_UINT *)(&finfo->size), (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime))
901 {
902 return os2cli_errno(cli);
903 }
904 else
905 {
906 finfo->ctime -= get_time_zone(finfo->ctime);
907 finfo->atime -= get_time_zone(finfo->atime);
908 finfo->mtime -= get_time_zone(finfo->mtime);
909 }
910 }
911 else
912 {
913// finfo->ctime -= get_time_zone(finfo->ctime);
914// finfo->atime -= get_time_zone(finfo->atime);
915// finfo->mtime -= get_time_zone(finfo->mtime);
916 }
917
918 return 0;
919}
920
921// =============================DIRECTORY ROUTINES============================
922
923/*****************************************************
924add a entry to a directory listing
925*******************************************************/
926static void smbwrp_dir_add(const char* mnt, smbwrp_fileinfo *finfo, const char *mask, void *state)
927{
928 if (state && finfo)
929 {
930 filelist_state * st = (filelist_state *)state;
931 if (st->add_dir_entry)
932 {
933debuglocal(8,"adding <%s> %d %d\n", finfo->fname, sizeof(st->finfo), st->datalen);
934 memcpy(&st->finfo, finfo, sizeof(st->finfo));
935 st->add_dir_entry(state);
936 }
937 }
938}
939
940#if 0
941static void smbwrp_dir_add_old(struct file_info *finfo, const char *mask, void *state)
942{
943 if (state && finfo)
944 {
945 filelist_state * st = (filelist_state *)state;
946 if (st->add_dir_entry)
947 {
948 strncpy(st->finfo.fname, finfo->name, sizeof(st->finfo.fname) - 1);
949 st->finfo.size = finfo->size;
950 st->finfo.easize = -1;
951 st->finfo.attr = finfo->mode;
952 st->finfo.ctime = finfo->ctime_ts.tv_sec - get_time_zone(finfo->ctime_ts.tv_sec);
953 st->finfo.mtime = finfo->mtime_ts.tv_sec - get_time_zone(finfo->mtime_ts.tv_sec);
954 st->finfo.atime = finfo->atime_ts.tv_sec - get_time_zone(finfo->atime_ts.tv_sec);
955 st->add_dir_entry(state);
956 }
957 }
958}
959#endif
960
961static void smbwrp_special_add(const char * name, void * state)
962{
963 smbwrp_fileinfo finfo = {0};
964
965 if (!name)
966 {
967 return;
968 }
969
970 ZERO_STRUCT(finfo);
971
972 strncpy(finfo.fname, name, sizeof(finfo.fname) - 1);
973 finfo.attr = aRONLY | aDIR;
974
975 smbwrp_dir_add("", &finfo, NULL, state);
976}
977
978static void smbwrp_printjob_add(struct print_job_info *job, void * state)
979{
980 smbwrp_fileinfo finfo = {0};
981
982 ZERO_STRUCT(finfo);
983
984//printf("Printjob <%s>\n", job->name);
985
986 strncpy(finfo.fname, job->name, sizeof(finfo.fname) - 1);
987 finfo.mtime = job->t - get_time_zone(job->t);
988 finfo.atime = finfo.atime; //was mtime
989 finfo.ctime = finfo.ctime; //was mtime
990 finfo.attr = aRONLY;
991 finfo.size = job->size;
992
993 smbwrp_dir_add("", &finfo, NULL, state);
994}
995
996static void smbwrp_share_add(const char *share, uint32 type,
997 const char *comment, void *state)
998{
999 smbwrp_fileinfo finfo = {0};
1000
1001 if (strcmp(share,"IPC$") == 0) return;
1002
1003 ZERO_STRUCT(finfo);
1004
1005 strncpy(finfo.fname, share, sizeof(finfo.fname) - 1);
1006 finfo.attr = aRONLY | aDIR;
1007
1008 smbwrp_dir_add("", &finfo, NULL, state);
1009}
1010
1011/****************************************************************************
1012 Interpret a long filename structure - this is mostly guesses at the moment.
1013 The length of the structure is returned
1014 The structure of a long filename depends on the info level. 260 is used
1015 by NT and 2 is used by OS/2
1016****************************************************************************/
1017// YD from libsmb\clilist.c
1018static size_t _os2_interpret_long_filename(struct cli_state *cli,
1019 int level,char *p, smbwrp_fileinfo *finfo,
1020 uint32 *p_resume_key, DATA_BLOB *p_last_name_raw, uint32 *p_last_name_raw_len)
1021{
1022 extern file_info def_finfo;
1023 int len;
1024 char *base = p;
1025 smbwrp_fileinfo finfo1;
1026
1027 if (!finfo) finfo = &finfo1;
1028
1029 finfo->attr = def_finfo.mode;
1030 finfo->mtime = def_finfo.mtime_ts.tv_sec;
1031 finfo->atime = def_finfo.atime_ts.tv_sec;
1032 finfo->ctime = def_finfo.ctime_ts.tv_sec;
1033 strncpy(finfo->fname, def_finfo.name, sizeof(finfo->fname) - 1);
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 0
1081 if (p_resume_key) {
1082 *p_resume_key = IVAL(p,0);
1083 }
1084#endif
1085 p += 4; /* fileindex */
1086
1087 /* Offset zero is "create time", not "change time". */
1088 p += 8;
1089 finfo->atime = interpret_long_date(p).tv_sec - cli->serverzone;
1090 p += 8;
1091 finfo->mtime = interpret_long_date(p).tv_sec - cli->serverzone;
1092 p += 8;
1093 finfo->ctime = interpret_long_date(p).tv_sec - cli->serverzone;
1094 p += 8;
1095 finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0);
1096 p += 8;
1097 p += 8; /* alloc size */
1098 finfo->attr = CVAL(p,0);
1099 p += 4;
1100 namelen = IVAL(p,0);
1101 p += 4;
1102 finfo->easize = IVAL(p,0);
1103 p += 4; /* EA size */
1104 slen = SVAL(p, 0);
1105 p += 2;
1106#if 0
1107 {
1108 /* stupid NT bugs. grr */
1109 int flags = 0;
1110 if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE;
1111 clistr_pull(cli, finfo->short_name, p,
1112 sizeof(finfo->short_name),
1113 slen, flags);
1114 }
1115#endif
1116 p += 24; /* short name? */
1117 clistr_pull(cli, finfo->fname, p,
1118 sizeof(finfo->fname),
1119 namelen, 0);
1120
1121 /* To be robust in the face of unicode conversion failures
1122 we need to copy the raw bytes of the last name seen here.
1123 Namelen doesn't include the terminating unicode null, so
1124 copy it here. */
1125#if 0
1126 if (p_last_name_raw && p_last_name_raw_len) {
1127 if (namelen + 2 > p_last_name_raw->length) {
1128 memset(p_last_name_raw->data, '\0', sizeof(p_last_name_raw->length));
1129 *p_last_name_raw_len = 0;
1130 } else {
1131 memcpy(p_last_name_raw->data, p, namelen);
1132 SSVAL(p_last_name_raw->data, namelen, 0);
1133 *p_last_name_raw_len = namelen + 2;
1134 }
1135 }
1136#endif
1137 return (size_t)IVAL(base, 0);
1138 }
1139 }
1140
1141 debuglocal(1,"Unknown long filename format %d\n",level);
1142 return (size_t)IVAL(base,0);
1143}
1144
1145/****************************************************************************
1146 Do a directory listing, calling fn on each file found.
1147 Modified from cli_list_new
1148****************************************************************************/
1149
1150static int list_files(struct cli_state *cli, const char *Mask, uint16 attribute,
1151 void (*fn)(const char*, smbwrp_fileinfo *, const char *, void *), void *state)
1152{
1153#if 1
1154 int max_matches = 1366; /* Match W2k - was 512. */
1155#else
1156 int max_matches = 512;
1157#endif
1158 int info_level;
1159 char *p, *p2;
1160 pstring mask;
1161 smbwrp_fileinfo finfo;
1162 int i;
1163 char *dirlist = NULL;
1164 int dirlist_len = 0;
1165 int total_received = -1;
1166 BOOL First = True;
1167 int ff_searchcount=0;
1168 int ff_eos=0;
1169 int ff_dir_handle=0;
1170 int loop_count = 0;
1171 char *rparam=NULL, *rdata=NULL;
1172 unsigned int param_len, data_len;
1173 uint16 setup;
1174 pstring param;
1175 const char *mnt;
1176 uint32 resume_key = 0;
1177 uint32 last_name_raw_len = 0;
1178 DATA_BLOB last_name_raw = data_blob(NULL, 2*sizeof(pstring));
1179
1180 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1181 info_level = (cli->capabilities&CAP_NT_SMBS)?260:2;
1182
1183 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, mask);
1184
1185 /* when getting a directory listing from a 2k dfs root share,
1186 we have to include the full path (\server\share\mask) here */
1187
1188 if ( cli->dfsroot )
1189 pstr_sprintf( mask, "\\%s\\%s\\%s", cli->desthost, cli->share, Mask );
1190 else
1191 pstrcpy(mask,Mask);
1192
1193 while (ff_eos == 0) {
1194 loop_count++;
1195 if (loop_count > 200) {
1196 debuglocal(0,"Error: Looping in FIND_NEXT??\n");
1197 break;
1198 }
1199
1200 if (First) {
1201 setup = TRANSACT2_FINDFIRST;
1202 SSVAL(param,0,attribute); /* attribute */
1203 SSVAL(param,2,max_matches); /* max count */
1204 SSVAL(param,4,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1205 SSVAL(param,6,info_level);
1206 SIVAL(param,8,0);
1207 p = param+12;
1208 p += clistr_push(cli, param+12, mask, sizeof(param)-12,
1209 STR_TERMINATE);
1210 } else {
1211 setup = TRANSACT2_FINDNEXT;
1212 SSVAL(param,0,ff_dir_handle);
1213 SSVAL(param,2,max_matches); /* max count */
1214 SSVAL(param,4,info_level);
1215 /* For W2K servers serving out FAT filesystems we *must* set the
1216 resume key. If it's not FAT then it's returned as zero. */
1217 SIVAL(param,6,resume_key); /* ff_resume_key */
1218 /* NB. *DON'T* use continue here. If you do it seems that W2K and bretheren
1219 can miss filenames. Use last filename continue instead. JRA */
1220 SSVAL(param,10,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1221 p = param+12;
1222 if (last_name_raw_len && (last_name_raw_len < (sizeof(param)-12))) {
1223 memcpy(p, last_name_raw.data, last_name_raw_len);
1224 p += last_name_raw_len;
1225 } else {
1226 p += clistr_push(cli, param+12, mask, sizeof(param)-12, STR_TERMINATE);
1227 }
1228 }
1229
1230 param_len = PTR_DIFF(p, param);
1231
1232 if (!cli_send_trans(cli, SMBtrans2,
1233 NULL, /* Name */
1234 -1, 0, /* fid, flags */
1235 &setup, 1, 0, /* setup, length, max */
1236 param, param_len, 10, /* param, length, max */
1237 NULL, 0,
1238#if 0
1239 /* w2k value. */
1240 MIN(16384,cli->max_xmit) /* data, length, max. */
1241#else
1242 cli->max_xmit /* data, length, max. */
1243#endif
1244 )) {
1245 break;
1246 }
1247
1248 if (!cli_receive_trans(cli, SMBtrans2,
1249 &rparam, &param_len,
1250 &rdata, &data_len) &&
1251 cli_is_dos_error(cli)) {
1252 /* we need to work around a Win95 bug - sometimes
1253 it gives ERRSRV/ERRerror temprarily */
1254 uint8 eclass;
1255 uint32 ecode;
1256
1257 SAFE_FREE(rdata);
1258 SAFE_FREE(rparam);
1259
1260 cli_dos_error(cli, &eclass, &ecode);
1261 if (eclass != ERRSRV || ecode != ERRerror)
1262 break;
1263 smb_msleep(100);
1264 continue;
1265 }
1266
1267 if (cli_is_error(cli) || !rdata || !rparam)
1268 {
1269 if (First && info_level == 2)
1270 {
1271 // we have tried query ea size, but now will try without ea size
1272 info_level = 1;
1273 debuglocal(4,"list_files fallback to level %d\n", info_level);
1274 continue;
1275 }
1276 SAFE_FREE(rdata);
1277 SAFE_FREE(rparam);
1278 break;
1279 }
1280
1281 if (total_received == -1)
1282 total_received = 0;
1283
1284 /* parse out some important return info */
1285 p = rparam;
1286 if (First) {
1287 ff_dir_handle = SVAL(p,0);
1288 ff_searchcount = SVAL(p,2);
1289 ff_eos = SVAL(p,4);
1290 } else {
1291 ff_searchcount = SVAL(p,0);
1292 ff_eos = SVAL(p,2);
1293 }
1294 debuglocal(4,"list_files %d %d %d %d\n", ff_searchcount, ff_eos, "(ff_lastname)", First);
1295
1296 if (ff_searchcount == 0) {
1297 SAFE_FREE(rdata);
1298 SAFE_FREE(rparam);
1299 break;
1300 }
1301
1302 /* point to the data bytes */
1303 p = rdata;
1304
1305 memset(&finfo, 0, sizeof(finfo));
1306 finfo.easize = -1;
1307 /* we might need the lastname for continuations */
1308 for (p2=p,i=0;i<ff_searchcount;i++) {
1309 if ((info_level == 260) && (i == ff_searchcount-1)) {
1310 /* Last entry - fixup the last offset length. */
1311 SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2));
1312 }
1313 p2 += _os2_interpret_long_filename(cli,info_level,p2,&finfo,
1314 &resume_key,&last_name_raw,&last_name_raw_len);
1315
1316 if (!First && *mask && strcsequal(finfo.fname, mask)) {
1317 debuglocal(0,"Error: Looping in FIND_NEXT as name %s has already been seen?\n",
1318 finfo.fname);
1319 ff_eos = 1;
1320 break;
1321 }
1322 }
1323
1324 if (ff_searchcount > 0) {
1325 pstrcpy(mask, finfo.fname);
1326 } else {
1327 pstrcpy(mask,"");
1328 }
1329
1330 /* grab the data for later use */
1331 /* and add them to the dirlist pool */
1332 dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len);
1333
1334 if (!dirlist) {
1335 debuglocal(0,"cli_list_new: Failed to expand dirlist\n");
1336 SAFE_FREE(rdata);
1337 SAFE_FREE(rparam);
1338 break;
1339 }
1340
1341 memcpy(dirlist+dirlist_len,p,data_len);
1342 dirlist_len += data_len;
1343
1344 total_received += ff_searchcount;
1345
1346 SAFE_FREE(rdata);
1347 SAFE_FREE(rparam);
1348
1349 debuglocal(3,"received %d entries (eos=%d)\n",
1350 ff_searchcount,ff_eos);
1351
1352 if (ff_searchcount > 0)
1353 loop_count = 0;
1354
1355 First = False;
1356 }
1357
1358 mnt = cli_cm_get_mntpoint( cli );
1359
1360 /* see if the server disconnected or the connection otherwise failed */
1361 if (cli_is_error(cli)) {
1362 total_received = -1;
1363 } else {
1364 /* no connection problem. let user function add each entry */
1365 for (p=dirlist,i=0;i<total_received;i++) {
1366 p += _os2_interpret_long_filename(cli, info_level, p,
1367 &finfo,NULL,NULL,NULL);
1368 fn( mnt,&finfo, Mask, state );
1369 }
1370 }
1371
1372 /* free up the dirlist buffer and last name raw blob */
1373 SAFE_FREE(dirlist);
1374 data_blob_free(&last_name_raw);
1375 return(total_received);
1376}
1377
1378
1379/*****************************************************
1380open a directory on the server
1381*******************************************************/
1382int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1383{
1384 if (!srv || !cli || !state || !*state->mask)
1385 {
1386 return EINVAL;
1387 }
1388 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);
1389 if (*srv->workgroup == 0 && *srv->server_name == 0)
1390 {
1391 smbwrp_special_add(".", state);
1392 smbwrp_special_add("..", state);
1393 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1394 smbwrp_share_add, state);
1395 } else
1396 if (*srv->server_name == 0)
1397 {
1398 smbwrp_special_add(".", state);
1399 smbwrp_special_add("..", state);
1400
1401 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1402 smbwrp_share_add, state);
1403 } else
1404 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1405 {
1406 smbwrp_special_add(".", state);
1407 smbwrp_special_add("..", state);
1408
1409 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1410 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1411 {
1412 return os2cli_errno(cli);
1413 }
1414 } else
1415 if (strncmp(cli->dev,"LPT",3) == 0)
1416 {
1417 smbwrp_special_add(".", state);
1418 smbwrp_special_add("..", state);
1419 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1420 {
1421 return os2cli_errno(cli);
1422 }
1423 }
1424 else
1425 {
1426#if 0
1427 if (strcmp(path,"\\") == 0) {
1428 smbwrp_special_add(".", state);
1429 smbwrp_special_add("..", state);
1430 }
1431#endif
1432#if 0
1433 if (cli_list(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1434 smbwrp_dir_add_old, state) < 0)
1435#else
1436 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1437 smbwrp_dir_add, state) < 0)
1438#endif
1439 {
1440 return os2cli_errno(cli);
1441 }
1442 }
1443
1444 return 0;
1445}
1446
1447/*****************************************************
1448a wrapper for chdir()
1449*******************************************************/
1450int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1451{
1452 unsigned short mode = aDIR;
1453 smbwrp_fileinfo finfo = {0};
1454 if (!cli || !fname)
1455 {
1456 return EINVAL;
1457 }
1458
1459 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1460 if (smbwrp_getattr(srv, cli, &finfo))
1461 {
1462 return os2cli_errno(cli);
1463 }
1464
1465 if (!(finfo.attr & aDIR)) {
1466 return ENOTDIR;
1467 }
1468
1469 return 0;
1470}
1471
1472
1473/*****************************************************
1474a wrapper for mkdir()
1475*******************************************************/
1476int _System smbwrp_mkdir(cli_state * cli, char *fname)
1477{
1478 if (!cli || !fname)
1479 {
1480 return EINVAL;
1481 }
1482
1483 if (!cli_mkdir(cli, fname))
1484 {
1485 return os2cli_errno(cli);
1486 }
1487 return 0;
1488}
1489
1490/*****************************************************
1491a wrapper for rmdir()
1492*******************************************************/
1493int _System smbwrp_rmdir(cli_state * cli, char *fname)
1494{
1495 if (!cli || !fname)
1496 {
1497 return EINVAL;
1498 }
1499
1500 if (!cli_rmdir(cli, fname))
1501 {
1502 return os2cli_errno(cli);
1503 }
1504 return 0;
1505}
1506
1507/*****************************************************
1508set EA for a path
1509*******************************************************/
1510int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1511{
1512 if (!cli || !fname || !name)
1513 {
1514 return EINVAL;
1515 }
1516 if (!cli_set_ea_path(cli, fname, name, value, size))
1517 {
1518 return os2cli_errno(cli);
1519 }
1520 return 0;
1521}
1522
1523/*****************************************************
1524set EA for a file
1525*******************************************************/
1526int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1527{
1528 if (!cli || !file || !name)
1529 {
1530 return EINVAL;
1531 }
1532 if (!cli_set_ea_fnum(cli, file->fd, name, value, size))
1533 {
1534 return os2cli_errno(cli);
1535 }
1536 return 0;
1537}
1538
1539
1540#pragma pack(1)
1541typedef struct _FEA /* fea */
1542{
1543 unsigned char fEA; /* flags */
1544 unsigned char cbName; /* name length not including NULL */
1545 unsigned short cbValue; /* value length */
1546} FEA;
1547
1548typedef struct _FEALIST /* feal */
1549{
1550 unsigned long cbList; /* total bytes of structure including full list */
1551 FEA list[1]; /* variable length FEA structures */
1552} FEALIST;
1553#pragma pack()
1554
1555static int unilistea(cli_state * cli, char *fname, smbwrp_file *file, void * buffer, unsigned long size)
1556{
1557 int fnum, i;
1558 int gotsize = sizeof(unsigned long);
1559 size_t num_eas;
1560 struct ea_struct *ea_list = NULL;
1561 TALLOC_CTX *mem_ctx;
1562 FEA * p;
1563 FEALIST * pfealist;
1564 char * q;
1565
1566 mem_ctx = talloc_init("%d: ealist", _gettid());
1567 pfealist = (FEALIST *)buffer;
1568 pfealist->cbList = 0;
1569
1570 if (file)
1571 {
1572 if (!cli_get_ea_list_fnum(cli, file->fd, mem_ctx, &num_eas, &ea_list))
1573 {
1574 debuglocal(4,"ea_get_fnum list failed - %s\n", cli_errstr(cli));
1575 talloc_destroy(mem_ctx);
1576 return os2cli_errno(cli);
1577 }
1578 }
1579 else
1580 {
1581 if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list))
1582 {
1583 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1584 talloc_destroy(mem_ctx);
1585 return os2cli_errno(cli);
1586 }
1587 }
1588
1589 debuglocal(4,"num_eas = %d\n", num_eas);
1590
1591 // we will count that os/2 max EA size for file is 64kb
1592 p = pfealist->list;
1593 for (i = 0; i < num_eas; i++)
1594 {
1595 int namelen = strlen(ea_list[i].name);
1596 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);
1597 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1598 {
1599 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1600 continue;
1601 }
1602 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1603 if (size >= gotsize)
1604 {
1605 p->fEA = 0;
1606 p->cbName = namelen;
1607 p->cbValue = ea_list[i].value.length;
1608 q = (char *)(p + 1);
1609 strncpy(q, ea_list[i].name, namelen + 1);
1610 q += namelen + 1;
1611 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1612 p = (FEA *)(q + ea_list[i].value.length);
1613 }
1614 }
1615 pfealist->cbList = gotsize;
1616 debuglocal(4,"ret size = %d\n", gotsize);
1617
1618 talloc_destroy(mem_ctx);
1619 return 0;
1620}
1621
1622/*****************************************************
1623lists EA of a path
1624*******************************************************/
1625int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1626{
1627 if (!cli || !fname || !buffer)
1628 {
1629 return EINVAL;
1630 }
1631
1632 debuglocal(4,"EALIst for <%s>\n", fname);
1633 return unilistea(cli, fname, NULL, buffer, size);
1634}
1635
1636/*****************************************************
1637lists EA of a file
1638*******************************************************/
1639int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1640{
1641 if (!cli || !file || !buffer)
1642 {
1643 return EINVAL;
1644 }
1645
1646 debuglocal(4,"FEALIst for <%s>/%d\n", file->fname, file->fd);
1647 return unilistea(cli, NULL, file, buffer, size);
1648}
1649
1650/****************************************************************************
1651Check the space on a device.
1652****************************************************************************/
1653int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1654{
1655 int total, bsize, avail;
1656
1657 if (!cli || !pfsa)
1658 {
1659 return EINVAL;
1660 }
1661
1662 if (!cli_dskattr(cli, &bsize, &total, &avail))
1663 {
1664 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1665 return os2cli_errno(cli);
1666 }
1667
1668 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1669 total, bsize, avail);
1670
1671 // YD currently Samba return it in MB!
1672 pfsa->cSectorUnit = 1;
1673 if (bsize > 65536)
1674 {
1675 pfsa->cUnit = total*1024;
1676 pfsa->cUnitAvail = avail*1024;
1677 pfsa->cbSector = bsize/1024;
1678 }
1679 else
1680 {
1681 pfsa->cUnit = total;
1682 pfsa->cUnitAvail = avail;
1683 pfsa->cbSector = bsize;
1684 }
1685
1686 return 0;
1687}
Note: See TracBrowser for help on using the repository browser.