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

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

samba client 1.6: more work on logfile

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