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

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

Samba Client 2.1: more errno fixes

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