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

Last change on this file since 127 was 126, checked in by Yuri Dario, 17 years ago

Fixes timezone handling for os2->xp->os2, os2->samba->os2. Partially fixes ticket:56.

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