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

Last change on this file since 650 was 567, checked in by Silvan Scherrer, 14 years ago

Samba Client 2.1: crash fix

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