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

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

Samba Client 2.1: interim commit

  • Property svn:eol-style set to native
File size: 49.2 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 finfo->atime = 0;
1117 finfo->ctime = 0;
1118 finfo->mtime = 0;
1119 *finfo->fname = '\0';
1120
1121 switch (level) {
1122 case 1: /* OS/2 understands this */
1123 /* these dates are converted to GMT by
1124 make_unix_date */
1125 if (pdata_end - base < 27) {
1126 return pdata_end - base;
1127 }
1128 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1129 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1130 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1131 finfo->size = IVAL(p,16);
1132 finfo->attr = CVAL(p,24);
1133 len = CVAL(p, 26);
1134 p += 27;
1135 p += clistr_align_in(cli, p, 0);
1136
1137 /* We can safely use len here (which is required by OS/2)
1138 * and the NAS-BASIC server instead of +2 or +1 as the
1139 * STR_TERMINATE flag below is
1140 * actually used as the length calculation.
1141 * The len is merely an upper bound.
1142 * Due to the explicit 2 byte null termination
1143 * in cli_receive_trans/cli_receive_nt_trans
1144 * we know this is safe. JRA + kukks
1145 */
1146
1147 if (p + len > pdata_end) {
1148 return pdata_end - base;
1149 }
1150
1151 /* the len+2 below looks strange but it is
1152 important to cope with the differences
1153 between win2000 and win9x for this call
1154 (tridge) */
1155 ret = clistr_pull_talloc(ctx, cli, &fname, p,
1156 len+2,
1157 STR_TERMINATE);
1158 if (ret == (size_t)-1) {
1159 return pdata_end - base;
1160 }
1161 p += ret;
1162 finfo->easize = -1;
1163 strncat(finfo->fname, fname, sizeof(finfo->fname) -1);
1164 return PTR_DIFF(p, base);
1165
1166 case 2: /* this is what OS/2 uses mostly */
1167 /* these dates are converted to GMT by
1168 make_unix_date */
1169 if (pdata_end - base < 31) {
1170 return pdata_end - base;
1171 }
1172 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1173 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1174 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1175 finfo->size = IVAL(p,16);
1176 finfo->attr = CVAL(p,24);
1177 finfo->easize = IVAL(p,26);
1178 len = CVAL(p, 30);
1179 p += 31;
1180 /* check for unisys! */
1181 if (p + len + 1 > pdata_end) {
1182 return pdata_end - base;
1183 }
1184 ret = clistr_pull_talloc(ctx, cli, &fname, p,
1185 len,
1186 STR_NOALIGN);
1187 if (ret == (size_t)-1) {
1188 return pdata_end - base;
1189 }
1190 p += ret;
1191 strncat(finfo->fname, fname, sizeof(finfo->fname) -1);
1192 return PTR_DIFF(p, base) + 1;
1193
1194 case 260: /* NT uses this, but also accepts 2 */
1195 {
1196 size_t namelen, slen;
1197
1198 if (pdata_end - base < 94) {
1199 return pdata_end - base;
1200 }
1201
1202 p += 4; /* next entry offset */
1203
1204 if (p_resume_key) {
1205 *p_resume_key = IVAL(p,0);
1206 }
1207
1208 p += 4; /* fileindex */
1209
1210 /* Offset zero is "create time", not "change time". */
1211 p += 8;
1212 finfo->atime = interpret_long_date(p).tv_sec;
1213 p += 8;
1214 finfo->mtime = interpret_long_date(p).tv_sec;
1215 p += 8;
1216 finfo->ctime = interpret_long_date(p).tv_sec;
1217 p += 8;
1218 finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0);
1219 p += 8;
1220 p += 8; /* alloc size */
1221 finfo->attr = CVAL(p,0);
1222 p += 4;
1223 namelen = IVAL(p,0);
1224 p += 4;
1225 finfo->easize = IVAL(p,0);
1226 p += 4; /* EA size */
1227 slen = SVAL(p, 0);
1228 if (slen > 24) {
1229 /* Bad short name length. */
1230 return pdata_end - base;
1231 }
1232 p += 2;
1233#if 0
1234 {
1235 /* stupid NT bugs. grr */
1236 int flags = 0;
1237 if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE;
1238 clistr_pull(cli, finfo->short_name, p,
1239 sizeof(finfo->short_name),
1240 slen, flags);
1241 }
1242#endif
1243 p += 24; /* short name? */
1244 if (p + namelen < p || p + namelen > pdata_end) {
1245 return pdata_end - base;
1246 }
1247 ret = clistr_pull_talloc(ctx, cli, &fname, p,
1248 namelen, 0);
1249 if (ret == (size_t)-1) {
1250 return pdata_end - base;
1251 }
1252 strncat(finfo->fname, fname, sizeof(finfo->fname) -1);
1253
1254 /* To be robust in the face of unicode conversion failures
1255 we need to copy the raw bytes of the last name seen here.
1256 Namelen doesn't include the terminating unicode null, so
1257 copy it here. */
1258#if 0
1259 if (p_last_name_raw) {
1260 *p_last_name_raw = data_blob(NULL, namelen+2);
1261 memcpy(p_last_name_raw->data, p, namelen);
1262 SSVAL(p_last_name_raw->data, namelen, 0);
1263 }
1264#endif
1265 return calc_next_entry_offset(base, pdata_end);
1266 }
1267 }
1268
1269 debuglocal(1,"Unknown long filename format %d\n",level);
1270 return calc_next_entry_offset(base, pdata_end);
1271}
1272
1273/****************************************************************************
1274 Do a directory listing, calling fn on each file found.
1275 Modified from cli_list_new
1276****************************************************************************/
1277
1278static int list_files(struct cli_state *cli, const char *Mask, uint16 attribute,
1279 void (*fn)(const char*, smbwrp_fileinfo *, const char *, void *), void *state)
1280{
1281#if 1
1282 int max_matches = 1366; /* Match W2k - was 512. */
1283#else
1284 int max_matches = 512;
1285#endif
1286 int info_level;
1287 char *p, *p2, *rdata_end;
1288 char *mask=NULL;
1289 smbwrp_fileinfo finfo;
1290 int i;
1291 char *dirlist = NULL;
1292 int dirlist_len = 0;
1293 int total_received = -1;
1294 bool First = True;
1295 int ff_searchcount=0;
1296 int ff_eos=0;
1297 int ff_dir_handle=0;
1298 int loop_count = 0;
1299 char *rparam=NULL, *rdata=NULL;
1300 unsigned int param_len, data_len;
1301 uint16 setup;
1302 char *param;
1303 const char *mnt;
1304 uint32 resume_key = 0;
1305 TALLOC_CTX *frame = talloc_stackframe();
1306 DATA_BLOB last_name_raw = data_blob(NULL, 0);
1307
1308 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1309 info_level = (cli->capabilities&CAP_NT_SMBS)?260:2;
1310
1311 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, Mask);
1312
1313 mask = SMB_STRDUP(Mask);
1314 if (!mask) {
1315 TALLOC_FREE(frame);
1316 return -1;
1317 }
1318
1319 /* Try to get the listing from cache. */
1320 if (dircache_list_files(fn, state, &total_received))
1321 {
1322 /* Got from cache. */
1323 return(total_received);
1324 }
1325
1326 while (ff_eos == 0) {
1327 size_t nlen = 2*(strlen(mask)+1);
1328
1329 loop_count++;
1330 if (loop_count > 200) {
1331 debuglocal(0,"Error: Looping in FIND_NEXT??\n");
1332 break;
1333 }
1334
1335 param = SMB_MALLOC_ARRAY(char, 12+nlen+last_name_raw.length+2);
1336 if (!param) {
1337 break;
1338 }
1339
1340 if (First) {
1341 setup = TRANSACT2_FINDFIRST;
1342 SSVAL(param,0,attribute); /* attribute */
1343 SSVAL(param,2,max_matches); /* max count */
1344 SSVAL(param,4,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1345 SSVAL(param,6,info_level);
1346 SIVAL(param,8,0);
1347 p = param+12;
1348 p += clistr_push(cli, param+12, mask, nlen,
1349 STR_TERMINATE);
1350 } else {
1351 setup = TRANSACT2_FINDNEXT;
1352 SSVAL(param,0,ff_dir_handle);
1353 SSVAL(param,2,max_matches); /* max count */
1354 SSVAL(param,4,info_level);
1355 /* For W2K servers serving out FAT filesystems we *must* set the
1356 resume key. If it's not FAT then it's returned as zero. */
1357 SIVAL(param,6,resume_key); /* ff_resume_key */
1358 /* NB. *DON'T* use continue here. If you do it seems that W2K and bretheren
1359 can miss filenames. Use last filename continue instead. JRA */
1360 SSVAL(param,10,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1361 p = param+12;
1362 if (last_name_raw.length) {
1363 memcpy(p, last_name_raw.data, last_name_raw.length);
1364 p += last_name_raw.length;
1365 } else {
1366 p += clistr_push(cli, param+12, mask, nlen, STR_TERMINATE);
1367 }
1368 }
1369
1370 param_len = PTR_DIFF(p, param);
1371
1372 if (!cli_send_trans(cli, SMBtrans2,
1373 NULL, /* Name */
1374 -1, 0, /* fid, flags */
1375 &setup, 1, 0, /* setup, length, max */
1376 param, param_len, 10, /* param, length, max */
1377 NULL, 0,
1378#if 0
1379 /* w2k value. */
1380 MIN(16384,cli->max_xmit) /* data, length, max. */
1381#else
1382 cli->max_xmit /* data, length, max. */
1383#endif
1384 )) {
1385 SAFE_FREE(param);
1386 TALLOC_FREE(frame);
1387 break;
1388 }
1389
1390 SAFE_FREE(param);
1391
1392 if (!cli_receive_trans(cli, SMBtrans2,
1393 &rparam, &param_len,
1394 &rdata, &data_len) &&
1395 cli_is_dos_error(cli)) {
1396 /* we need to work around a Win95 bug - sometimes
1397 it gives ERRSRV/ERRerror temprarily */
1398 uint8 eclass;
1399 uint32 ecode;
1400
1401 SAFE_FREE(rdata);
1402 SAFE_FREE(rparam);
1403
1404 cli_dos_error(cli, &eclass, &ecode);
1405
1406 /*
1407 * OS/2 might return "no more files",
1408 * which just tells us, that searchcount is zero
1409 * in this search.
1410 * Guenter Kukkukk <linux@kukkukk.com>
1411 */
1412
1413 if (eclass == ERRDOS && ecode == ERRnofiles) {
1414 ff_searchcount = 0;
1415 cli_reset_error(cli);
1416 break;
1417 }
1418
1419 if (eclass != ERRSRV || ecode != ERRerror)
1420 break;
1421 smb_msleep(100);
1422 continue;
1423 }
1424
1425 if (cli_is_error(cli) || !rdata || !rparam)
1426 {
1427 if (First && info_level == 2)
1428 {
1429 // we have tried query ea size, but now will try without ea size
1430 info_level = 1;
1431 debuglocal(4,"list_files fallback to level %d\n", info_level);
1432 continue;
1433 }
1434 SAFE_FREE(rdata);
1435 SAFE_FREE(rparam);
1436 break;
1437 }
1438
1439 if (total_received == -1)
1440 total_received = 0;
1441
1442 /* parse out some important return info */
1443 p = rparam;
1444 if (First) {
1445 ff_dir_handle = SVAL(p,0);
1446 ff_searchcount = SVAL(p,2);
1447 ff_eos = SVAL(p,4);
1448 } else {
1449 ff_searchcount = SVAL(p,0);
1450 ff_eos = SVAL(p,2);
1451 }
1452 debuglocal(4,"list_files %d %d %d %d\n", ff_searchcount, ff_eos, "(ff_lastname)", First);
1453
1454 if (ff_searchcount == 0) {
1455 SAFE_FREE(rdata);
1456 SAFE_FREE(rparam);
1457 break;
1458 }
1459
1460 /* point to the data bytes */
1461 p = rdata;
1462 rdata_end = rdata + data_len;
1463
1464 memset(&finfo, 0, sizeof(finfo));
1465 finfo.easize = -1;
1466 /* we might need the lastname for continuations */
1467 for (p2=p,i=0;i<ff_searchcount && p2 < rdata_end;i++) {
1468 if ((info_level == 260) && (i == ff_searchcount-1)) {
1469 /* Last entry - fixup the last offset length. */
1470 SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2));
1471 }
1472 p2 += _os2_interpret_long_filename(frame, cli, info_level, p2, rdata_end, &finfo,
1473 &resume_key, &last_name_raw);
1474
1475 if (!finfo.fname) {
1476 debuglocal(0,"Error: unable to parse name from info level %d\n",
1477 info_level);
1478 ff_eos = 1;
1479 break;
1480 }
1481
1482 if (!First && *mask && strcsequal(finfo.fname, mask)) {
1483 debuglocal(0,"Error: Looping in FIND_NEXT as name %s has already been seen?\n",
1484 finfo.fname);
1485 ff_eos = 1;
1486 break;
1487 }
1488 }
1489
1490 SAFE_FREE(mask);
1491 if (ff_searchcount > 0) {
1492 mask = SMB_STRDUP(finfo.fname);
1493 } else {
1494 mask = SMB_STRDUP("");
1495 }
1496 if (!mask) {
1497 SAFE_FREE(rdata);
1498 SAFE_FREE(rparam);
1499 break;
1500 }
1501
1502 /* grab the data for later use */
1503 /* and add them to the dirlist pool */
1504 dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len);
1505
1506 if (!dirlist) {
1507 debuglocal(0,"cli_list_new: Failed to expand dirlist\n");
1508 SAFE_FREE(rdata);
1509 SAFE_FREE(rparam);
1510 break;
1511 }
1512
1513 memcpy(dirlist+dirlist_len,p,data_len);
1514 dirlist_len += data_len;
1515
1516 total_received += ff_searchcount;
1517
1518 SAFE_FREE(rdata);
1519 SAFE_FREE(rparam);
1520
1521 debuglocal(3,"received %d entries (eos=%d)\n",
1522 ff_searchcount,ff_eos);
1523
1524 if (ff_searchcount > 0)
1525 loop_count = 0;
1526
1527 First = False;
1528 }
1529
1530 mnt = cli_cm_get_mntpoint( cli );
1531
1532 /* see if the server disconnected or the connection otherwise failed */
1533 if (cli_is_error(cli)) {
1534 total_received = -1;
1535 } else {
1536 void *dircachectx = dircache_write_begin(state, total_received);
1537
1538 /* no connection problem. let user function add each entry */
1539 rdata_end = dirlist + dirlist_len;
1540 for (p=dirlist,i=0;i<total_received;i++) {
1541 p += _os2_interpret_long_filename(frame, cli, info_level, p, rdata_end,
1542 &finfo,NULL,NULL);
1543
1544 if (!finfo.fname) {
1545 debuglocal(0,"list_new: unable to parse name from info level %d\n",
1546 info_level);
1547 break;
1548 }
1549 fn( mnt,&finfo, Mask, state );
1550
1551 /* Also add the entry to the cache. */
1552 dircache_write_entry(dircachectx, &finfo);
1553 }
1554
1555 dircache_write_end(dircachectx);
1556
1557 }
1558
1559 /* free up the dirlist buffer and last name raw blob */
1560 SAFE_FREE(dirlist);
1561 data_blob_free(&last_name_raw);
1562 SAFE_FREE(mask);
1563 TALLOC_FREE(frame);
1564 return(total_received);
1565}
1566
1567
1568/*****************************************************
1569open a directory on the server
1570*******************************************************/
1571int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1572{
1573 if (!srv || !cli || !state || !*state->mask)
1574 {
1575 return maperror(EINVAL);
1576 }
1577 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);
1578 if (*srv->workgroup == 0 && *srv->server_name == 0)
1579 {
1580 smbwrp_special_add(".", state);
1581 smbwrp_special_add("..", state);
1582 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1583 smbwrp_share_add, state);
1584 } else
1585 if (*srv->server_name == 0)
1586 {
1587 smbwrp_special_add(".", state);
1588 smbwrp_special_add("..", state);
1589
1590 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1591 smbwrp_share_add, state);
1592 } else
1593 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1594 {
1595 smbwrp_special_add(".", state);
1596 smbwrp_special_add("..", state);
1597
1598 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1599 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1600 {
1601 return os2cli_errno(cli);
1602 }
1603 } else
1604 if (strncmp(cli->dev,"LPT",3) == 0)
1605 {
1606 smbwrp_special_add(".", state);
1607 smbwrp_special_add("..", state);
1608 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1609 {
1610 return os2cli_errno(cli);
1611 }
1612 }
1613 else
1614 {
1615#if 0
1616 if (strcmp(path,"\\") == 0) {
1617 smbwrp_special_add(".", state);
1618 smbwrp_special_add("..", state);
1619 }
1620#endif
1621#if 0
1622 if (cli_list(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1623 smbwrp_dir_add_old, state) < 0)
1624#else
1625 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1626 smbwrp_dir_add, state) < 0)
1627#endif
1628 {
1629 return os2cli_errno(cli);
1630 }
1631 }
1632
1633 return 0;
1634}
1635
1636/*****************************************************
1637a wrapper for chdir()
1638*******************************************************/
1639int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1640{
1641 unsigned short mode = aDIR;
1642 smbwrp_fileinfo finfo = {0};
1643 if (!cli || !fname)
1644 {
1645 return maperror(EINVAL);
1646 }
1647
1648 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1649 if (smbwrp_getattr(srv, cli, &finfo))
1650 {
1651 return os2cli_errno(cli);
1652 }
1653
1654 if (!(finfo.attr & aDIR)) {
1655 return maperror(ENOTDIR);
1656 }
1657
1658 return 0;
1659}
1660
1661
1662/*****************************************************
1663a wrapper for mkdir()
1664*******************************************************/
1665int _System smbwrp_mkdir(cli_state * cli, char *fname)
1666{
1667 if (!cli || !fname)
1668 {
1669 return maperror(EINVAL);
1670 }
1671
1672 if (!cli_mkdir(cli, fname))
1673 {
1674 return os2cli_errno(cli);
1675 }
1676 return 0;
1677}
1678
1679/*****************************************************
1680a wrapper for rmdir()
1681*******************************************************/
1682int _System smbwrp_rmdir(cli_state * cli, char *fname)
1683{
1684 if (!cli || !fname)
1685 {
1686 return maperror(EINVAL);
1687 }
1688
1689 if (!cli_rmdir(cli, fname))
1690 {
1691 return os2cli_errno(cli);
1692 }
1693 return 0;
1694}
1695
1696/*****************************************************
1697set EA for a path
1698*******************************************************/
1699int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1700{
1701 if (!cli || !fname || !name)
1702 {
1703 return maperror(EINVAL);
1704 }
1705 if (!cli_set_ea_path(cli, fname, name, value, size))
1706 {
1707 return os2cli_errno(cli);
1708 }
1709 return 0;
1710}
1711
1712/*****************************************************
1713set EA for a file
1714*******************************************************/
1715int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1716{
1717 if (!cli || !file || !name)
1718 {
1719 return maperror(EINVAL);
1720 }
1721 if (!cli_set_ea_fnum(cli, file->fd, name, value, size))
1722 {
1723 return os2cli_errno(cli);
1724 }
1725 return 0;
1726}
1727
1728
1729#pragma pack(1)
1730typedef struct _FEA /* fea */
1731{
1732 unsigned char fEA; /* flags */
1733 unsigned char cbName; /* name length not including NULL */
1734 unsigned short cbValue; /* value length */
1735} FEA;
1736
1737typedef struct _FEALIST /* feal */
1738{
1739 unsigned long cbList; /* total bytes of structure including full list */
1740 FEA list[1]; /* variable length FEA structures */
1741} FEALIST;
1742#pragma pack()
1743
1744static int unilistea(cli_state * cli, char *fname, smbwrp_file *file, void * buffer, unsigned long size)
1745{
1746 int fnum, i;
1747 int gotsize = sizeof(unsigned long);
1748 size_t num_eas;
1749 struct ea_struct *ea_list = NULL;
1750 TALLOC_CTX *mem_ctx;
1751 FEA * p;
1752 FEALIST * pfealist;
1753 char * q;
1754
1755 mem_ctx = talloc_init("%d: ealist", _gettid());
1756 pfealist = (FEALIST *)buffer;
1757 pfealist->cbList = 0;
1758
1759 if (file)
1760 {
1761 if (!cli_get_ea_list_fnum(cli, file->fd, mem_ctx, &num_eas, &ea_list))
1762 {
1763 debuglocal(4,"ea_get_fnum list failed - %s\n", cli_errstr(cli));
1764 talloc_destroy(mem_ctx);
1765 return os2cli_errno(cli);
1766 }
1767 }
1768 else
1769 {
1770 if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list))
1771 {
1772 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1773 talloc_destroy(mem_ctx);
1774 return os2cli_errno(cli);
1775 }
1776 }
1777
1778 debuglocal(4,"num_eas = %d\n", num_eas);
1779
1780 // we will count that os/2 max EA size for file is 64kb
1781 p = pfealist->list;
1782 for (i = 0; i < num_eas; i++)
1783 {
1784 int namelen = strlen(ea_list[i].name);
1785 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);
1786 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1787 {
1788 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1789 continue;
1790 }
1791 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1792 if (size >= gotsize)
1793 {
1794 p->fEA = 0;
1795 p->cbName = namelen;
1796 p->cbValue = ea_list[i].value.length;
1797 q = (char *)(p + 1);
1798 strncpy(q, ea_list[i].name, namelen + 1);
1799 q += namelen + 1;
1800 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1801 p = (FEA *)(q + ea_list[i].value.length);
1802 }
1803 }
1804 pfealist->cbList = gotsize;
1805 debuglocal(4,"ret size = %d\n", gotsize);
1806
1807 talloc_destroy(mem_ctx);
1808 return 0;
1809}
1810
1811/*****************************************************
1812lists EA of a path
1813*******************************************************/
1814int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1815{
1816 if (!cli || !fname || !buffer)
1817 {
1818 return maperror(EINVAL);
1819 }
1820
1821 debuglocal(4,"EALIst for <%s>\n", fname);
1822 return unilistea(cli, fname, NULL, buffer, size);
1823}
1824
1825/*****************************************************
1826lists EA of a file
1827*******************************************************/
1828int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1829{
1830 if (!cli || !file || !buffer)
1831 {
1832 return maperror(EINVAL);
1833 }
1834
1835 debuglocal(4,"FEALIst for <%s>/%d\n", file->fname, file->fd);
1836 return unilistea(cli, NULL, file, buffer, size);
1837}
1838
1839/****************************************************************************
1840Check the space on a device.
1841****************************************************************************/
1842int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1843{
1844 int total, bsize, avail;
1845
1846 if (!cli || !pfsa)
1847 {
1848 return maperror(EINVAL);
1849 }
1850
1851 if (!cli_dskattr(cli, &bsize, &total, &avail))
1852 {
1853 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1854 return os2cli_errno(cli);
1855 }
1856
1857 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1858 total, bsize, avail);
1859
1860 // YD currently Samba return it in MB!
1861 pfsa->cSectorUnit = 1;
1862 if (bsize >= 65536)
1863 {
1864 pfsa->cUnit = total*1024;
1865 pfsa->cUnitAvail = avail*1024;
1866 pfsa->cbSector = bsize/1024;
1867 }
1868 else
1869 {
1870 pfsa->cUnit = total;
1871 pfsa->cUnitAvail = avail;
1872 pfsa->cbSector = bsize;
1873 }
1874
1875 return 0;
1876}
1877
Note: See TracBrowser for help on using the repository browser.