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

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

Samba Client 2.1: sigpipe crash, cosmetic and text

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