source: branches/client-2.0/src/smbwrp.c@ 578

Last change on this file since 578 was 547, checked in by Silvan Scherrer, 15 years ago

Samba Client 2.0: reconnect fix and text updates

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