source: branches/client-2.1/src/smbwrp.c@ 816

Last change on this file since 816 was 816, checked in by Silvan Scherrer, 12 years ago

Samba Client 2.1: some more timestamp work

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