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

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

samba client 1.6: more work

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