source: trunk/client/src/smbwrp.c@ 645

Last change on this file since 645 was 645, checked in by Silvan Scherrer, 14 years ago

Samba Client 2.2: some small adjustments and building with bin mode on

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