source: branches/client-1.5/src/smbwrp.c@ 147

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

Map errno smb errors to OS/2 error codes. Minor build system rework.

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