source: branches/client-2.2/src/smbwrp.c@ 929

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

Samba Client 2.1: timestamp work

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