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

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

Add configurable kerberos support for Netdrive plugin

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