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

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

Added proper license informations, .def cleaning.

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