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

Last change on this file since 124 was 124, checked in by Paul Smedley, 17 years ago

Update source to 3.0.28a

  • Property svn:eol-style set to native
File size: 43.6 KB
Line 
1#include "includes.h"
2
3#include "smbwrp.h"
4
5static int
6net_share_enum_rpc(struct cli_state *cli,
7 void (*fn)(const char *name,
8 uint32 type,
9 const char *comment,
10 void *state),
11 void *state)
12{
13 int i;
14 WERROR result;
15 ENUM_HND enum_hnd;
16 uint32 info_level = 1;
17 uint32 preferred_len = 0xffffffff;
18 uint32 type;
19 SRV_SHARE_INFO_CTR ctr;
20 fstring name = "";
21 fstring comment = "";
22 void *mem_ctx;
23 struct rpc_pipe_client *pipe_hnd;
24 NTSTATUS nt_status;
25
26 /* Open the server service pipe */
27 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &nt_status);
28 if (!pipe_hnd) {
29 DEBUG(1, ("net_share_enum_rpc pipe open fail!\n"));
30 return -1;
31 }
32
33 /* Allocate a context for parsing and for the entries in "ctr" */
34 mem_ctx = talloc_init("libsmbclient: net_share_enum_rpc");
35 if (mem_ctx == NULL) {
36 DEBUG(0, ("out of memory for net_share_enum_rpc!\n"));
37 cli_rpc_pipe_close(pipe_hnd);
38 return -1;
39 }
40
41 /* Issue the NetShareEnum RPC call and retrieve the response */
42 init_enum_hnd(&enum_hnd, 0);
43 result = rpccli_srvsvc_net_share_enum(pipe_hnd,
44 mem_ctx,
45 info_level,
46 &ctr,
47 preferred_len,
48 &enum_hnd);
49
50 /* Was it successful? */
51 if (!W_ERROR_IS_OK(result) || ctr.num_entries == 0) {
52 /* Nope. Go clean up. */
53 goto done;
54 }
55
56 /* For each returned entry... */
57 for (i = 0; i < ctr.num_entries; i++) {
58
59 /* pull out the share name */
60 rpcstr_pull_unistr2_fstring(
61 name, &ctr.share.info1[i].info_1_str.uni_netname);
62
63 /* pull out the share's comment */
64 rpcstr_pull_unistr2_fstring(
65 comment, &ctr.share.info1[i].info_1_str.uni_remark);
66
67 /* Get the type value */
68 type = ctr.share.info1[i].info_1.type;
69
70 /* Add this share to the list */
71 (*fn)(name, type, comment, state);
72 }
73
74done:
75 /* Close the server service pipe */
76 cli_rpc_pipe_close(pipe_hnd);
77
78 /* Free all memory which was allocated for this request */
79 TALLOC_FREE(mem_ctx);
80
81 /* Tell 'em if it worked */
82 return W_ERROR_IS_OK(result) ? 0 : -1;
83}
84
85/*
86 * Wrapper for cli_errno to return not connected error on negative fd
87 */
88int os2cli_errno(cli_state * cli)
89{
90 if (cli->fd == -1)
91 {
92 return ENOTCONN;
93 }
94 return cli_errno(cli);
95}
96
97int _System smbwrp_getclisize(void)
98{
99 return sizeof(struct cli_state);
100}
101
102/*****************************************************
103initialise structures
104*******************************************************/
105int _System smbwrp_init(void)
106{
107 static int initialised = 0;
108 char *p;
109 pstring line;
110
111 if (initialised)
112 {
113 return 0;
114 }
115 initialised = 1;
116
117 load_case_tables();
118
119 init_globals( True);
120
121 load_interfaces();
122
123 if (!init_names())
124 {
125 return 1;
126 }
127
128/*
129 if ((p=smbw_getshared("RESOLVE_ORDER"))) {
130 lp_set_name_resolve_order(p);
131 }
132*/
133 return 0;
134
135}
136
137#if 0
138/*****************************************************
139remove redundent stuff from a filename
140*******************************************************/
141void clean_fname(char *name)
142{
143 char *p, *p2;
144 int l;
145 int modified = 1;
146
147 if (!name) return;
148
149 while (modified) {
150 modified = 0;
151
152 if ((p=strstr(name,"/./"))) {
153 modified = 1;
154 while (*p) {
155 p[0] = p[2];
156 p++;
157 }
158 }
159
160 if ((p=strstr(name,"//"))) {
161 modified = 1;
162 while (*p) {
163 p[0] = p[1];
164 p++;
165 }
166 }
167
168 if (strcmp(name,"/../")==0) {
169 modified = 1;
170 name[1] = 0;
171 }
172
173 if ((p=strstr(name,"/../"))) {
174 modified = 1;
175 for (p2=(p>name?p-1:p);p2>name;p2--) {
176 if (p2[0] == '/') break;
177 }
178 while (*p2) {
179 p2[0] = p2[3];
180 p2++;
181 }
182 }
183
184 if (strcmp(name,"/..")==0) {
185 modified = 1;
186 name[1] = 0;
187 }
188
189 l = strlen(name);
190 p = l>=3?(name+l-3):name;
191 if (strcmp(p,"/..")==0) {
192 modified = 1;
193 for (p2=p-1;p2>name;p2--) {
194 if (p2[0] == '/') break;
195 }
196 if (p2==name) {
197 p[0] = '/';
198 p[1] = 0;
199 } else {
200 p2[0] = 0;
201 }
202 }
203
204 l = strlen(name);
205 p = l>=2?(name+l-2):name;
206 if (strcmp(p,"/.")==0) {
207 if (p == name) {
208 p[1] = 0;
209 } else {
210 p[0] = 0;
211 }
212 }
213
214 if (strncmp(p=name,"./",2) == 0) {
215 modified = 1;
216 do {
217 p[0] = p[2];
218 } while (*p++);
219 }
220
221 l = strlen(p=name);
222 if (l > 1 && p[l-1] == '/') {
223 modified = 1;
224 p[l-1] = 0;
225 }
226 }
227}
228#endif
229
230
231/****************************************************************************
232send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
233****************************************************************************/
234BOOL cli_qpathinfo3(struct cli_state *cli, const char *fname,
235 time_t *c_time, time_t *a_time, time_t *m_time,
236 time_t *w_time, off_t *size, uint16 *mode,
237 SMB_INO_T *ino)
238{
239 unsigned int data_len = 0;
240 unsigned int param_len = 0;
241 uint16 setup = TRANSACT2_QPATHINFO;
242 pstring param;
243 char *rparam=NULL, *rdata=NULL;
244 char *p;
245
246 p = param;
247 memset(p, 0, 6);
248 SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);
249 p += 6;
250 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
251
252 param_len = PTR_DIFF(p, param);
253
254 if (!cli_send_trans(cli, SMBtrans2,
255 NULL, /* name */
256 -1, 0, /* fid, flags */
257 &setup, 1, 0, /* setup, length, max */
258 param, param_len, 10, /* param, length, max */
259 NULL, data_len, cli->max_xmit /* data, length, max */
260 )) {
261 return False;
262 }
263
264 if (!cli_receive_trans(cli, SMBtrans2,
265 &rparam, &param_len,
266 &rdata, &data_len)) {
267 return False;
268 }
269
270 if (!rdata || data_len < 22) {
271 return False;
272 }
273
274 if (c_time) {
275 *c_time = convert_timespec_to_time_t(interpret_long_date(rdata+0)) - cli->serverzone;
276 }
277 if (a_time) {
278 *a_time = convert_timespec_to_time_t(interpret_long_date(rdata+8)) - cli->serverzone;
279 }
280 if (m_time) {
281 *m_time = convert_timespec_to_time_t(interpret_long_date(rdata+16)) - cli->serverzone;
282 }
283 if (w_time) {
284 *w_time = convert_timespec_to_time_t(interpret_long_date(rdata+24)) - cli->serverzone;
285 }
286 if (mode) {
287 *mode = SVAL(rdata, 32);
288 }
289 if (size) {
290 *size = IVAL2_TO_SMB_BIG_UINT(rdata, 48);
291 }
292 if (ino) {
293 *ino = IVAL(rdata, 64);
294 }
295
296 SAFE_FREE(rdata);
297 SAFE_FREE(rparam);
298 return True;
299}
300
301/****************************************************************************
302send a qfileinfo call
303****************************************************************************/
304BOOL cli_qfileinfo3(struct cli_state *cli, int fnum,
305 uint16 *mode, off_t *size,
306 time_t *c_time, time_t *a_time, time_t *m_time,
307 time_t *w_time, SMB_INO_T *ino)
308{
309 unsigned int data_len = 0;
310 unsigned int param_len = 0;
311 uint16 setup = TRANSACT2_QFILEINFO;
312 pstring param;
313 char *rparam=NULL, *rdata=NULL;
314
315 /* if its a win95 server then fail this - win95 totally screws it
316 up */
317 if (cli->win95) return False;
318
319 param_len = 4;
320
321 memset(param, 0, param_len);
322 SSVAL(param, 0, fnum);
323 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
324
325 if (!cli_send_trans(cli, SMBtrans2,
326 NULL, /* name */
327 -1, 0, /* fid, flags */
328 &setup, 1, 0, /* setup, length, max */
329 param, param_len, 2, /* param, length, max */
330 NULL, data_len, cli->max_xmit /* data, length, max */
331 )) {
332 return False;
333 }
334
335 if (!cli_receive_trans(cli, SMBtrans2,
336 &rparam, &param_len,
337 &rdata, &data_len)) {
338 return False;
339 }
340
341 if (!rdata || data_len < 68) {
342 return False;
343 }
344
345 if (c_time) {
346 *c_time = convert_timespec_to_time_t(interpret_long_date(rdata+0)) - cli->serverzone;
347 }
348 if (a_time) {
349 *a_time = convert_timespec_to_time_t(interpret_long_date(rdata+8)) - cli->serverzone;
350 }
351 if (m_time) {
352 *m_time = convert_timespec_to_time_t(interpret_long_date(rdata+16)) - cli->serverzone;
353 }
354 if (w_time) {
355 *w_time = convert_timespec_to_time_t(interpret_long_date(rdata+24)) - cli->serverzone;
356 }
357 if (mode) {
358 *mode = SVAL(rdata, 32);
359 }
360 if (size) {
361 *size = IVAL2_TO_SMB_BIG_UINT(rdata, 48);
362 }
363 if (ino) {
364 *ino = IVAL(rdata, 64);
365 }
366
367 SAFE_FREE(rdata);
368 SAFE_FREE(rparam);
369 return True;
370}
371
372/*****************************************************
373return a connection to a server
374*******************************************************/
375int _System smbwrp_connect(smbwrp_server * srv, struct cli_state ** cli, 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 if (p_resume_key) {
1030 *p_resume_key = 0;
1031 }
1032
1033 finfo->attr = def_finfo.mode;
1034 finfo->mtime = def_finfo.mtime_ts.tv_sec;
1035 finfo->atime = def_finfo.atime_ts.tv_sec;
1036 finfo->ctime = def_finfo.ctime_ts.tv_sec;
1037 strncpy(finfo->fname, def_finfo.name, sizeof(finfo->fname) - 1);
1038
1039 switch (level) {
1040 case 1: /* OS/2 understands this */
1041 /* these dates are converted to GMT by
1042 make_unix_date */
1043 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1044 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1045 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1046 finfo->size = IVAL(p,16);
1047 finfo->attr = CVAL(p,24);
1048 len = CVAL(p, 26);
1049 p += 27;
1050 p += clistr_align_in(cli, p, 0);
1051 /* the len+2 below looks strange but it is
1052 important to cope with the differences
1053 between win2000 and win9x for this call
1054 (tridge) */
1055 p += clistr_pull(cli, finfo->fname, p,
1056 sizeof(finfo->fname),
1057 len+2,
1058 STR_TERMINATE);
1059 finfo->easize = -1;
1060 return PTR_DIFF(p, base);
1061
1062 case 2: /* this is what OS/2 uses mostly */
1063 /* these dates are converted to GMT by
1064 make_unix_date */
1065 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1066 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1067 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1068 finfo->size = IVAL(p,16);
1069 finfo->attr = CVAL(p,24);
1070 finfo->easize = IVAL(p,26);
1071 len = CVAL(p, 30);
1072 p += 31;
1073 /* check for unisys! */
1074 p += clistr_pull(cli, finfo->fname, p,
1075 sizeof(finfo->fname),
1076 len,
1077 STR_NOALIGN);
1078 return PTR_DIFF(p, base) + 1;
1079
1080 case 260: /* NT uses this, but also accepts 2 */
1081 {
1082 size_t namelen, slen;
1083 p += 4; /* next entry offset */
1084 if (p_resume_key) {
1085 *p_resume_key = IVAL(p,0);
1086 }
1087
1088 p += 4; /* fileindex */
1089
1090 /* Offset zero is "create time", not "change time". */
1091 p += 8;
1092 finfo->atime = interpret_long_date(p).tv_sec - cli->serverzone;
1093 p += 8;
1094 finfo->mtime = interpret_long_date(p).tv_sec - cli->serverzone;
1095 p += 8;
1096 finfo->ctime = interpret_long_date(p).tv_sec - cli->serverzone;
1097 p += 8;
1098 finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0);
1099 p += 8;
1100 p += 8; /* alloc size */
1101 finfo->attr = CVAL(p,0);
1102 p += 4;
1103 namelen = IVAL(p,0);
1104 p += 4;
1105 finfo->easize = IVAL(p,0);
1106 p += 4; /* EA size */
1107 slen = SVAL(p, 0);
1108 p += 2;
1109#if 0
1110 {
1111 /* stupid NT bugs. grr */
1112 int flags = 0;
1113 if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE;
1114 clistr_pull(cli, finfo->short_name, p,
1115 sizeof(finfo->short_name),
1116 slen, flags);
1117 }
1118#endif
1119 p += 24; /* short name? */
1120 clistr_pull(cli, finfo->fname, p,
1121 sizeof(finfo->fname),
1122 namelen, 0);
1123
1124 /* To be robust in the face of unicode conversion failures
1125 we need to copy the raw bytes of the last name seen here.
1126 Namelen doesn't include the terminating unicode null, so
1127 copy it here. */
1128#if 0
1129 if (p_last_name_raw && p_last_name_raw_len) {
1130 if (namelen + 2 > p_last_name_raw->length) {
1131 memset(p_last_name_raw->data, '\0', sizeof(p_last_name_raw->length));
1132 *p_last_name_raw_len = 0;
1133 } else {
1134 memcpy(p_last_name_raw->data, p, namelen);
1135 SSVAL(p_last_name_raw->data, namelen, 0);
1136 *p_last_name_raw_len = namelen + 2;
1137 }
1138 }
1139#endif
1140 return (size_t)IVAL(base, 0);
1141 }
1142 }
1143
1144 debuglocal(1,"Unknown long filename format %d\n",level);
1145 return (size_t)IVAL(base,0);
1146}
1147
1148/****************************************************************************
1149 Do a directory listing, calling fn on each file found.
1150 Modified from cli_list_new
1151****************************************************************************/
1152
1153static int list_files(struct cli_state *cli, const char *Mask, uint16 attribute,
1154 void (*fn)(const char*, smbwrp_fileinfo *, const char *, void *), void *state)
1155{
1156#if 1
1157 int max_matches = 1366; /* Match W2k - was 512. */
1158#else
1159 int max_matches = 512;
1160#endif
1161 int info_level;
1162 char *p, *p2;
1163 pstring mask;
1164 smbwrp_fileinfo finfo;
1165 int i;
1166 char *dirlist = NULL;
1167 int dirlist_len = 0;
1168 int total_received = -1;
1169 BOOL First = True;
1170 int ff_searchcount=0;
1171 int ff_eos=0;
1172 int ff_dir_handle=0;
1173 int loop_count = 0;
1174 char *rparam=NULL, *rdata=NULL;
1175 unsigned int param_len, data_len;
1176 uint16 setup;
1177 pstring param;
1178 const char *mnt;
1179 uint32 resume_key = 0;
1180 uint32 last_name_raw_len = 0;
1181 DATA_BLOB last_name_raw = data_blob(NULL, 2*sizeof(pstring));
1182
1183 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1184 info_level = (cli->capabilities&CAP_NT_SMBS)?260:2;
1185
1186 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, mask);
1187
1188 /* when getting a directory listing from a 2k dfs root share,
1189 we have to include the full path (\server\share\mask) here */
1190
1191 if ( cli->dfsroot )
1192 pstr_sprintf( mask, "\\%s\\%s\\%s", cli->desthost, cli->share, Mask );
1193 else
1194 pstrcpy(mask,Mask);
1195
1196 while (ff_eos == 0) {
1197 loop_count++;
1198 if (loop_count > 200) {
1199 debuglocal(0,"Error: Looping in FIND_NEXT??\n");
1200 break;
1201 }
1202
1203 if (First) {
1204 setup = TRANSACT2_FINDFIRST;
1205 SSVAL(param,0,attribute); /* attribute */
1206 SSVAL(param,2,max_matches); /* max count */
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 SSVAL(param,4,info_level);
1218 /* For W2K servers serving out FAT filesystems we *must* set the
1219 resume key. If it's not FAT then it's returned as zero. */
1220 SIVAL(param,6,resume_key); /* ff_resume_key */
1221 /* NB. *DON'T* use continue here. If you do it seems that W2K and bretheren
1222 can miss filenames. Use last filename continue instead. JRA */
1223 SSVAL(param,10,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1224 p = param+12;
1225 if (last_name_raw_len && (last_name_raw_len < (sizeof(param)-12))) {
1226 memcpy(p, last_name_raw.data, last_name_raw_len);
1227 p += last_name_raw_len;
1228 } else {
1229 p += clistr_push(cli, param+12, mask, sizeof(param)-12, STR_TERMINATE);
1230 }
1231 }
1232
1233 param_len = PTR_DIFF(p, param);
1234
1235 if (!cli_send_trans(cli, SMBtrans2,
1236 NULL, /* Name */
1237 -1, 0, /* fid, flags */
1238 &setup, 1, 0, /* setup, length, max */
1239 param, param_len, 10, /* param, length, max */
1240 NULL, 0,
1241#if 0
1242 /* w2k value. */
1243 MIN(16384,cli->max_xmit) /* data, length, max. */
1244#else
1245 cli->max_xmit /* data, length, max. */
1246#endif
1247 )) {
1248 break;
1249 }
1250
1251 if (!cli_receive_trans(cli, SMBtrans2,
1252 &rparam, &param_len,
1253 &rdata, &data_len) &&
1254 cli_is_dos_error(cli)) {
1255 /* we need to work around a Win95 bug - sometimes
1256 it gives ERRSRV/ERRerror temprarily */
1257 uint8 eclass;
1258 uint32 ecode;
1259
1260 SAFE_FREE(rdata);
1261 SAFE_FREE(rparam);
1262
1263 cli_dos_error(cli, &eclass, &ecode);
1264
1265 /*
1266 * OS/2 might return "no more files",
1267 * which just tells us, that searchcount is zero
1268 * in this search.
1269 * Guenter Kukkukk <linux@kukkukk.com>
1270 */
1271
1272 if (eclass == ERRDOS && ecode == ERRnofiles) {
1273 ff_searchcount = 0;
1274 cli_reset_error(cli);
1275 break;
1276 }
1277
1278 if (eclass != ERRSRV || ecode != ERRerror)
1279 break;
1280 smb_msleep(100);
1281 continue;
1282 }
1283
1284 if (cli_is_error(cli) || !rdata || !rparam)
1285 {
1286 if (First && info_level == 2)
1287 {
1288 // we have tried query ea size, but now will try without ea size
1289 info_level = 1;
1290 debuglocal(4,"list_files fallback to level %d\n", info_level);
1291 continue;
1292 }
1293 SAFE_FREE(rdata);
1294 SAFE_FREE(rparam);
1295 break;
1296 }
1297
1298 if (total_received == -1)
1299 total_received = 0;
1300
1301 /* parse out some important return info */
1302 p = rparam;
1303 if (First) {
1304 ff_dir_handle = SVAL(p,0);
1305 ff_searchcount = SVAL(p,2);
1306 ff_eos = SVAL(p,4);
1307 } else {
1308 ff_searchcount = SVAL(p,0);
1309 ff_eos = SVAL(p,2);
1310 }
1311 debuglocal(4,"list_files %d %d %d %d\n", ff_searchcount, ff_eos, "(ff_lastname)", First);
1312
1313 if (ff_searchcount == 0) {
1314 SAFE_FREE(rdata);
1315 SAFE_FREE(rparam);
1316 break;
1317 }
1318
1319 /* point to the data bytes */
1320 p = rdata;
1321
1322 memset(&finfo, 0, sizeof(finfo));
1323 finfo.easize = -1;
1324 /* we might need the lastname for continuations */
1325 for (p2=p,i=0;i<ff_searchcount;i++) {
1326 if ((info_level == 260) && (i == ff_searchcount-1)) {
1327 /* Last entry - fixup the last offset length. */
1328 SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2));
1329 }
1330 p2 += _os2_interpret_long_filename(cli,info_level,p2,&finfo,
1331 &resume_key,&last_name_raw,&last_name_raw_len);
1332
1333 if (!First && *mask && strcsequal(finfo.fname, mask)) {
1334 debuglocal(0,"Error: Looping in FIND_NEXT as name %s has already been seen?\n",
1335 finfo.fname);
1336 ff_eos = 1;
1337 break;
1338 }
1339 }
1340
1341 if (ff_searchcount > 0) {
1342 pstrcpy(mask, finfo.fname);
1343 } else {
1344 pstrcpy(mask,"");
1345 }
1346
1347 /* grab the data for later use */
1348 /* and add them to the dirlist pool */
1349 dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len);
1350
1351 if (!dirlist) {
1352 debuglocal(0,"cli_list_new: Failed to expand dirlist\n");
1353 SAFE_FREE(rdata);
1354 SAFE_FREE(rparam);
1355 break;
1356 }
1357
1358 memcpy(dirlist+dirlist_len,p,data_len);
1359 dirlist_len += data_len;
1360
1361 total_received += ff_searchcount;
1362
1363 SAFE_FREE(rdata);
1364 SAFE_FREE(rparam);
1365
1366 debuglocal(3,"received %d entries (eos=%d)\n",
1367 ff_searchcount,ff_eos);
1368
1369 if (ff_searchcount > 0)
1370 loop_count = 0;
1371
1372 First = False;
1373 }
1374
1375 mnt = cli_cm_get_mntpoint( cli );
1376
1377 /* see if the server disconnected or the connection otherwise failed */
1378 if (cli_is_error(cli)) {
1379 total_received = -1;
1380 } else {
1381 /* no connection problem. let user function add each entry */
1382 for (p=dirlist,i=0;i<total_received;i++) {
1383 p += _os2_interpret_long_filename(cli, info_level, p,
1384 &finfo,NULL,NULL,NULL);
1385 fn( mnt,&finfo, Mask, state );
1386 }
1387 }
1388
1389 /* free up the dirlist buffer and last name raw blob */
1390 SAFE_FREE(dirlist);
1391 data_blob_free(&last_name_raw);
1392 return(total_received);
1393}
1394
1395
1396/*****************************************************
1397open a directory on the server
1398*******************************************************/
1399int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1400{
1401 if (!srv || !cli || !state || !*state->mask)
1402 {
1403 return EINVAL;
1404 }
1405 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);
1406 if (*srv->workgroup == 0 && *srv->server_name == 0)
1407 {
1408 smbwrp_special_add(".", state);
1409 smbwrp_special_add("..", state);
1410 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1411 smbwrp_share_add, state);
1412 } else
1413 if (*srv->server_name == 0)
1414 {
1415 smbwrp_special_add(".", state);
1416 smbwrp_special_add("..", state);
1417
1418 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1419 smbwrp_share_add, state);
1420 } else
1421 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1422 {
1423 smbwrp_special_add(".", state);
1424 smbwrp_special_add("..", state);
1425
1426 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1427 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1428 {
1429 return os2cli_errno(cli);
1430 }
1431 } else
1432 if (strncmp(cli->dev,"LPT",3) == 0)
1433 {
1434 smbwrp_special_add(".", state);
1435 smbwrp_special_add("..", state);
1436 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1437 {
1438 return os2cli_errno(cli);
1439 }
1440 }
1441 else
1442 {
1443#if 0
1444 if (strcmp(path,"\\") == 0) {
1445 smbwrp_special_add(".", state);
1446 smbwrp_special_add("..", state);
1447 }
1448#endif
1449#if 0
1450 if (cli_list(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1451 smbwrp_dir_add_old, state) < 0)
1452#else
1453 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1454 smbwrp_dir_add, state) < 0)
1455#endif
1456 {
1457 return os2cli_errno(cli);
1458 }
1459 }
1460
1461 return 0;
1462}
1463
1464/*****************************************************
1465a wrapper for chdir()
1466*******************************************************/
1467int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1468{
1469 unsigned short mode = aDIR;
1470 smbwrp_fileinfo finfo = {0};
1471 if (!cli || !fname)
1472 {
1473 return EINVAL;
1474 }
1475
1476 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1477 if (smbwrp_getattr(srv, cli, &finfo))
1478 {
1479 return os2cli_errno(cli);
1480 }
1481
1482 if (!(finfo.attr & aDIR)) {
1483 return ENOTDIR;
1484 }
1485
1486 return 0;
1487}
1488
1489
1490/*****************************************************
1491a wrapper for mkdir()
1492*******************************************************/
1493int _System smbwrp_mkdir(cli_state * cli, char *fname)
1494{
1495 if (!cli || !fname)
1496 {
1497 return EINVAL;
1498 }
1499
1500 if (!cli_mkdir(cli, fname))
1501 {
1502 return os2cli_errno(cli);
1503 }
1504 return 0;
1505}
1506
1507/*****************************************************
1508a wrapper for rmdir()
1509*******************************************************/
1510int _System smbwrp_rmdir(cli_state * cli, char *fname)
1511{
1512 if (!cli || !fname)
1513 {
1514 return EINVAL;
1515 }
1516
1517 if (!cli_rmdir(cli, fname))
1518 {
1519 return os2cli_errno(cli);
1520 }
1521 return 0;
1522}
1523
1524/*****************************************************
1525set EA for a path
1526*******************************************************/
1527int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1528{
1529 if (!cli || !fname || !name)
1530 {
1531 return EINVAL;
1532 }
1533 if (!cli_set_ea_path(cli, fname, name, value, size))
1534 {
1535 return os2cli_errno(cli);
1536 }
1537 return 0;
1538}
1539
1540/*****************************************************
1541set EA for a file
1542*******************************************************/
1543int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1544{
1545 if (!cli || !file || !name)
1546 {
1547 return EINVAL;
1548 }
1549 if (!cli_set_ea_fnum(cli, file->fd, name, value, size))
1550 {
1551 return os2cli_errno(cli);
1552 }
1553 return 0;
1554}
1555
1556
1557#pragma pack(1)
1558typedef struct _FEA /* fea */
1559{
1560 unsigned char fEA; /* flags */
1561 unsigned char cbName; /* name length not including NULL */
1562 unsigned short cbValue; /* value length */
1563} FEA;
1564
1565typedef struct _FEALIST /* feal */
1566{
1567 unsigned long cbList; /* total bytes of structure including full list */
1568 FEA list[1]; /* variable length FEA structures */
1569} FEALIST;
1570#pragma pack()
1571
1572static int unilistea(cli_state * cli, char *fname, smbwrp_file *file, void * buffer, unsigned long size)
1573{
1574 int fnum, i;
1575 int gotsize = sizeof(unsigned long);
1576 size_t num_eas;
1577 struct ea_struct *ea_list = NULL;
1578 TALLOC_CTX *mem_ctx;
1579 FEA * p;
1580 FEALIST * pfealist;
1581 char * q;
1582
1583 mem_ctx = talloc_init("%d: ealist", _gettid());
1584 pfealist = (FEALIST *)buffer;
1585 pfealist->cbList = 0;
1586
1587 if (file)
1588 {
1589 if (!cli_get_ea_list_fnum(cli, file->fd, mem_ctx, &num_eas, &ea_list))
1590 {
1591 debuglocal(4,"ea_get_fnum list failed - %s\n", cli_errstr(cli));
1592 talloc_destroy(mem_ctx);
1593 return os2cli_errno(cli);
1594 }
1595 }
1596 else
1597 {
1598 if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list))
1599 {
1600 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1601 talloc_destroy(mem_ctx);
1602 return os2cli_errno(cli);
1603 }
1604 }
1605
1606 debuglocal(4,"num_eas = %d\n", num_eas);
1607
1608 // we will count that os/2 max EA size for file is 64kb
1609 p = pfealist->list;
1610 for (i = 0; i < num_eas; i++)
1611 {
1612 int namelen = strlen(ea_list[i].name);
1613 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);
1614 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1615 {
1616 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1617 continue;
1618 }
1619 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1620 if (size >= gotsize)
1621 {
1622 p->fEA = 0;
1623 p->cbName = namelen;
1624 p->cbValue = ea_list[i].value.length;
1625 q = (char *)(p + 1);
1626 strncpy(q, ea_list[i].name, namelen + 1);
1627 q += namelen + 1;
1628 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1629 p = (FEA *)(q + ea_list[i].value.length);
1630 }
1631 }
1632 pfealist->cbList = gotsize;
1633 debuglocal(4,"ret size = %d\n", gotsize);
1634
1635 talloc_destroy(mem_ctx);
1636 return 0;
1637}
1638
1639/*****************************************************
1640lists EA of a path
1641*******************************************************/
1642int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1643{
1644 if (!cli || !fname || !buffer)
1645 {
1646 return EINVAL;
1647 }
1648
1649 debuglocal(4,"EALIst for <%s>\n", fname);
1650 return unilistea(cli, fname, NULL, buffer, size);
1651}
1652
1653/*****************************************************
1654lists EA of a file
1655*******************************************************/
1656int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1657{
1658 if (!cli || !file || !buffer)
1659 {
1660 return EINVAL;
1661 }
1662
1663 debuglocal(4,"FEALIst for <%s>/%d\n", file->fname, file->fd);
1664 return unilistea(cli, NULL, file, buffer, size);
1665}
1666
1667/****************************************************************************
1668Check the space on a device.
1669****************************************************************************/
1670int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1671{
1672 int total, bsize, avail;
1673
1674 if (!cli || !pfsa)
1675 {
1676 return EINVAL;
1677 }
1678
1679 if (!cli_dskattr(cli, &bsize, &total, &avail))
1680 {
1681 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1682 return os2cli_errno(cli);
1683 }
1684
1685 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1686 total, bsize, avail);
1687
1688 // YD currently Samba return it in MB!
1689 pfsa->cSectorUnit = 1;
1690 if (bsize > 65536)
1691 {
1692 pfsa->cUnit = total*1024;
1693 pfsa->cUnitAvail = avail*1024;
1694 pfsa->cbSector = bsize/1024;
1695 }
1696 else
1697 {
1698 pfsa->cUnit = total;
1699 pfsa->cUnitAvail = avail;
1700 pfsa->cbSector = bsize;
1701 }
1702
1703 return 0;
1704}
Note: See TracBrowser for help on using the repository browser.