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

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

Merged daemon code, now the plugin calls directly samba client library (still using smbrp code).

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