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

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

Add code missing from _os2_interpret_long_filenames - addresses Ticket #48

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