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

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

Samba Client 2.1: Even further more work on timestamps

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