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

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

Samba Client 2.1: degug changes, attemp to fix the trap

  • Property svn:eol-style set to native
File size: 49.4 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 debuglocal(9, "fname %s (remove me 1)\n", finfo.fname);
1476 if (!finfo.fname) {
1477 debuglocal(0,"Error: unable to parse name from info level %d\n",
1478 info_level);
1479 ff_eos = 1;
1480 break;
1481 }
1482
1483 if (!First && *mask && strcsequal(finfo.fname, mask)) {
1484 debuglocal(0,"Error: Looping in FIND_NEXT as name %s has already been seen?\n",
1485 finfo.fname);
1486 ff_eos = 1;
1487 break;
1488 }
1489 }
1490
1491 SAFE_FREE(mask);
1492 if (ff_searchcount > 0) {
1493 mask = SMB_STRDUP(finfo.fname);
1494 } else {
1495 mask = SMB_STRDUP("");
1496 }
1497 if (!mask) {
1498 SAFE_FREE(rdata);
1499 SAFE_FREE(rparam);
1500 break;
1501 }
1502
1503 /* grab the data for later use */
1504 /* and add them to the dirlist pool */
1505 dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len);
1506
1507 if (!dirlist) {
1508 debuglocal(0,"cli_list_new: Failed to expand dirlist\n");
1509 SAFE_FREE(rdata);
1510 SAFE_FREE(rparam);
1511 break;
1512 }
1513
1514 memcpy(dirlist+dirlist_len,p,data_len);
1515 dirlist_len += data_len;
1516
1517 total_received += ff_searchcount;
1518
1519 SAFE_FREE(rdata);
1520 SAFE_FREE(rparam);
1521
1522 debuglocal(3,"received %d entries (eos=%d)\n",
1523 ff_searchcount,ff_eos);
1524
1525 if (ff_searchcount > 0)
1526 loop_count = 0;
1527
1528 First = False;
1529 }
1530
1531 mnt = cli_cm_get_mntpoint( cli );
1532
1533 /* see if the server disconnected or the connection otherwise failed */
1534 if (cli_is_error(cli)) {
1535 total_received = -1;
1536 } else {
1537 void *dircachectx = dircache_write_begin(state, total_received);
1538
1539 /* no connection problem. let user function add each entry */
1540 rdata_end = dirlist + dirlist_len;
1541 for (p=dirlist,i=0;i<total_received;i++) {
1542 p += _os2_interpret_long_filename(frame, cli, info_level, p, rdata_end,
1543 &finfo,NULL,NULL);
1544 debuglocal(9, "fname %s (remove me 2)\n", finfo.fname);
1545 if (!finfo.fname) {
1546 debuglocal(0,"list_new: unable to parse name from info level %d\n",
1547 info_level);
1548 break;
1549 }
1550 fn( mnt,&finfo, Mask, state );
1551
1552 /* Also add the entry to the cache. */
1553 dircache_write_entry(dircachectx, &finfo);
1554 }
1555
1556 dircache_write_end(dircachectx);
1557
1558 }
1559
1560 /* free up the dirlist buffer and last name raw blob */
1561 SAFE_FREE(dirlist);
1562 data_blob_free(&last_name_raw);
1563 SAFE_FREE(mask);
1564 TALLOC_FREE(frame);
1565 return(total_received);
1566}
1567
1568
1569/*****************************************************
1570open a directory on the server
1571*******************************************************/
1572int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1573{
1574 if (!srv || !cli || !state || !*state->mask)
1575 {
1576 return maperror(EINVAL);
1577 }
1578 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);
1579 if (*srv->workgroup == 0 && *srv->server_name == 0)
1580 {
1581 smbwrp_special_add(".", state);
1582 smbwrp_special_add("..", state);
1583 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1584 smbwrp_share_add, state);
1585 } else
1586 if (*srv->server_name == 0)
1587 {
1588 smbwrp_special_add(".", state);
1589 smbwrp_special_add("..", state);
1590
1591 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1592 smbwrp_share_add, state);
1593 } else
1594 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1595 {
1596 smbwrp_special_add(".", state);
1597 smbwrp_special_add("..", state);
1598
1599 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1600 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1601 {
1602 return os2cli_errno(cli);
1603 }
1604 } else
1605 if (strncmp(cli->dev,"LPT",3) == 0)
1606 {
1607 smbwrp_special_add(".", state);
1608 smbwrp_special_add("..", state);
1609 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1610 {
1611 return os2cli_errno(cli);
1612 }
1613 }
1614 else
1615 {
1616#if 0
1617 if (strcmp(path,"\\") == 0) {
1618 smbwrp_special_add(".", state);
1619 smbwrp_special_add("..", state);
1620 }
1621#endif
1622#if 0
1623 if (cli_list(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1624 smbwrp_dir_add_old, state) < 0)
1625#else
1626 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1627 smbwrp_dir_add, state) < 0)
1628#endif
1629 {
1630 return os2cli_errno(cli);
1631 }
1632 }
1633
1634 return 0;
1635}
1636
1637/*****************************************************
1638a wrapper for chdir()
1639*******************************************************/
1640int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1641{
1642 unsigned short mode = aDIR;
1643 smbwrp_fileinfo finfo = {0};
1644 if (!cli || !fname)
1645 {
1646 return maperror(EINVAL);
1647 }
1648
1649 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1650 if (smbwrp_getattr(srv, cli, &finfo))
1651 {
1652 return os2cli_errno(cli);
1653 }
1654
1655 if (!(finfo.attr & aDIR)) {
1656 return maperror(ENOTDIR);
1657 }
1658
1659 return 0;
1660}
1661
1662
1663/*****************************************************
1664a wrapper for mkdir()
1665*******************************************************/
1666int _System smbwrp_mkdir(cli_state * cli, char *fname)
1667{
1668 if (!cli || !fname)
1669 {
1670 return maperror(EINVAL);
1671 }
1672
1673 if (!cli_mkdir(cli, fname))
1674 {
1675 return os2cli_errno(cli);
1676 }
1677 return 0;
1678}
1679
1680/*****************************************************
1681a wrapper for rmdir()
1682*******************************************************/
1683int _System smbwrp_rmdir(cli_state * cli, char *fname)
1684{
1685 if (!cli || !fname)
1686 {
1687 return maperror(EINVAL);
1688 }
1689
1690 if (!cli_rmdir(cli, fname))
1691 {
1692 return os2cli_errno(cli);
1693 }
1694 return 0;
1695}
1696
1697/*****************************************************
1698set EA for a path
1699*******************************************************/
1700int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1701{
1702 if (!cli || !fname || !name)
1703 {
1704 return maperror(EINVAL);
1705 }
1706 if (!cli_set_ea_path(cli, fname, name, value, size))
1707 {
1708 return os2cli_errno(cli);
1709 }
1710 return 0;
1711}
1712
1713/*****************************************************
1714set EA for a file
1715*******************************************************/
1716int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1717{
1718 if (!cli || !file || !name)
1719 {
1720 return maperror(EINVAL);
1721 }
1722 if (!cli_set_ea_fnum(cli, file->fd, name, value, size))
1723 {
1724 return os2cli_errno(cli);
1725 }
1726 return 0;
1727}
1728
1729
1730#pragma pack(1)
1731typedef struct _FEA /* fea */
1732{
1733 unsigned char fEA; /* flags */
1734 unsigned char cbName; /* name length not including NULL */
1735 unsigned short cbValue; /* value length */
1736} FEA;
1737
1738typedef struct _FEALIST /* feal */
1739{
1740 unsigned long cbList; /* total bytes of structure including full list */
1741 FEA list[1]; /* variable length FEA structures */
1742} FEALIST;
1743#pragma pack()
1744
1745static int unilistea(cli_state * cli, char *fname, smbwrp_file *file, void * buffer, unsigned long size)
1746{
1747 int fnum, i;
1748 int gotsize = sizeof(unsigned long);
1749 size_t num_eas;
1750 struct ea_struct *ea_list = NULL;
1751 TALLOC_CTX *mem_ctx;
1752 FEA * p;
1753 FEALIST * pfealist;
1754 char * q;
1755
1756 mem_ctx = talloc_init("%d: ealist", _gettid());
1757 pfealist = (FEALIST *)buffer;
1758 pfealist->cbList = 0;
1759
1760 if (file)
1761 {
1762 if (!cli_get_ea_list_fnum(cli, file->fd, mem_ctx, &num_eas, &ea_list))
1763 {
1764 debuglocal(4,"ea_get_fnum list failed - %s\n", cli_errstr(cli));
1765 talloc_destroy(mem_ctx);
1766 return os2cli_errno(cli);
1767 }
1768 }
1769 else
1770 {
1771 if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list))
1772 {
1773 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1774 talloc_destroy(mem_ctx);
1775 return os2cli_errno(cli);
1776 }
1777 }
1778
1779 debuglocal(4,"num_eas = %d\n", num_eas);
1780
1781 // we will count that os/2 max EA size for file is 64kb
1782 p = pfealist->list;
1783 for (i = 0; i < num_eas; i++)
1784 {
1785 int namelen = strlen(ea_list[i].name);
1786 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);
1787 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1788 {
1789 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1790 continue;
1791 }
1792 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1793 if (size >= gotsize)
1794 {
1795 p->fEA = 0;
1796 p->cbName = namelen;
1797 p->cbValue = ea_list[i].value.length;
1798 q = (char *)(p + 1);
1799 strncpy(q, ea_list[i].name, namelen + 1);
1800 q += namelen + 1;
1801 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1802 p = (FEA *)(q + ea_list[i].value.length);
1803 }
1804 }
1805 pfealist->cbList = gotsize;
1806 debuglocal(4,"ret size = %d\n", gotsize);
1807
1808 talloc_destroy(mem_ctx);
1809 return 0;
1810}
1811
1812/*****************************************************
1813lists EA of a path
1814*******************************************************/
1815int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1816{
1817 if (!cli || !fname || !buffer)
1818 {
1819 return maperror(EINVAL);
1820 }
1821
1822 debuglocal(4,"EALIst for <%s>\n", fname);
1823 return unilistea(cli, fname, NULL, buffer, size);
1824}
1825
1826/*****************************************************
1827lists EA of a file
1828*******************************************************/
1829int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1830{
1831 if (!cli || !file || !buffer)
1832 {
1833 return maperror(EINVAL);
1834 }
1835
1836 debuglocal(4,"FEALIst for <%s>/%d\n", file->fname, file->fd);
1837 return unilistea(cli, NULL, file, buffer, size);
1838}
1839
1840/****************************************************************************
1841Check the space on a device.
1842****************************************************************************/
1843int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1844{
1845 int total, bsize, avail;
1846
1847 if (!cli || !pfsa)
1848 {
1849 return maperror(EINVAL);
1850 }
1851
1852 if (!cli_dskattr(cli, &bsize, &total, &avail))
1853 {
1854 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1855 return os2cli_errno(cli);
1856 }
1857
1858 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1859 total, bsize, avail);
1860
1861 // YD currently Samba return it in MB!
1862 pfsa->cSectorUnit = 1;
1863 if (bsize >= 65536)
1864 {
1865 pfsa->cUnit = total*1024;
1866 pfsa->cUnitAvail = avail*1024;
1867 pfsa->cbSector = bsize/1024;
1868 }
1869 else
1870 {
1871 pfsa->cUnit = total;
1872 pfsa->cUnitAvail = avail;
1873 pfsa->cbSector = bsize;
1874 }
1875
1876 return 0;
1877}
1878
Note: See TracBrowser for help on using the repository browser.