source: trunk/client/src/smbwrp.c@ 521

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

Samba Client 2.1: another bunch of updates

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