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

Last change on this file since 806 was 806, checked in by Herwig Bauernfeind, 12 years ago

Samba Client 2.1: Fix Ticket #227 (updated timestamp during read access)

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