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

Last change on this file since 813 was 813, checked in by Herwig Bauernfeind, 12 years ago

Samba Client 2.1: Even more work on timestamps

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