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

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

Samba Client 1.6: working dll

  • Property svn:eol-style set to native
File size: 48.0 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 who frees fname, as clistr_pull_talloc allocs it
1088static size_t _os2_interpret_long_filename(TALLOC_CTX *ctx, struct cli_state *cli,
1089 int level,const char *p, const char *pdata_end, smbwrp_fileinfo *finfo,
1090 uint32 *p_resume_key, DATA_BLOB *p_last_name_raw)
1091{
1092 int len;
1093 const char *base = p;
1094 size_t ret;
1095 char *fname;
1096
1097 data_blob_free(p_last_name_raw);
1098
1099 if (p_resume_key) {
1100 *p_resume_key = 0;
1101 }
1102
1103 ZERO_STRUCTP(finfo);
1104 debuglocal(9,"fname %s (serverzone %d, level %d)\n",finfo->fname, cli->serverzone, level);
1105
1106 switch (level) {
1107 case 1: /* OS/2 understands this */
1108 /* these dates are converted to GMT by
1109 make_unix_date */
1110 if (pdata_end - base < 27) {
1111 return pdata_end - base;
1112 }
1113 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1114 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1115 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1116 finfo->size = IVAL(p,16);
1117 finfo->attr = CVAL(p,24);
1118 len = CVAL(p, 26);
1119 p += 27;
1120 p += clistr_align_in(cli, p, 0);
1121
1122 /* We can safely use len here (which is required by OS/2)
1123 * and the NAS-BASIC server instead of +2 or +1 as the
1124 * STR_TERMINATE flag below is
1125 * actually used as the length calculation.
1126 * The len is merely an upper bound.
1127 * Due to the explicit 2 byte null termination
1128 * in cli_receive_trans/cli_receive_nt_trans
1129 * we know this is safe. JRA + kukks
1130 */
1131
1132 if (p + len > pdata_end) {
1133 return pdata_end - base;
1134 }
1135
1136 /* the len+2 below looks strange but it is
1137 important to cope with the differences
1138 between win2000 and win9x for this call
1139 (tridge) */
1140 ret = clistr_pull_talloc(ctx, cli, &fname, p,
1141 len+2,
1142 STR_TERMINATE);
1143 if (ret == (size_t)-1) {
1144 return pdata_end - base;
1145 }
1146 p += ret;
1147 finfo->easize = -1;
1148 strncpy(finfo->fname, fname, sizeof(finfo->fname) -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, &fname, p,
1170 len,
1171 STR_NOALIGN);
1172 if (ret == (size_t)-1) {
1173 return pdata_end - base;
1174 }
1175 p += ret;
1176 strncpy(finfo->fname, fname, sizeof(finfo->fname) -1);
1177 return PTR_DIFF(p, base) + 1;
1178
1179 case 260: /* NT uses this, but also accepts 2 */
1180 {
1181 size_t namelen, slen;
1182
1183 if (pdata_end - base < 94) {
1184 return pdata_end - base;
1185 }
1186
1187 p += 4; /* next entry offset */
1188
1189 if (p_resume_key) {
1190 *p_resume_key = IVAL(p,0);
1191 }
1192
1193 p += 4; /* fileindex */
1194
1195 /* Offset zero is "create time", not "change time". */
1196 p += 8;
1197 finfo->atime = interpret_long_date(p).tv_sec;
1198 p += 8;
1199 finfo->mtime = interpret_long_date(p).tv_sec;
1200 p += 8;
1201 finfo->ctime = interpret_long_date(p).tv_sec;
1202 p += 8;
1203 finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0);
1204 p += 8;
1205 p += 8; /* alloc size */
1206 finfo->attr = CVAL(p,0);
1207 p += 4;
1208 namelen = IVAL(p,0);
1209 p += 4;
1210 finfo->easize = IVAL(p,0);
1211 p += 4; /* EA size */
1212 slen = SVAL(p, 0);
1213 if (slen > 24) {
1214 /* Bad short name length. */
1215 return pdata_end - base;
1216 }
1217 p += 2;
1218#if 0
1219 {
1220 /* stupid NT bugs. grr */
1221 int flags = 0;
1222 if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE;
1223 clistr_pull(cli, finfo->short_name, p,
1224 sizeof(finfo->short_name),
1225 slen, flags);
1226 }
1227#endif
1228 p += 24; /* short name? */
1229 if (p + namelen < p || p + namelen > pdata_end) {
1230 return pdata_end - base;
1231 }
1232 ret = clistr_pull_talloc(ctx, cli, &fname, p,
1233 namelen, 0);
1234 if (ret == (size_t)-1) {
1235 return pdata_end - base;
1236 }
1237 strncpy(finfo->fname, fname, sizeof(finfo->fname) -1);
1238 /* To be robust in the face of unicode conversion failures
1239 we need to copy the raw bytes of the last name seen here.
1240 Namelen doesn't include the terminating unicode null, so
1241 copy it here. */
1242#if 0
1243 if (p_last_name_raw) {
1244 *p_last_name_raw = data_blob(NULL, namelen+2);
1245 memcpy(p_last_name_raw->data, p, namelen);
1246 SSVAL(p_last_name_raw->data, namelen, 0);
1247 }
1248#endif
1249 return calc_next_entry_offset(base, pdata_end);
1250 }
1251 }
1252
1253 debuglocal(1,"Unknown long filename format %d\n",level);
1254 return calc_next_entry_offset(base, pdata_end);
1255}
1256
1257/****************************************************************************
1258 Do a directory listing, calling fn on each file found.
1259 Modified from cli_list_new
1260****************************************************************************/
1261
1262static int list_files(struct cli_state *cli, const char *Mask, uint16 attribute,
1263 void (*fn)(const char*, smbwrp_fileinfo *, const char *, void *), void *state)
1264{
1265#if 1
1266 int max_matches = 1366; /* Match W2k - was 512. */
1267#else
1268 int max_matches = 512;
1269#endif
1270 int info_level;
1271 char *p, *p2, *rdata_end;
1272 char *mask=NULL;
1273 smbwrp_fileinfo finfo;
1274 int i;
1275 char *dirlist = NULL;
1276 int dirlist_len = 0;
1277 int total_received = -1;
1278 bool First = True;
1279 int ff_searchcount=0;
1280 int ff_eos=0;
1281 int ff_dir_handle=0;
1282 int loop_count = 0;
1283 char *rparam=NULL, *rdata=NULL;
1284 unsigned int param_len, data_len;
1285 uint16 setup;
1286 char *param;
1287 const char *mnt;
1288 uint32 resume_key = 0;
1289 TALLOC_CTX *frame = talloc_stackframe();
1290 DATA_BLOB last_name_raw = data_blob(NULL, 0);
1291
1292 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1293 info_level = (cli->capabilities&CAP_NT_SMBS)?260:2;
1294
1295 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, Mask);
1296
1297 mask = SMB_STRDUP(Mask);
1298 if (!mask) {
1299 TALLOC_FREE(frame);
1300 return -1;
1301 }
1302
1303 while (ff_eos == 0) {
1304 size_t nlen = 2*(strlen(mask)+1);
1305
1306 loop_count++;
1307 if (loop_count > 200) {
1308 debuglocal(0,"Error: Looping in FIND_NEXT??\n");
1309 break;
1310 }
1311
1312 param = SMB_MALLOC_ARRAY(char, 12+nlen+last_name_raw.length+2);
1313 if (!param) {
1314 break;
1315 }
1316
1317 if (First) {
1318 setup = TRANSACT2_FINDFIRST;
1319 SSVAL(param,0,attribute); /* attribute */
1320 SSVAL(param,2,max_matches); /* max count */
1321 SSVAL(param,4,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1322 SSVAL(param,6,info_level);
1323 SIVAL(param,8,0);
1324 p = param+12;
1325 p += clistr_push(cli, param+12, mask, nlen,
1326 STR_TERMINATE);
1327 } else {
1328 setup = TRANSACT2_FINDNEXT;
1329 SSVAL(param,0,ff_dir_handle);
1330 SSVAL(param,2,max_matches); /* max count */
1331 SSVAL(param,4,info_level);
1332 /* For W2K servers serving out FAT filesystems we *must* set the
1333 resume key. If it's not FAT then it's returned as zero. */
1334 SIVAL(param,6,resume_key); /* ff_resume_key */
1335 /* NB. *DON'T* use continue here. If you do it seems that W2K and bretheren
1336 can miss filenames. Use last filename continue instead. JRA */
1337 SSVAL(param,10,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1338 p = param+12;
1339 if (last_name_raw.length) {
1340 memcpy(p, last_name_raw.data, last_name_raw.length);
1341 p += last_name_raw.length;
1342 } else {
1343 p += clistr_push(cli, param+12, mask, nlen, STR_TERMINATE);
1344 }
1345 }
1346
1347 param_len = PTR_DIFF(p, param);
1348
1349 if (!cli_send_trans(cli, SMBtrans2,
1350 NULL, /* Name */
1351 -1, 0, /* fid, flags */
1352 &setup, 1, 0, /* setup, length, max */
1353 param, param_len, 10, /* param, length, max */
1354 NULL, 0,
1355#if 0
1356 /* w2k value. */
1357 MIN(16384,cli->max_xmit) /* data, length, max. */
1358#else
1359 cli->max_xmit /* data, length, max. */
1360#endif
1361 )) {
1362 SAFE_FREE(param);
1363 TALLOC_FREE(frame);
1364 break;
1365 }
1366
1367 SAFE_FREE(param);
1368
1369 if (!cli_receive_trans(cli, SMBtrans2,
1370 &rparam, &param_len,
1371 &rdata, &data_len) &&
1372 cli_is_dos_error(cli)) {
1373 /* we need to work around a Win95 bug - sometimes
1374 it gives ERRSRV/ERRerror temprarily */
1375 uint8 eclass;
1376 uint32 ecode;
1377
1378 SAFE_FREE(rdata);
1379 SAFE_FREE(rparam);
1380
1381 cli_dos_error(cli, &eclass, &ecode);
1382
1383 /*
1384 * OS/2 might return "no more files",
1385 * which just tells us, that searchcount is zero
1386 * in this search.
1387 * Guenter Kukkukk <linux@kukkukk.com>
1388 */
1389
1390 if (eclass == ERRDOS && ecode == ERRnofiles) {
1391 ff_searchcount = 0;
1392 cli_reset_error(cli);
1393 break;
1394 }
1395
1396 if (eclass != ERRSRV || ecode != ERRerror)
1397 break;
1398 smb_msleep(100);
1399 continue;
1400 }
1401
1402 if (cli_is_error(cli) || !rdata || !rparam)
1403 {
1404 if (First && info_level == 2)
1405 {
1406 // we have tried query ea size, but now will try without ea size
1407 info_level = 1;
1408 debuglocal(4,"list_files fallback to level %d\n", info_level);
1409 continue;
1410 }
1411 SAFE_FREE(rdata);
1412 SAFE_FREE(rparam);
1413 break;
1414 }
1415
1416 if (total_received == -1)
1417 total_received = 0;
1418
1419 /* parse out some important return info */
1420 p = rparam;
1421 if (First) {
1422 ff_dir_handle = SVAL(p,0);
1423 ff_searchcount = SVAL(p,2);
1424 ff_eos = SVAL(p,4);
1425 } else {
1426 ff_searchcount = SVAL(p,0);
1427 ff_eos = SVAL(p,2);
1428 }
1429 debuglocal(4,"list_files %d %d %d %d\n", ff_searchcount, ff_eos, "(ff_lastname)", First);
1430
1431 if (ff_searchcount == 0) {
1432 SAFE_FREE(rdata);
1433 SAFE_FREE(rparam);
1434 break;
1435 }
1436
1437 /* point to the data bytes */
1438 p = rdata;
1439 rdata_end = rdata + data_len;
1440
1441 memset(&finfo, 0, sizeof(finfo));
1442 finfo.easize = -1;
1443 /* we might need the lastname for continuations */
1444 for (p2=p,i=0;i<ff_searchcount && p2 < rdata_end;i++) {
1445 if ((info_level == 260) && (i == ff_searchcount-1)) {
1446 /* Last entry - fixup the last offset length. */
1447 SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2));
1448 }
1449 p2 += _os2_interpret_long_filename(frame, cli, info_level, p2, rdata_end, &finfo,
1450 &resume_key, &last_name_raw);
1451
1452 if (!finfo.fname) {
1453 debuglocal(0,("Error: unable to parse name from info level %d\n",
1454 info_level));
1455 ff_eos = 1;
1456 break;
1457 }
1458
1459 if (!First && *mask && strcsequal(finfo.fname, mask)) {
1460 debuglocal(0,"Error: Looping in FIND_NEXT as name %s has already been seen?\n",
1461 finfo.fname);
1462 ff_eos = 1;
1463 break;
1464 }
1465 }
1466
1467 SAFE_FREE(mask);
1468 if (ff_searchcount > 0) {
1469 mask = SMB_STRDUP(finfo.fname);
1470 } else {
1471 mask = SMB_STRDUP("");
1472 }
1473 if (!mask) {
1474 SAFE_FREE(rdata);
1475 SAFE_FREE(rparam);
1476 break;
1477 }
1478
1479 /* grab the data for later use */
1480 /* and add them to the dirlist pool */
1481 dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len);
1482
1483 if (!dirlist) {
1484 debuglocal(0,"cli_list_new: Failed to expand dirlist\n");
1485 SAFE_FREE(rdata);
1486 SAFE_FREE(rparam);
1487 break;
1488 }
1489
1490 memcpy(dirlist+dirlist_len,p,data_len);
1491 dirlist_len += data_len;
1492
1493 total_received += ff_searchcount;
1494
1495 SAFE_FREE(rdata);
1496 SAFE_FREE(rparam);
1497
1498 debuglocal(3,"received %d entries (eos=%d)\n",
1499 ff_searchcount,ff_eos);
1500
1501 if (ff_searchcount > 0)
1502 loop_count = 0;
1503
1504 First = False;
1505 }
1506
1507 mnt = cli_cm_get_mntpoint( cli );
1508
1509 /* see if the server disconnected or the connection otherwise failed */
1510 if (cli_is_error(cli)) {
1511 total_received = -1;
1512 } else {
1513 /* no connection problem. let user function add each entry */
1514 rdata_end = dirlist + dirlist_len;
1515 for (p=dirlist,i=0;i<total_received;i++) {
1516 p += _os2_interpret_long_filename(frame, cli, info_level, p, rdata_end,
1517 &finfo,NULL,NULL);
1518 if (!finfo.fname) {
1519 debuglocal(0,"list_new: unable to parse name from info level %d\n",
1520 info_level);
1521 break;
1522 }
1523 fn( mnt,&finfo, Mask, state );
1524 }
1525 }
1526
1527 /* free up the dirlist buffer and last name raw blob */
1528 SAFE_FREE(dirlist);
1529 data_blob_free(&last_name_raw);
1530 SAFE_FREE(mask);
1531 TALLOC_FREE(frame);
1532 return(total_received);
1533}
1534
1535
1536/*****************************************************
1537open a directory on the server
1538*******************************************************/
1539int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1540{
1541 if (!srv || !cli || !state || !*state->mask)
1542 {
1543 return EINVAL;
1544 }
1545 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);
1546 if (*srv->workgroup == 0 && *srv->server_name == 0)
1547 {
1548 smbwrp_special_add(".", state);
1549 smbwrp_special_add("..", state);
1550 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1551 smbwrp_share_add, state);
1552 } else
1553 if (*srv->server_name == 0)
1554 {
1555 smbwrp_special_add(".", state);
1556 smbwrp_special_add("..", state);
1557
1558 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1559 smbwrp_share_add, state);
1560 } else
1561 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1562 {
1563 smbwrp_special_add(".", state);
1564 smbwrp_special_add("..", state);
1565
1566 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1567 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1568 {
1569 return os2cli_errno(cli);
1570 }
1571 } else
1572 if (strncmp(cli->dev,"LPT",3) == 0)
1573 {
1574 smbwrp_special_add(".", state);
1575 smbwrp_special_add("..", state);
1576 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1577 {
1578 return os2cli_errno(cli);
1579 }
1580 }
1581 else
1582 {
1583#if 0
1584 if (strcmp(path,"\\") == 0) {
1585 smbwrp_special_add(".", state);
1586 smbwrp_special_add("..", state);
1587 }
1588#endif
1589#if 0
1590 if (cli_list(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1591 smbwrp_dir_add_old, state) < 0)
1592#else
1593 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1594 smbwrp_dir_add, state) < 0)
1595#endif
1596 {
1597 return os2cli_errno(cli);
1598 }
1599 }
1600
1601 return 0;
1602}
1603
1604/*****************************************************
1605a wrapper for chdir()
1606*******************************************************/
1607int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1608{
1609 unsigned short mode = aDIR;
1610 smbwrp_fileinfo finfo = {0};
1611 if (!cli || !fname)
1612 {
1613 return EINVAL;
1614 }
1615
1616 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1617 if (smbwrp_getattr(srv, cli, &finfo))
1618 {
1619 return os2cli_errno(cli);
1620 }
1621
1622 if (!(finfo.attr & aDIR)) {
1623 return ENOTDIR;
1624 }
1625
1626 return 0;
1627}
1628
1629
1630/*****************************************************
1631a wrapper for mkdir()
1632*******************************************************/
1633int _System smbwrp_mkdir(cli_state * cli, char *fname)
1634{
1635 if (!cli || !fname)
1636 {
1637 return EINVAL;
1638 }
1639
1640 if (!cli_mkdir(cli, fname))
1641 {
1642 return os2cli_errno(cli);
1643 }
1644 return 0;
1645}
1646
1647/*****************************************************
1648a wrapper for rmdir()
1649*******************************************************/
1650int _System smbwrp_rmdir(cli_state * cli, char *fname)
1651{
1652 if (!cli || !fname)
1653 {
1654 return EINVAL;
1655 }
1656
1657 if (!cli_rmdir(cli, fname))
1658 {
1659 return os2cli_errno(cli);
1660 }
1661 return 0;
1662}
1663
1664/*****************************************************
1665set EA for a path
1666*******************************************************/
1667int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1668{
1669 if (!cli || !fname || !name)
1670 {
1671 return EINVAL;
1672 }
1673 if (!cli_set_ea_path(cli, fname, name, value, size))
1674 {
1675 return os2cli_errno(cli);
1676 }
1677 return 0;
1678}
1679
1680/*****************************************************
1681set EA for a file
1682*******************************************************/
1683int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1684{
1685 if (!cli || !file || !name)
1686 {
1687 return EINVAL;
1688 }
1689 if (!cli_set_ea_fnum(cli, file->fd, name, value, size))
1690 {
1691 return os2cli_errno(cli);
1692 }
1693 return 0;
1694}
1695
1696
1697#pragma pack(1)
1698typedef struct _FEA /* fea */
1699{
1700 unsigned char fEA; /* flags */
1701 unsigned char cbName; /* name length not including NULL */
1702 unsigned short cbValue; /* value length */
1703} FEA;
1704
1705typedef struct _FEALIST /* feal */
1706{
1707 unsigned long cbList; /* total bytes of structure including full list */
1708 FEA list[1]; /* variable length FEA structures */
1709} FEALIST;
1710#pragma pack()
1711
1712static int unilistea(cli_state * cli, char *fname, smbwrp_file *file, void * buffer, unsigned long size)
1713{
1714 int fnum, i;
1715 int gotsize = sizeof(unsigned long);
1716 size_t num_eas;
1717 struct ea_struct *ea_list = NULL;
1718 TALLOC_CTX *mem_ctx;
1719 FEA * p;
1720 FEALIST * pfealist;
1721 char * q;
1722
1723 mem_ctx = talloc_init("%d: ealist", _gettid());
1724 pfealist = (FEALIST *)buffer;
1725 pfealist->cbList = 0;
1726
1727 if (file)
1728 {
1729 if (!cli_get_ea_list_fnum(cli, file->fd, mem_ctx, &num_eas, &ea_list))
1730 {
1731 debuglocal(4,"ea_get_fnum list failed - %s\n", cli_errstr(cli));
1732 talloc_destroy(mem_ctx);
1733 return os2cli_errno(cli);
1734 }
1735 }
1736 else
1737 {
1738 if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list))
1739 {
1740 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1741 talloc_destroy(mem_ctx);
1742 return os2cli_errno(cli);
1743 }
1744 }
1745
1746 debuglocal(4,"num_eas = %d\n", num_eas);
1747
1748 // we will count that os/2 max EA size for file is 64kb
1749 p = pfealist->list;
1750 for (i = 0; i < num_eas; i++)
1751 {
1752 int namelen = strlen(ea_list[i].name);
1753 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);
1754 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1755 {
1756 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1757 continue;
1758 }
1759 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1760 if (size >= gotsize)
1761 {
1762 p->fEA = 0;
1763 p->cbName = namelen;
1764 p->cbValue = ea_list[i].value.length;
1765 q = (char *)(p + 1);
1766 strncpy(q, ea_list[i].name, namelen + 1);
1767 q += namelen + 1;
1768 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1769 p = (FEA *)(q + ea_list[i].value.length);
1770 }
1771 }
1772 pfealist->cbList = gotsize;
1773 debuglocal(4,"ret size = %d\n", gotsize);
1774
1775 talloc_destroy(mem_ctx);
1776 return 0;
1777}
1778
1779/*****************************************************
1780lists EA of a path
1781*******************************************************/
1782int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1783{
1784 if (!cli || !fname || !buffer)
1785 {
1786 return EINVAL;
1787 }
1788
1789 debuglocal(4,"EALIst for <%s>\n", fname);
1790 return unilistea(cli, fname, NULL, buffer, size);
1791}
1792
1793/*****************************************************
1794lists EA of a file
1795*******************************************************/
1796int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1797{
1798 if (!cli || !file || !buffer)
1799 {
1800 return EINVAL;
1801 }
1802
1803 debuglocal(4,"FEALIst for <%s>/%d\n", file->fname, file->fd);
1804 return unilistea(cli, NULL, file, buffer, size);
1805}
1806
1807/****************************************************************************
1808Check the space on a device.
1809****************************************************************************/
1810int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1811{
1812 int total, bsize, avail;
1813
1814 if (!cli || !pfsa)
1815 {
1816 return EINVAL;
1817 }
1818
1819 if (!cli_dskattr(cli, &bsize, &total, &avail))
1820 {
1821 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1822 return os2cli_errno(cli);
1823 }
1824
1825 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1826 total, bsize, avail);
1827
1828 // YD currently Samba return it in MB!
1829 pfsa->cSectorUnit = 1;
1830 if (bsize >= 65536)
1831 {
1832 pfsa->cUnit = total*1024;
1833 pfsa->cUnitAvail = avail*1024;
1834 pfsa->cbSector = bsize/1024;
1835 }
1836 else
1837 {
1838 pfsa->cUnit = total;
1839 pfsa->cUnitAvail = avail;
1840 pfsa->cbSector = bsize;
1841 }
1842
1843 return 0;
1844}
1845
Note: See TracBrowser for help on using the repository browser.