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

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

samba client 2.1: caching

  • Property svn:eol-style set to native
File size: 48.5 KB
Line 
1/*
2 Netdrive Samba client plugin
3 samba library wrappers
4 Copyright (C) netlabs.org 2003-2008
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include "includes.h"
22#include "smbwrp.h"
23/****************************************************************************
24 Calculate a safe next_entry_offset.
25****************************************************************************/
26
27static size_t calc_next_entry_offset(const char *base, const char *pdata_end)
28{
29 size_t next_entry_offset = (size_t)IVAL(base,0);
30
31 if (next_entry_offset == 0 ||
32 base + next_entry_offset < base ||
33 base + next_entry_offset > pdata_end) {
34 next_entry_offset = pdata_end - base;
35 }
36 return next_entry_offset;
37}
38
39static int
40net_share_enum_rpc(struct cli_state *cli,
41 void (*fn)(const char *name,
42 uint32 type,
43 const char *comment,
44 void *state),
45 void *state)
46{
47 int i;
48 NTSTATUS status;
49 WERROR werr;
50 uint32_t resume_handle = 0;
51 uint32_t total_entries = 0;
52 struct srvsvc_NetShareInfoCtr info_ctr;
53 struct srvsvc_NetShareCtr1 ctr1;
54 fstring name = "";
55 fstring comment = "";
56 void *mem_ctx;
57 struct rpc_pipe_client *pipe_hnd;
58
59 /* Open the server service pipe */
60 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id, &pipe_hnd);
61 if (!NT_STATUS_IS_OK(status)) {
62 DEBUG(1, ("net_share_enum_rpc pipe open fail!\n"));
63 return -1;
64 }
65
66 /* Allocate a context for parsing and for the entries in "ctr" */
67 mem_ctx = talloc_init("libsmbclient: net_share_enum_rpc");
68 if (mem_ctx == NULL) {
69 DEBUG(0, ("out of memory for net_share_enum_rpc!\n"));
70 TALLOC_FREE(pipe_hnd);
71 return -1;
72 }
73
74 /* Issue the NetShareEnum RPC call and retrieve the response */
75 ZERO_STRUCT(info_ctr);
76 ZERO_STRUCT(ctr1);
77 info_ctr.level = 1;
78 info_ctr.ctr.ctr1 = &ctr1;
79 status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, mem_ctx,
80 pipe_hnd->desthost,
81 &info_ctr,
82 0xffffffff,
83 &total_entries,
84 &resume_handle,
85 &werr);
86
87 /* Was it successful? */
88 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr) || info_ctr.ctr.ctr1->count == 0) {
89 /* Nope. Go clean up. */
90 goto done;
91 }
92
93 /* For each returned entry... */
94 for (i = 0; i < info_ctr.ctr.ctr1->count; i++) {
95 struct srvsvc_NetShareInfo1 info = info_ctr.ctr.ctr1->array[i];
96
97 /* Add this share to the list */
98 (*fn)(info.name, info.type, info.comment, state);
99 }
100
101done:
102 /* Close the server service pipe */
103 TALLOC_FREE(pipe_hnd);
104
105 /* Free all memory which was allocated for this request */
106 TALLOC_FREE(mem_ctx);
107
108 /* Tell 'em if it worked */
109 return W_ERROR_IS_OK(status) ? 0 : -1;
110}
111
112/*
113 * Wrapper for cli_errno to return not connected error on negative fd
114 * Now returns an OS/2 return code instead of lerrno.
115 */
116int os2cli_errno(cli_state * cli)
117{
118 if (cli->fd == -1)
119 {
120 return maperror( ENOTCONN);
121 }
122 return maperror(cli_errno(cli));
123}
124
125void smbwrp_Logging()
126{
127 char slogfile[_MAX_PATH +1] = {0};
128 char slogfilename[] = "log.smbc";
129 char *env = getenv("LOGFILES");
130 if (env != NULL)
131 {
132 strncpy(slogfile, env, sizeof(slogfile) -1);
133 strncat(slogfile, "\\", sizeof(slogfile) - strlen(slogfile) -1);
134 strncat(slogfile, slogfilename, sizeof(slogfile) - strlen(slogfile) -1);
135 }
136 else
137 {
138 strncpy(slogfile, slogfilename, sizeof(slogfile) -1);
139 }
140
141 // init samba for debug messages
142 setup_logging(slogfile, false);
143 lp_set_logfile(slogfile);
144 debug_parse_levels("10");
145
146}
147const char * smbwrp_getVersion()
148{
149 return SAMBA_VERSION_STRING;
150}
151
152int _System smbwrp_getclisize(void)
153{
154 return sizeof(struct cli_state);
155}
156
157/*****************************************************
158initialise structures
159*******************************************************/
160int _System smbwrp_init(void)
161{
162 static int initialised = 0;
163 char *p;
164
165 if (initialised)
166 {
167 return 0;
168 }
169 initialised = 1;
170
171 lp_set_in_client(true); /* Make sure that we tell lp_load we are client */
172
173 load_case_tables();
174
175 if (!lp_load(get_dyn_CONFIGFILE(),true,false,false,true)) {
176 debuglocal(0,("The initial smb.conf is missing, 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
1108 switch (level) {
1109 case 1: /* OS/2 understands this */
1110 /* these dates are converted to GMT by
1111 make_unix_date */
1112 if (pdata_end - base < 27) {
1113 return pdata_end - base;
1114 }
1115 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1116 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1117 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1118 finfo->size = IVAL(p,16);
1119 finfo->attr = CVAL(p,24);
1120 len = CVAL(p, 26);
1121 p += 27;
1122 p += clistr_align_in(cli, p, 0);
1123
1124 /* We can safely use len here (which is required by OS/2)
1125 * and the NAS-BASIC server instead of +2 or +1 as the
1126 * STR_TERMINATE flag below is
1127 * actually used as the length calculation.
1128 * The len is merely an upper bound.
1129 * Due to the explicit 2 byte null termination
1130 * in cli_receive_trans/cli_receive_nt_trans
1131 * we know this is safe. JRA + kukks
1132 */
1133
1134 if (p + len > pdata_end) {
1135 return pdata_end - base;
1136 }
1137
1138 /* the len+2 below looks strange but it is
1139 important to cope with the differences
1140 between win2000 and win9x for this call
1141 (tridge) */
1142 ret = clistr_pull_talloc(ctx, cli, &fname, p,
1143 len+2,
1144 STR_TERMINATE);
1145 if (ret == (size_t)-1) {
1146 return pdata_end - base;
1147 }
1148 p += ret;
1149 finfo->easize = -1;
1150 strncpy(finfo->fname, fname, sizeof(finfo->fname) -1);
1151 return PTR_DIFF(p, base);
1152
1153 case 2: /* this is what OS/2 uses mostly */
1154 /* these dates are converted to GMT by
1155 make_unix_date */
1156 if (pdata_end - base < 31) {
1157 return pdata_end - base;
1158 }
1159 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1160 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1161 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1162 finfo->size = IVAL(p,16);
1163 finfo->attr = CVAL(p,24);
1164 finfo->easize = IVAL(p,26);
1165 len = CVAL(p, 30);
1166 p += 31;
1167 /* check for unisys! */
1168 if (p + len + 1 > pdata_end) {
1169 return pdata_end - base;
1170 }
1171 ret = clistr_pull_talloc(ctx, cli, &fname, p,
1172 len,
1173 STR_NOALIGN);
1174 if (ret == (size_t)-1) {
1175 return pdata_end - base;
1176 }
1177 p += ret;
1178 strncpy(finfo->fname, fname, sizeof(finfo->fname) -1);
1179 return PTR_DIFF(p, base) + 1;
1180
1181 case 260: /* NT uses this, but also accepts 2 */
1182 {
1183 size_t namelen, slen;
1184
1185 if (pdata_end - base < 94) {
1186 return pdata_end - base;
1187 }
1188
1189 p += 4; /* next entry offset */
1190
1191 if (p_resume_key) {
1192 *p_resume_key = IVAL(p,0);
1193 }
1194
1195 p += 4; /* fileindex */
1196
1197 /* Offset zero is "create time", not "change time". */
1198 p += 8;
1199 finfo->atime = interpret_long_date(p).tv_sec;
1200 p += 8;
1201 finfo->mtime = interpret_long_date(p).tv_sec;
1202 p += 8;
1203 finfo->ctime = interpret_long_date(p).tv_sec;
1204 p += 8;
1205 finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0);
1206 p += 8;
1207 p += 8; /* alloc size */
1208 finfo->attr = CVAL(p,0);
1209 p += 4;
1210 namelen = IVAL(p,0);
1211 p += 4;
1212 finfo->easize = IVAL(p,0);
1213 p += 4; /* EA size */
1214 slen = SVAL(p, 0);
1215 if (slen > 24) {
1216 /* Bad short name length. */
1217 return pdata_end - base;
1218 }
1219 p += 2;
1220#if 0
1221 {
1222 /* stupid NT bugs. grr */
1223 int flags = 0;
1224 if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE;
1225 clistr_pull(cli, finfo->short_name, p,
1226 sizeof(finfo->short_name),
1227 slen, flags);
1228 }
1229#endif
1230 p += 24; /* short name? */
1231 if (p + namelen < p || p + namelen > pdata_end) {
1232 return pdata_end - base;
1233 }
1234 ret = clistr_pull_talloc(ctx, cli, &fname, p,
1235 namelen, 0);
1236 if (ret == (size_t)-1) {
1237 return pdata_end - base;
1238 }
1239 strncpy(finfo->fname, fname, sizeof(finfo->fname) -1);
1240 /* To be robust in the face of unicode conversion failures
1241 we need to copy the raw bytes of the last name seen here.
1242 Namelen doesn't include the terminating unicode null, so
1243 copy it here. */
1244#if 0
1245 if (p_last_name_raw) {
1246 *p_last_name_raw = data_blob(NULL, namelen+2);
1247 memcpy(p_last_name_raw->data, p, namelen);
1248 SSVAL(p_last_name_raw->data, namelen, 0);
1249 }
1250#endif
1251 return calc_next_entry_offset(base, pdata_end);
1252 }
1253 }
1254
1255 debuglocal(1,"Unknown long filename format %d\n",level);
1256 return calc_next_entry_offset(base, pdata_end);
1257}
1258
1259/****************************************************************************
1260 Do a directory listing, calling fn on each file found.
1261 Modified from cli_list_new
1262****************************************************************************/
1263
1264static int list_files(struct cli_state *cli, const char *Mask, uint16 attribute,
1265 void (*fn)(const char*, smbwrp_fileinfo *, const char *, void *), void *state)
1266{
1267#if 1
1268 int max_matches = 1366; /* Match W2k - was 512. */
1269#else
1270 int max_matches = 512;
1271#endif
1272 int info_level;
1273 char *p, *p2, *rdata_end;
1274 char *mask=NULL;
1275 smbwrp_fileinfo finfo;
1276 int i;
1277 char *dirlist = NULL;
1278 int dirlist_len = 0;
1279 int total_received = -1;
1280 bool First = True;
1281 int ff_searchcount=0;
1282 int ff_eos=0;
1283 int ff_dir_handle=0;
1284 int loop_count = 0;
1285 char *rparam=NULL, *rdata=NULL;
1286 unsigned int param_len, data_len;
1287 uint16 setup;
1288 char *param;
1289 const char *mnt;
1290 uint32 resume_key = 0;
1291 TALLOC_CTX *frame = talloc_stackframe();
1292 DATA_BLOB last_name_raw = data_blob(NULL, 0);
1293
1294 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1295 info_level = (cli->capabilities&CAP_NT_SMBS)?260:2;
1296
1297 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, Mask);
1298
1299 mask = SMB_STRDUP(Mask);
1300 if (!mask) {
1301 TALLOC_FREE(frame);
1302 return -1;
1303 }
1304
1305 /* Try to get the listing from cache. */
1306 if (dircache_list_files(fn, state, &total_received))
1307 {
1308 /* Got from cache. */
1309 return(total_received);
1310 }
1311
1312 while (ff_eos == 0) {
1313 size_t nlen = 2*(strlen(mask)+1);
1314
1315 loop_count++;
1316 if (loop_count > 200) {
1317 debuglocal(0,"Error: Looping in FIND_NEXT??\n");
1318 break;
1319 }
1320
1321 param = SMB_MALLOC_ARRAY(char, 12+nlen+last_name_raw.length+2);
1322 if (!param) {
1323 break;
1324 }
1325
1326 if (First) {
1327 setup = TRANSACT2_FINDFIRST;
1328 SSVAL(param,0,attribute); /* attribute */
1329 SSVAL(param,2,max_matches); /* max count */
1330 SSVAL(param,4,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1331 SSVAL(param,6,info_level);
1332 SIVAL(param,8,0);
1333 p = param+12;
1334 p += clistr_push(cli, param+12, mask, nlen,
1335 STR_TERMINATE);
1336 } else {
1337 setup = TRANSACT2_FINDNEXT;
1338 SSVAL(param,0,ff_dir_handle);
1339 SSVAL(param,2,max_matches); /* max count */
1340 SSVAL(param,4,info_level);
1341 /* For W2K servers serving out FAT filesystems we *must* set the
1342 resume key. If it's not FAT then it's returned as zero. */
1343 SIVAL(param,6,resume_key); /* ff_resume_key */
1344 /* NB. *DON'T* use continue here. If you do it seems that W2K and bretheren
1345 can miss filenames. Use last filename continue instead. JRA */
1346 SSVAL(param,10,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1347 p = param+12;
1348 if (last_name_raw.length) {
1349 memcpy(p, last_name_raw.data, last_name_raw.length);
1350 p += last_name_raw.length;
1351 } else {
1352 p += clistr_push(cli, param+12, mask, nlen, STR_TERMINATE);
1353 }
1354 }
1355
1356 param_len = PTR_DIFF(p, param);
1357
1358 if (!cli_send_trans(cli, SMBtrans2,
1359 NULL, /* Name */
1360 -1, 0, /* fid, flags */
1361 &setup, 1, 0, /* setup, length, max */
1362 param, param_len, 10, /* param, length, max */
1363 NULL, 0,
1364#if 0
1365 /* w2k value. */
1366 MIN(16384,cli->max_xmit) /* data, length, max. */
1367#else
1368 cli->max_xmit /* data, length, max. */
1369#endif
1370 )) {
1371 SAFE_FREE(param);
1372 TALLOC_FREE(frame);
1373 break;
1374 }
1375
1376 SAFE_FREE(param);
1377
1378 if (!cli_receive_trans(cli, SMBtrans2,
1379 &rparam, &param_len,
1380 &rdata, &data_len) &&
1381 cli_is_dos_error(cli)) {
1382 /* we need to work around a Win95 bug - sometimes
1383 it gives ERRSRV/ERRerror temprarily */
1384 uint8 eclass;
1385 uint32 ecode;
1386
1387 SAFE_FREE(rdata);
1388 SAFE_FREE(rparam);
1389
1390 cli_dos_error(cli, &eclass, &ecode);
1391
1392 /*
1393 * OS/2 might return "no more files",
1394 * which just tells us, that searchcount is zero
1395 * in this search.
1396 * Guenter Kukkukk <linux@kukkukk.com>
1397 */
1398
1399 if (eclass == ERRDOS && ecode == ERRnofiles) {
1400 ff_searchcount = 0;
1401 cli_reset_error(cli);
1402 break;
1403 }
1404
1405 if (eclass != ERRSRV || ecode != ERRerror)
1406 break;
1407 smb_msleep(100);
1408 continue;
1409 }
1410
1411 if (cli_is_error(cli) || !rdata || !rparam)
1412 {
1413 if (First && info_level == 2)
1414 {
1415 // we have tried query ea size, but now will try without ea size
1416 info_level = 1;
1417 debuglocal(4,"list_files fallback to level %d\n", info_level);
1418 continue;
1419 }
1420 SAFE_FREE(rdata);
1421 SAFE_FREE(rparam);
1422 break;
1423 }
1424
1425 if (total_received == -1)
1426 total_received = 0;
1427
1428 /* parse out some important return info */
1429 p = rparam;
1430 if (First) {
1431 ff_dir_handle = SVAL(p,0);
1432 ff_searchcount = SVAL(p,2);
1433 ff_eos = SVAL(p,4);
1434 } else {
1435 ff_searchcount = SVAL(p,0);
1436 ff_eos = SVAL(p,2);
1437 }
1438 debuglocal(4,"list_files %d %d %d %d\n", ff_searchcount, ff_eos, "(ff_lastname)", First);
1439
1440 if (ff_searchcount == 0) {
1441 SAFE_FREE(rdata);
1442 SAFE_FREE(rparam);
1443 break;
1444 }
1445
1446 /* point to the data bytes */
1447 p = rdata;
1448 rdata_end = rdata + data_len;
1449
1450 memset(&finfo, 0, sizeof(finfo));
1451 finfo.easize = -1;
1452 /* we might need the lastname for continuations */
1453 for (p2=p,i=0;i<ff_searchcount && p2 < rdata_end;i++) {
1454 if ((info_level == 260) && (i == ff_searchcount-1)) {
1455 /* Last entry - fixup the last offset length. */
1456 SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2));
1457 }
1458 p2 += _os2_interpret_long_filename(frame, cli, info_level, p2, rdata_end, &finfo,
1459 &resume_key, &last_name_raw);
1460
1461 if (!finfo.fname) {
1462 debuglocal(0,("Error: unable to parse name from info level %d\n",
1463 info_level));
1464 ff_eos = 1;
1465 break;
1466 }
1467
1468 if (!First && *mask && strcsequal(finfo.fname, mask)) {
1469 debuglocal(0,"Error: Looping in FIND_NEXT as name %s has already been seen?\n",
1470 finfo.fname);
1471 ff_eos = 1;
1472 break;
1473 }
1474 }
1475
1476 SAFE_FREE(mask);
1477 if (ff_searchcount > 0) {
1478 mask = SMB_STRDUP(finfo.fname);
1479 } else {
1480 mask = SMB_STRDUP("");
1481 }
1482 if (!mask) {
1483 SAFE_FREE(rdata);
1484 SAFE_FREE(rparam);
1485 break;
1486 }
1487
1488 /* grab the data for later use */
1489 /* and add them to the dirlist pool */
1490 dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len);
1491
1492 if (!dirlist) {
1493 debuglocal(0,"cli_list_new: Failed to expand dirlist\n");
1494 SAFE_FREE(rdata);
1495 SAFE_FREE(rparam);
1496 break;
1497 }
1498
1499 memcpy(dirlist+dirlist_len,p,data_len);
1500 dirlist_len += data_len;
1501
1502 total_received += ff_searchcount;
1503
1504 SAFE_FREE(rdata);
1505 SAFE_FREE(rparam);
1506
1507 debuglocal(3,"received %d entries (eos=%d)\n",
1508 ff_searchcount,ff_eos);
1509
1510 if (ff_searchcount > 0)
1511 loop_count = 0;
1512
1513 First = False;
1514 }
1515
1516 mnt = cli_cm_get_mntpoint( cli );
1517
1518 /* see if the server disconnected or the connection otherwise failed */
1519 if (cli_is_error(cli)) {
1520 total_received = -1;
1521 } else {
1522 void *dircachectx = dircache_write_begin(state, total_received);
1523
1524 /* no connection problem. let user function add each entry */
1525 rdata_end = dirlist + dirlist_len;
1526 for (p=dirlist,i=0;i<total_received;i++) {
1527 p += _os2_interpret_long_filename(frame, cli, info_level, p, rdata_end,
1528 &finfo,NULL,NULL);
1529 if (!finfo.fname) {
1530 debuglocal(0,"list_new: unable to parse name from info level %d\n",
1531 info_level);
1532 break;
1533 }
1534 fn( mnt,&finfo, Mask, state );
1535
1536 /* Also add the entry to the cache. */
1537 dircache_write_entry(dircachectx, &finfo);
1538 }
1539
1540 dircache_write_end(dircachectx);
1541
1542 }
1543
1544 /* free up the dirlist buffer and last name raw blob */
1545 SAFE_FREE(dirlist);
1546 data_blob_free(&last_name_raw);
1547 SAFE_FREE(mask);
1548 TALLOC_FREE(frame);
1549 return(total_received);
1550}
1551
1552
1553/*****************************************************
1554open a directory on the server
1555*******************************************************/
1556int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1557{
1558 if (!srv || !cli || !state || !*state->mask)
1559 {
1560 return EINVAL;
1561 }
1562 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);
1563 if (*srv->workgroup == 0 && *srv->server_name == 0)
1564 {
1565 smbwrp_special_add(".", state);
1566 smbwrp_special_add("..", state);
1567 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1568 smbwrp_share_add, state);
1569 } else
1570 if (*srv->server_name == 0)
1571 {
1572 smbwrp_special_add(".", state);
1573 smbwrp_special_add("..", state);
1574
1575 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1576 smbwrp_share_add, state);
1577 } else
1578 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1579 {
1580 smbwrp_special_add(".", state);
1581 smbwrp_special_add("..", state);
1582
1583 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1584 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1585 {
1586 return os2cli_errno(cli);
1587 }
1588 } else
1589 if (strncmp(cli->dev,"LPT",3) == 0)
1590 {
1591 smbwrp_special_add(".", state);
1592 smbwrp_special_add("..", state);
1593 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1594 {
1595 return os2cli_errno(cli);
1596 }
1597 }
1598 else
1599 {
1600#if 0
1601 if (strcmp(path,"\\") == 0) {
1602 smbwrp_special_add(".", state);
1603 smbwrp_special_add("..", state);
1604 }
1605#endif
1606#if 0
1607 if (cli_list(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1608 smbwrp_dir_add_old, state) < 0)
1609#else
1610 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1611 smbwrp_dir_add, state) < 0)
1612#endif
1613 {
1614 return os2cli_errno(cli);
1615 }
1616 }
1617
1618 return 0;
1619}
1620
1621/*****************************************************
1622a wrapper for chdir()
1623*******************************************************/
1624int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1625{
1626 unsigned short mode = aDIR;
1627 smbwrp_fileinfo finfo = {0};
1628 if (!cli || !fname)
1629 {
1630 return EINVAL;
1631 }
1632
1633 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1634 if (smbwrp_getattr(srv, cli, &finfo))
1635 {
1636 return os2cli_errno(cli);
1637 }
1638
1639 if (!(finfo.attr & aDIR)) {
1640 return ENOTDIR;
1641 }
1642
1643 return 0;
1644}
1645
1646
1647/*****************************************************
1648a wrapper for mkdir()
1649*******************************************************/
1650int _System smbwrp_mkdir(cli_state * cli, char *fname)
1651{
1652 if (!cli || !fname)
1653 {
1654 return EINVAL;
1655 }
1656
1657 if (!cli_mkdir(cli, fname))
1658 {
1659 return os2cli_errno(cli);
1660 }
1661 return 0;
1662}
1663
1664/*****************************************************
1665a wrapper for rmdir()
1666*******************************************************/
1667int _System smbwrp_rmdir(cli_state * cli, char *fname)
1668{
1669 if (!cli || !fname)
1670 {
1671 return EINVAL;
1672 }
1673
1674 if (!cli_rmdir(cli, fname))
1675 {
1676 return os2cli_errno(cli);
1677 }
1678 return 0;
1679}
1680
1681/*****************************************************
1682set EA for a path
1683*******************************************************/
1684int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1685{
1686 if (!cli || !fname || !name)
1687 {
1688 return EINVAL;
1689 }
1690 if (!cli_set_ea_path(cli, fname, name, value, size))
1691 {
1692 return os2cli_errno(cli);
1693 }
1694 return 0;
1695}
1696
1697/*****************************************************
1698set EA for a file
1699*******************************************************/
1700int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1701{
1702 if (!cli || !file || !name)
1703 {
1704 return EINVAL;
1705 }
1706 if (!cli_set_ea_fnum(cli, file->fd, name, value, size))
1707 {
1708 return os2cli_errno(cli);
1709 }
1710 return 0;
1711}
1712
1713
1714#pragma pack(1)
1715typedef struct _FEA /* fea */
1716{
1717 unsigned char fEA; /* flags */
1718 unsigned char cbName; /* name length not including NULL */
1719 unsigned short cbValue; /* value length */
1720} FEA;
1721
1722typedef struct _FEALIST /* feal */
1723{
1724 unsigned long cbList; /* total bytes of structure including full list */
1725 FEA list[1]; /* variable length FEA structures */
1726} FEALIST;
1727#pragma pack()
1728
1729static int unilistea(cli_state * cli, char *fname, smbwrp_file *file, void * buffer, unsigned long size)
1730{
1731 int fnum, i;
1732 int gotsize = sizeof(unsigned long);
1733 size_t num_eas;
1734 struct ea_struct *ea_list = NULL;
1735 TALLOC_CTX *mem_ctx;
1736 FEA * p;
1737 FEALIST * pfealist;
1738 char * q;
1739
1740 mem_ctx = talloc_init("%d: ealist", _gettid());
1741 pfealist = (FEALIST *)buffer;
1742 pfealist->cbList = 0;
1743
1744 if (file)
1745 {
1746 if (!cli_get_ea_list_fnum(cli, file->fd, mem_ctx, &num_eas, &ea_list))
1747 {
1748 debuglocal(4,"ea_get_fnum list failed - %s\n", cli_errstr(cli));
1749 talloc_destroy(mem_ctx);
1750 return os2cli_errno(cli);
1751 }
1752 }
1753 else
1754 {
1755 if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list))
1756 {
1757 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1758 talloc_destroy(mem_ctx);
1759 return os2cli_errno(cli);
1760 }
1761 }
1762
1763 debuglocal(4,"num_eas = %d\n", num_eas);
1764
1765 // we will count that os/2 max EA size for file is 64kb
1766 p = pfealist->list;
1767 for (i = 0; i < num_eas; i++)
1768 {
1769 int namelen = strlen(ea_list[i].name);
1770 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);
1771 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1772 {
1773 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1774 continue;
1775 }
1776 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1777 if (size >= gotsize)
1778 {
1779 p->fEA = 0;
1780 p->cbName = namelen;
1781 p->cbValue = ea_list[i].value.length;
1782 q = (char *)(p + 1);
1783 strncpy(q, ea_list[i].name, namelen + 1);
1784 q += namelen + 1;
1785 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1786 p = (FEA *)(q + ea_list[i].value.length);
1787 }
1788 }
1789 pfealist->cbList = gotsize;
1790 debuglocal(4,"ret size = %d\n", gotsize);
1791
1792 talloc_destroy(mem_ctx);
1793 return 0;
1794}
1795
1796/*****************************************************
1797lists EA of a path
1798*******************************************************/
1799int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1800{
1801 if (!cli || !fname || !buffer)
1802 {
1803 return EINVAL;
1804 }
1805
1806 debuglocal(4,"EALIst for <%s>\n", fname);
1807 return unilistea(cli, fname, NULL, buffer, size);
1808}
1809
1810/*****************************************************
1811lists EA of a file
1812*******************************************************/
1813int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1814{
1815 if (!cli || !file || !buffer)
1816 {
1817 return EINVAL;
1818 }
1819
1820 debuglocal(4,"FEALIst for <%s>/%d\n", file->fname, file->fd);
1821 return unilistea(cli, NULL, file, buffer, size);
1822}
1823
1824/****************************************************************************
1825Check the space on a device.
1826****************************************************************************/
1827int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1828{
1829 int total, bsize, avail;
1830
1831 if (!cli || !pfsa)
1832 {
1833 return EINVAL;
1834 }
1835
1836 if (!cli_dskattr(cli, &bsize, &total, &avail))
1837 {
1838 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1839 return os2cli_errno(cli);
1840 }
1841
1842 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1843 total, bsize, avail);
1844
1845 // YD currently Samba return it in MB!
1846 pfsa->cSectorUnit = 1;
1847 if (bsize >= 65536)
1848 {
1849 pfsa->cUnit = total*1024;
1850 pfsa->cUnitAvail = avail*1024;
1851 pfsa->cbSector = bsize/1024;
1852 }
1853 else
1854 {
1855 pfsa->cUnit = total;
1856 pfsa->cUnitAvail = avail;
1857 pfsa->cbSector = bsize;
1858 }
1859
1860 return 0;
1861}
1862
Note: See TracBrowser for help on using the repository browser.