source: branches/client-1.6/src/smbwrp.c@ 494

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

sambaclient 1.6: attemp to fix tz problems closes ticket:56

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