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

Last change on this file since 630 was 630, checked in by Silvan Scherrer, 14 years ago

Samba Client 2.2: adjusted some more bits

  • Property svn:eol-style set to native
File size: 50.1 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 (pRes->krb5support == 1)
516 {
517 debuglocal(1,"Kerberos support enabled\n");
518 c->use_kerberos = True;
519 }
520
521 if (!NT_STATUS_IS_OK(cli_connect(c, server_n, &ss)))
522 {
523 return 3;
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 (!NT_STATUS_IS_OK(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 (!NT_STATUS_IS_OK(cli_tcon_andx(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 uint16_t fd = 0;
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 if (!NT_STATUS_IS_OK(cli_open(cli, file->fname, file->openmode, file->denymode, &fd)))
618 {
619 return os2cli_errno(cli);
620 }
621 file->fd = fd;
622 if (file->openmode & (O_WRONLY | O_RDWR | O_TRUNC | O_CREAT))
623 {
624 time_t t;
625 file->mtime = time(NULL);
626#if 0 // as time() delivers elapsed time in epoch we already have UTC
627 t = get_time_zone(file->mtime);
628 debuglocal(4,"cli_open mtime %lu %lu\n", file->mtime, t);
629 file->mtime -= t;
630#endif
631 debuglocal(4,"cli_open new mtime %lu\n", file->mtime);
632 }
633 file->offset = 0;
634 return 0;
635}
636
637/*****************************************************
638a wrapper for read()
639*******************************************************/
640int _System smbwrp_read(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
641{
642 int ret;
643
644 if (!cli || !file || !buf || !result)
645 {
646 return maperror(EINVAL);
647 }
648
649 *result = 0;
650 ret = cli_read(cli, file->fd, buf, file->offset, count);
651 if (ret == -1)
652 {
653 return os2cli_errno(cli);
654 }
655
656 file->offset += ret;
657 *result = ret;
658 return 0;
659}
660
661
662
663/*****************************************************
664a wrapper for write()
665*******************************************************/
666int _System smbwrp_write(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
667{
668 int ret;
669
670 if (!cli || !file || !buf || !result)
671 {
672 return maperror(EINVAL);
673 }
674
675 *result = 0;
676//debuglocal(1,("Write %x %d %lld %d", cli, file->fd, file->offset, count));
677 ret = cli_write(cli, file->fd, 0, buf, file->offset, count);
678 if (ret == -1)
679 {
680 return os2cli_errno(cli);
681 }
682
683 file->offset += ret;
684 *result = ret;
685 return 0;
686}
687
688/*****************************************************
689a wrapper for close()
690*******************************************************/
691int _System smbwrp_close(cli_state * cli, smbwrp_file * file)
692{
693 int rc = 0;
694 if (!cli || !file)
695 {
696 return maperror(EINVAL);
697 }
698
699
700 if (!NT_STATUS_IS_OK(cli_close(cli, file->fd)))
701 {
702 return os2cli_errno(cli);
703 }
704 file->fd = -1;
705 file->offset = 0;
706 if (file->openattr || file->mtime)
707 {
708 debuglocal(4,"Set attr on close %s %08x %d %d\n", file->fname, file->openattr, file->mtime, file->mtime);
709 if (!NT_STATUS_IS_OK(cli_setatr(cli, file->fname, file->openattr, file->mtime)))
710 {
711 debuglocal(4,"Set attr on close failed %d\n", os2cli_errno(cli));
712 //rc = os2cli_errno(cli);
713 }
714 file->openattr = 0;
715 file->mtime = 0;
716 }
717 *file->fname = 0;
718 return rc;
719}
720
721/*****************************************************
722a wrapper for setfilesize()
723*******************************************************/
724int cli_setfilenewsize(struct cli_state *cli, int fnum, off_t newsize)
725{
726 unsigned int data_len = 8;
727 unsigned int param_len = 6;
728 uint16 setup = TRANSACT2_SETFILEINFO;
729 char param[6];
730 unsigned char data[8];
731 char *rparam=NULL, *rdata=NULL;
732
733 SSVAL(param,0,fnum);
734 SSVAL(param,2,SMB_SET_FILE_END_OF_FILE_INFO);
735 SSVAL(param,4,0);
736
737 SBVAL(data, 0, newsize);
738
739 if (!cli_send_trans(cli, SMBtrans2,
740 NULL, /* name */
741 -1, 0, /* fid, flags */
742 &setup, 1, 0, /* setup, length, max */
743 param, param_len, 2, /* param, length, max */
744 (char *)&data, data_len, /* data, length */
745 cli->max_xmit /* max */
746 )) {
747 return False;
748 }
749
750 if (!cli_receive_trans(cli, SMBtrans2,
751 &rparam, &param_len,
752 &rdata, &data_len)) {
753 return False;
754 }
755
756 SAFE_FREE(rdata);
757 SAFE_FREE(rparam);
758
759 return True;
760}
761
762int _System smbwrp_setfilesize(cli_state * cli, smbwrp_file * file, long long newsize)
763{
764 int rc = 0;
765 if (!cli || !file)
766 {
767 return maperror(EINVAL);
768 }
769
770 debuglocal(4,"cli_setnewfilesize(%s) %lld\n", file->fname, newsize);
771 if (!cli_setfilenewsize(cli, file->fd, newsize))
772 {
773 if (newsize)
774 {
775 rc = os2cli_errno(cli);
776 }
777
778 if (!NT_STATUS_IS_OK(cli_close(cli, file->fd)))
779 {
780 return os2cli_errno(cli);
781 }
782 uint16_t fd = 0;
783 file->fd = -1;
784 file->offset = 0;
785 file->openmode &= ~(O_CREAT | O_EXCL);
786 file->openmode |= O_TRUNC;
787 debuglocal(4,"cli_setnewfileszie : cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
788 if (!NT_STATUS_IS_OK(cli_open(cli, file->fname, file->openmode, file->denymode, &fd)))
789 {
790 return os2cli_errno(cli);
791 }
792 file->fd = fd;
793 }
794 return 0;
795}
796
797/*****************************************************
798a wrapper for rename()
799*******************************************************/
800int _System smbwrp_rename(cli_state * cli, char *oldname, char *newname)
801{
802 if (!cli || !oldname || !newname)
803 {
804 return maperror(EINVAL);
805 }
806
807 debuglocal(1,"Rename <%s> -> <%s>\n", oldname, newname);
808 //cli_unlink(cli, newname);
809// if (!cli_rename(cli, oldname, newname) && !cli_ntrename(cli, oldname, newname))
810 if (!NT_STATUS_IS_OK(cli_rename(cli, oldname, newname)))
811 {
812 return os2cli_errno(cli);
813 }
814 return 0;
815}
816
817
818/*****************************************************
819a wrapper for chmod()
820*******************************************************/
821int _System smbwrp_setattr(cli_state * cli, smbwrp_fileinfo *finfo)
822{
823 if (!cli || !finfo || !*finfo->fname)
824 {
825 return maperror(EINVAL);
826 }
827
828debuglocal(4,"Setting on <%s> attr %04x, time %lu (timezone /%lu\n", finfo->fname, finfo->attr, finfo->mtime, finfo->mtime + get_time_zone(finfo->mtime));
829 // we already have gmt time, so no need to add timezone
830 // if (!cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime + (finfo->mtime == 0 ? 0 : get_time_zone(finfo->mtime)))
831 if (!NT_STATUS_IS_OK(cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime))
832 && !NT_STATUS_IS_OK(cli_setatr(cli, finfo->fname, finfo->attr, 0)))
833 {
834 return os2cli_errno(cli);
835 }
836 return 0;
837}
838
839/*****************************************************
840a wrapper for unlink()
841*******************************************************/
842int _System smbwrp_unlink(cli_state * cli, const char *fname)
843{
844 if (!cli || !fname)
845 {
846 return maperror(EINVAL);
847 }
848#if 0
849 if (strncmp(cli->dev, "LPT", 3) == 0)
850 {
851 int job = smbw_stat_printjob(cli, fname, NULL, NULL);
852 if (job == -1)
853 {
854 goto failed;
855 }
856 if (cli_printjob_del(cli, job) != 0)
857 {
858 goto failed;
859 }
860 } else
861#endif
862 if (!NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN)))
863 {
864 return os2cli_errno(cli);
865 }
866 return 0;
867}
868
869/*****************************************************
870a wrapper for lseek()
871*******************************************************/
872int _System smbwrp_lseek(cli_state * cli, smbwrp_file * file, int whence, long long offset)
873{
874 off_t size;
875 if (!cli || !file)
876 {
877 return maperror(EINVAL);
878 }
879
880 debuglocal(4,"lseek %d %lld %lld\n", whence, offset, file->offset);
881
882 switch (whence) {
883 case SEEK_SET:
884 if (offset < 0)
885 {
886 return maperror(EINVAL);
887 }
888 file->offset = offset;
889 break;
890 case SEEK_CUR:
891 file->offset += offset;
892 break;
893 case SEEK_END:
894 if (offset > 0)
895 {
896 return maperror(EINVAL);
897 }
898 if (!cli_qfileinfo3(cli, file->fd,
899 NULL, &size, NULL, NULL, NULL,
900 NULL, NULL) &&
901 !NT_STATUS_IS_OK(cli_getattrE(cli, file->fd,
902 NULL, &size, NULL, NULL, NULL)))
903 {
904 return os2cli_errno(cli);
905 }
906 file->offset = size + offset;
907 break;
908 default: return maperror(EINVAL);
909 }
910
911 return 0;
912}
913
914/*****************************************************
915try to do a QPATHINFO and if that fails then do a getatr
916this is needed because win95 sometimes refuses the qpathinfo
917*******************************************************/
918int _System smbwrp_getattr(smbwrp_server *srv, cli_state * cli, smbwrp_fileinfo *finfo)
919{
920 SMB_INO_T ino = 0;
921 if (!cli || !finfo || !*finfo->fname)
922 {
923 return maperror(EINVAL);
924 }
925 debuglocal(4,"getattr %d %d <%s>\n", cli->capabilities & CAP_NOPATHINFO2, cli->capabilities & CAP_NT_SMBS, finfo->fname);
926 if (!(cli->capabilities & CAP_NOPATHINFO2) &&
927 cli_qpathinfo3(cli, finfo->fname, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,
928 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino))
929 {
930 finfo->attr &= 0x7F;
931//debuglocal(2,("gotattr %08x <%s>\n", finfo->attr, finfo->fname));
932// finfo->ctime -= get_time_zone(finfo->ctime);
933// finfo->atime -= get_time_zone(finfo->atime);
934// finfo->mtime -= get_time_zone(finfo->mtime);
935 return 0;
936 }
937//debuglocal(2,("getattr rc1 %d\n", os2cli_errno(cli)));
938
939 if (cli->fd == -1)
940 {
941 /* fd == -1 means the connection is broken */
942 return maperror(ENOTCONN);
943 }
944
945 /* If the path is not on a share (it is a workgroup or a server),
946 * then cli_qpathinfo3 obviously fails. Return some fake information
947 * about the directory.
948 */
949 if ( *srv->server_name == 0
950 || (strcmp(cli->dev,"IPC") == 0)
951 || *srv->share_name == 0
952 || (stricmp(srv->share_name,"IPC$") == 0)
953 || (strncmp(cli->dev,"LPT",3) == 0)
954 )
955 {
956 debuglocal(4,"getattr not a share.\n");
957 *(time_t *)&finfo->ctime = time (NULL);
958 *(time_t *)&finfo->atime = time (NULL);
959 *(time_t *)&finfo->mtime = time (NULL);
960 finfo->size = 0;
961 finfo->easize = 0;
962 finfo->attr = aDIR;
963 return 0;
964 }
965
966 /* if this is NT then don't bother with the getatr */
967 if (cli->capabilities & CAP_NT_SMBS && !(cli->capabilities & CAP_NOPATHINFO2))
968 {
969 int ret = cli_errno(cli);
970 // cli_qpathinfo* reports EINVAL when path of given file not exists
971 // thus there is no real situation when EINVAL should be returned to
972 // client at this point, we just replace it to ENOTDIR
973 if (ret == EINVAL)
974 {
975 ret = ENOTDIR;
976 }
977 return maperror(ret);
978 }
979
980 if (NT_STATUS_IS_OK(cli_getatr(cli, finfo->fname, (unsigned short *)&finfo->attr, &finfo->size, (time_t *)&finfo->mtime)))
981 {
982//debuglocal(2,("gotattr1 %08x <%s>\n", finfo->attr, finfo->fname));
983 finfo->mtime -= get_time_zone(finfo->mtime);
984 finfo->atime = finfo->atime; //was mtime
985 finfo->ctime = finfo->ctime; //was mtime
986 cli->capabilities &= CAP_NOPATHINFO2;
987 return 0;
988 }
989 return os2cli_errno(cli);
990}
991
992/*****************************************************
993try to do a QPATHINFO and if that fails then do a getatr
994this is needed because win95 sometimes refuses the qpathinfo
995*******************************************************/
996int _System smbwrp_fgetattr(cli_state * cli, smbwrp_file *file, smbwrp_fileinfo *finfo)
997{
998 SMB_INO_T ino = 0;
999 if (!cli || !file || !finfo)
1000 {
1001 return maperror(EINVAL);
1002 }
1003
1004 strncpy(finfo->fname, file->fname, sizeof(finfo->fname) - 1);
1005 if (!cli_qfileinfo3(cli, file->fd,
1006 (unsigned short *)&finfo->attr, (off_t *)&finfo->size, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,
1007 &ino))
1008 {
1009 if (!NT_STATUS_IS_OK(cli_getattrE(cli, file->fd,
1010 (unsigned short *)&finfo->attr, (&finfo->size), (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime)))
1011 {
1012 return os2cli_errno(cli);
1013 }
1014 else
1015 {
1016 finfo->ctime -= get_time_zone(finfo->ctime);
1017 finfo->atime -= get_time_zone(finfo->atime);
1018 finfo->mtime -= get_time_zone(finfo->mtime);
1019 }
1020 }
1021 else
1022 {
1023// finfo->ctime -= get_time_zone(finfo->ctime);
1024// finfo->atime -= get_time_zone(finfo->atime);
1025// finfo->mtime -= get_time_zone(finfo->mtime);
1026 }
1027
1028 return 0;
1029}
1030
1031// =============================DIRECTORY ROUTINES============================
1032
1033/*****************************************************
1034add a entry to a directory listing
1035*******************************************************/
1036static void smbwrp_dir_add(const char* mnt, smbwrp_fileinfo *finfo, const char *mask, void *state)
1037{
1038 if (state && finfo)
1039 {
1040 filelist_state * st = (filelist_state *)state;
1041 char fullname[ _MAX_PATH] = {0};
1042 debuglocal(8,"adding <%s> %d %d %d\n", finfo->fname, sizeof(st->finfo), st->datalen, sizeof(st->finfo.fname));
1043 memcpy(&st->finfo, finfo, sizeof(st->finfo));
1044 strncpy(fullname, st->dir, strlen(st->dir));
1045 strncat(fullname, finfo->fname, sizeof(fullname) - strlen(fullname) -1);
1046 strncpy(st->finfo.fname, fullname, sizeof(st->finfo.fname));
1047 getfindinfoL( st->pConn, st->plist, &st->finfo, st->ulAttribute, st->dir_mask);
1048 }
1049}
1050
1051static void smbwrp_special_add(const char * name, void * state)
1052{
1053 smbwrp_fileinfo finfo = {0};
1054
1055 if (!name)
1056 {
1057 return;
1058 }
1059
1060 ZERO_STRUCT(finfo);
1061
1062 strncpy(finfo.fname, name, sizeof(finfo.fname) - 1);
1063 finfo.attr = aRONLY | aDIR;
1064
1065 smbwrp_dir_add("", &finfo, NULL, state);
1066}
1067
1068static void smbwrp_printjob_add(struct print_job_info *job, void * state)
1069{
1070 smbwrp_fileinfo finfo = {0};
1071
1072 ZERO_STRUCT(finfo);
1073
1074//printf("Printjob <%s>\n", job->name);
1075
1076 strncpy(finfo.fname, job->name, sizeof(finfo.fname) - 1);
1077 finfo.mtime = job->t - get_time_zone(job->t);
1078 finfo.atime = finfo.atime; //was mtime
1079 finfo.ctime = finfo.ctime; //was mtime
1080 finfo.attr = aRONLY;
1081 finfo.size = job->size;
1082
1083 smbwrp_dir_add("", &finfo, NULL, state);
1084}
1085
1086static void smbwrp_share_add(const char *share, uint32 type,
1087 const char *comment, void *state)
1088{
1089 smbwrp_fileinfo finfo = {0};
1090
1091 // strip administrative names and printers from list
1092 if (type == STYPE_PRINTQ || strcmp(share,"IPC$") == 0) return;
1093
1094 ZERO_STRUCT(finfo);
1095
1096 strncpy(finfo.fname, share, sizeof(finfo.fname) - 1);
1097 finfo.attr = aRONLY | aDIR;
1098
1099 smbwrp_dir_add("", &finfo, NULL, state);
1100}
1101
1102/****************************************************************************
1103 Interpret a long filename structure - this is mostly guesses at the moment.
1104 The length of the structure is returned
1105 The structure of a long filename depends on the info level. 260 is used
1106 by NT and 2 is used by OS/2
1107****************************************************************************/
1108// YD from libsmb\clilist.c
1109static size_t _os2_interpret_long_filename(TALLOC_CTX *ctx, struct cli_state *cli,
1110 int level,const char *p, const char *pdata_end, smbwrp_fileinfo *finfo,
1111 uint32 *p_resume_key, DATA_BLOB *p_last_name_raw)
1112{
1113 int len;
1114 const char *base = p;
1115 size_t ret;
1116 char *fname;
1117
1118 data_blob_free(p_last_name_raw);
1119
1120 if (p_resume_key) {
1121 *p_resume_key = 0;
1122 }
1123
1124/* ZERO_STRUCTP(finfo); */
1125 finfo->atime = 0;
1126 finfo->ctime = 0;
1127 finfo->mtime = 0;
1128 *finfo->fname = '\0';
1129
1130 switch (level) {
1131 case SMB_FIND_INFO_STANDARD: /* OS/2 understands this */
1132 /* these dates are converted to GMT by
1133 make_unix_date */
1134 if (pdata_end - base < 27) {
1135 return pdata_end - base;
1136 }
1137 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1138 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1139 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1140 finfo->size = IVAL(p,16);
1141 finfo->attr = CVAL(p,24);
1142 len = CVAL(p, 26);
1143 p += 27;
1144 p += clistr_align_in(cli, p, 0);
1145
1146 /* We can safely use len here (which is required by OS/2)
1147 * and the NAS-BASIC server instead of +2 or +1 as the
1148 * STR_TERMINATE flag below is
1149 * actually used as the length calculation.
1150 * The len is merely an upper bound.
1151 * Due to the explicit 2 byte null termination
1152 * in cli_receive_trans/cli_receive_nt_trans
1153 * we know this is safe. JRA + kukks
1154 */
1155
1156 if (p + len > pdata_end) {
1157 return pdata_end - base;
1158 }
1159
1160 /* the len+2 below looks strange but it is
1161 important to cope with the differences
1162 between win2000 and win9x for this call
1163 (tridge) */
1164 ret = clistr_pull_talloc(ctx, cli->inbuf, &fname, p,
1165 len+2,
1166 STR_TERMINATE);
1167 if (ret == (size_t)-1) {
1168 return pdata_end - base;
1169 }
1170 p += ret;
1171 finfo->easize = -1;
1172 strncat(finfo->fname, fname, sizeof(finfo->fname) -1);
1173 return PTR_DIFF(p, base);
1174
1175 case SMB_FIND_EA_SIZE: /* this is what OS/2 uses mostly */
1176 /* these dates are converted to GMT by
1177 make_unix_date */
1178 if (pdata_end - base < 31) {
1179 return pdata_end - base;
1180 }
1181 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1182 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1183 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1184 finfo->size = IVAL(p,16);
1185 finfo->attr = CVAL(p,24);
1186 finfo->easize = IVAL(p,26);
1187 len = CVAL(p, 30);
1188 p += 31;
1189 /* check for unisys! */
1190 if (p + len + 1 > pdata_end) {
1191 return pdata_end - base;
1192 }
1193 ret = clistr_pull_talloc(ctx, cli->inbuf, &fname, p,
1194 len,
1195 STR_NOALIGN);
1196 if (ret == (size_t)-1) {
1197 return pdata_end - base;
1198 }
1199 p += ret;
1200 strncat(finfo->fname, fname, sizeof(finfo->fname) -1);
1201 return PTR_DIFF(p, base) + 1;
1202
1203 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: /* NT uses this, but also accepts 2 */
1204 {
1205 size_t namelen, slen;
1206
1207 if (pdata_end - base < 94) {
1208 return pdata_end - base;
1209 }
1210
1211 p += 4; /* next entry offset */
1212
1213 if (p_resume_key) {
1214 *p_resume_key = IVAL(p,0);
1215 }
1216
1217 p += 4; /* fileindex */
1218
1219 /* Offset zero is "create time", not "change time". */
1220 p += 8;
1221 finfo->atime = interpret_long_date(p).tv_sec;
1222 p += 8;
1223 finfo->mtime = interpret_long_date(p).tv_sec;
1224 p += 8;
1225 finfo->ctime = interpret_long_date(p).tv_sec;
1226 p += 8;
1227 finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0);
1228 p += 8;
1229 p += 8; /* alloc size */
1230 finfo->attr = CVAL(p,0);
1231 p += 4;
1232 namelen = IVAL(p,0);
1233 p += 4;
1234 finfo->easize = IVAL(p,0);
1235 p += 4; /* EA size */
1236 slen = SVAL(p, 0);
1237 if (slen > 24) {
1238 /* Bad short name length. */
1239 return pdata_end - base;
1240 }
1241 p += 2;
1242#if 0
1243 {
1244 /* stupid NT bugs. grr */
1245 int flags = 0;
1246 if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE;
1247 clistr_pull(cli, finfo->short_name, p,
1248 sizeof(finfo->short_name),
1249 slen, flags);
1250 }
1251#endif
1252 p += 24; /* short name? */
1253 if (p + namelen < p || p + namelen > pdata_end) {
1254 return pdata_end - base;
1255 }
1256 ret = clistr_pull_talloc(ctx, cli->inbuf, &fname, p,
1257 namelen, 0);
1258 if (ret == (size_t)-1) {
1259 return pdata_end - base;
1260 }
1261 strncat(finfo->fname, fname, sizeof(finfo->fname) -1);
1262
1263 /* To be robust in the face of unicode conversion failures
1264 we need to copy the raw bytes of the last name seen here.
1265 Namelen doesn't include the terminating unicode null, so
1266 copy it here. */
1267#if 0
1268 if (p_last_name_raw) {
1269 *p_last_name_raw = data_blob(NULL, namelen+2);
1270 memcpy(p_last_name_raw->data, p, namelen);
1271 SSVAL(p_last_name_raw->data, namelen, 0);
1272 }
1273#endif
1274 return calc_next_entry_offset(base, pdata_end);
1275 }
1276 }
1277
1278 debuglocal(1,"Unknown long filename format %d\n",level);
1279 return calc_next_entry_offset(base, pdata_end);
1280}
1281
1282/****************************************************************************
1283 Do a directory listing, calling fn on each file found.
1284 Modified from cli_list_new
1285****************************************************************************/
1286
1287static int list_files(struct cli_state *cli, const char *Mask, uint16 attribute,
1288 void (*fn)(const char*, smbwrp_fileinfo *, const char *, void *), void *state)
1289{
1290#if 1
1291 int max_matches = 1366; /* Match W2k - was 512. */
1292#else
1293 int max_matches = 512;
1294#endif
1295 int info_level;
1296 char *p, *p2, *rdata_end;
1297 char *mask=NULL;
1298 smbwrp_fileinfo finfo;
1299 int i;
1300 char *dirlist = NULL;
1301 int dirlist_len = 0;
1302 int total_received = -1;
1303 bool First = True;
1304 int ff_searchcount=0;
1305 int ff_eos=0;
1306 int ff_dir_handle=0;
1307 int loop_count = 0;
1308 char *rparam=NULL, *rdata=NULL;
1309 unsigned int param_len, data_len;
1310 uint16 setup;
1311 char *param;
1312 uint32 resume_key = 0;
1313 TALLOC_CTX *frame = talloc_stackframe();
1314 DATA_BLOB last_name_raw = data_blob(NULL, 0);
1315
1316 /* NT uses SMB_FIND_FILE_BOTH_DIRECTORY_INFO,
1317 OS/2 uses SMB_FIND_EA_SIZE. Both accept SMB_FIND_INFO_STANDARD. */
1318 info_level = (cli->capabilities&CAP_NT_SMBS)?
1319 SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_EA_SIZE;
1320
1321 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, Mask);
1322
1323 mask = SMB_STRDUP(Mask);
1324 if (!mask) {
1325 TALLOC_FREE(frame);
1326 return -1;
1327 }
1328
1329 /* Try to get the listing from cache. */
1330 if (dircache_list_files(fn, state, &total_received))
1331 {
1332 /* Got from cache. */
1333 return(total_received);
1334 }
1335
1336 while (ff_eos == 0) {
1337 size_t nlen = 2*(strlen(mask)+1);
1338
1339 loop_count++;
1340 if (loop_count > 200) {
1341 debuglocal(0,"Error: Looping in FIND_NEXT??\n");
1342 break;
1343 }
1344
1345 param = SMB_MALLOC_ARRAY(char, 12+nlen+last_name_raw.length+2);
1346 if (!param) {
1347 break;
1348 }
1349
1350 if (First) {
1351 setup = TRANSACT2_FINDFIRST;
1352 SSVAL(param,0,attribute); /* attribute */
1353 SSVAL(param,2,max_matches); /* max count */
1354 SSVAL(param,4,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1355 SSVAL(param,6,info_level);
1356 SIVAL(param,8,0);
1357 p = param+12;
1358 p += clistr_push(cli, param+12, mask, nlen,
1359 STR_TERMINATE);
1360 } else {
1361 setup = TRANSACT2_FINDNEXT;
1362 SSVAL(param,0,ff_dir_handle);
1363 SSVAL(param,2,max_matches); /* max count */
1364 SSVAL(param,4,info_level);
1365 /* For W2K servers serving out FAT filesystems we *must* set the
1366 resume key. If it's not FAT then it's returned as zero. */
1367 SIVAL(param,6,resume_key); /* ff_resume_key */
1368 /* NB. *DON'T* use continue here. If you do it seems that W2K and bretheren
1369 can miss filenames. Use last filename continue instead. JRA */
1370 SSVAL(param,10,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1371 p = param+12;
1372 if (last_name_raw.length) {
1373 memcpy(p, last_name_raw.data, last_name_raw.length);
1374 p += last_name_raw.length;
1375 } else {
1376 p += clistr_push(cli, param+12, mask,
1377 nlen, STR_TERMINATE);
1378 }
1379 }
1380
1381 param_len = PTR_DIFF(p, param);
1382
1383 if (!cli_send_trans(cli, SMBtrans2,
1384 NULL, /* Name */
1385 -1, 0, /* fid, flags */
1386 &setup, 1, 0, /* setup, length, max */
1387 param, param_len, 10, /* param, length, max */
1388 NULL, 0,
1389#if 0
1390 /* w2k value. */
1391 MIN(16384,cli->max_xmit) /* data, length, max. */
1392#else
1393 cli->max_xmit /* data, length, max. */
1394#endif
1395 )) {
1396 SAFE_FREE(param);
1397 TALLOC_FREE(frame);
1398 break;
1399 }
1400
1401 SAFE_FREE(param);
1402
1403 if (!cli_receive_trans(cli, SMBtrans2,
1404 &rparam, &param_len,
1405 &rdata, &data_len) &&
1406 cli_is_dos_error(cli)) {
1407 /* we need to work around a Win95 bug - sometimes
1408 it gives ERRSRV/ERRerror temprarily */
1409 uint8 eclass;
1410 uint32 ecode;
1411
1412 SAFE_FREE(rdata);
1413 SAFE_FREE(rparam);
1414
1415 cli_dos_error(cli, &eclass, &ecode);
1416
1417 /*
1418 * OS/2 might return "no more files",
1419 * which just tells us, that searchcount is zero
1420 * in this search.
1421 * Guenter Kukkukk <linux@kukkukk.com>
1422 */
1423
1424 if (eclass == ERRDOS && ecode == ERRnofiles) {
1425 ff_searchcount = 0;
1426 cli_reset_error(cli);
1427 break;
1428 }
1429
1430 if (eclass != ERRSRV || ecode != ERRerror)
1431 break;
1432 smb_msleep(100);
1433 continue;
1434 }
1435
1436 if (cli_is_error(cli) || !rdata || !rparam)
1437 {
1438 if (First && info_level == SMB_FIND_EA_SIZE)
1439 {
1440 // we have tried query ea size, but now will try without ea size
1441 info_level = SMB_FIND_INFO_STANDARD;
1442 debuglocal(4,"list_files fallback to level %d\n", info_level);
1443 continue;
1444 }
1445 SAFE_FREE(rdata);
1446 SAFE_FREE(rparam);
1447 break;
1448 }
1449
1450 if (total_received == -1)
1451 total_received = 0;
1452
1453 /* parse out some important return info */
1454 p = rparam;
1455 if (First) {
1456 ff_dir_handle = SVAL(p,0);
1457 ff_searchcount = SVAL(p,2);
1458 ff_eos = SVAL(p,4);
1459 } else {
1460 ff_searchcount = SVAL(p,0);
1461 ff_eos = SVAL(p,2);
1462 }
1463 debuglocal(4,"list_files %d %d %d %d\n", ff_searchcount, ff_eos, "(ff_lastname)", First);
1464
1465 if (ff_searchcount == 0) {
1466 SAFE_FREE(rdata);
1467 SAFE_FREE(rparam);
1468 break;
1469 }
1470
1471 /* point to the data bytes */
1472 p = rdata;
1473 rdata_end = rdata + data_len;
1474
1475 memset(&finfo, 0, sizeof(finfo));
1476 finfo.easize = -1;
1477 /* we might need the lastname for continuations */
1478 for (p2=p,i=0;i<ff_searchcount && p2 < rdata_end;i++) {
1479 if ((info_level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) &&
1480 (i == ff_searchcount-1)) {
1481 /* Last entry - fixup the last offset length. */
1482 SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2));
1483 }
1484 p2 += _os2_interpret_long_filename(frame, cli, info_level, p2, rdata_end, &finfo,
1485 &resume_key, &last_name_raw);
1486
1487 if (!finfo.fname) {
1488 debuglocal(0,"Error: unable to parse name from info level %d\n",
1489 info_level);
1490 ff_eos = 1;
1491 break;
1492 }
1493
1494 if (!First && *mask && strcsequal(finfo.fname, mask)) {
1495 debuglocal(0,"Error: Looping in FIND_NEXT as name %s has already been seen?\n",
1496 finfo.fname);
1497 ff_eos = 1;
1498 break;
1499 }
1500 }
1501
1502 SAFE_FREE(mask);
1503 if (ff_searchcount > 0 && ff_eos == 0 && finfo.fname) {
1504 mask = SMB_STRDUP(finfo.fname);
1505 } else {
1506 mask = SMB_STRDUP("");
1507 }
1508 if (!mask) {
1509 SAFE_FREE(rdata);
1510 SAFE_FREE(rparam);
1511 break;
1512 }
1513
1514 /* grab the data for later use */
1515 /* and add them to the dirlist pool */
1516 dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len);
1517
1518 if (!dirlist) {
1519 debuglocal(0,"cli_list_new: Failed to expand dirlist\n");
1520 SAFE_FREE(rdata);
1521 SAFE_FREE(rparam);
1522 break;
1523 }
1524
1525 memcpy(dirlist+dirlist_len,p,data_len);
1526 dirlist_len += data_len;
1527
1528 total_received += ff_searchcount;
1529
1530 SAFE_FREE(rdata);
1531 SAFE_FREE(rparam);
1532
1533 debuglocal(3,"received %d entries (eos=%d)\n",
1534 ff_searchcount,ff_eos);
1535
1536 if (ff_searchcount > 0)
1537 loop_count = 0;
1538
1539 First = False;
1540 }
1541
1542 /* see if the server disconnected or the connection otherwise failed */
1543 if (cli_is_error(cli)) {
1544 total_received = -1;
1545 } else {
1546 void *dircachectx = dircache_write_begin(state, total_received);
1547
1548 /* no connection problem. let user function add each entry */
1549 rdata_end = dirlist + dirlist_len;
1550 for (p=dirlist,i=0;i<total_received;i++) {
1551 p += _os2_interpret_long_filename(frame, cli, info_level, p, rdata_end,
1552 &finfo,NULL,NULL);
1553
1554 if (!finfo.fname) {
1555 debuglocal(0,"list_new: unable to parse name from info level %d\n",
1556 info_level);
1557 break;
1558 }
1559 fn(cli->dfs_mountpoint,&finfo, Mask, state );
1560
1561 /* Also add the entry to the cache. */
1562 dircache_write_entry(dircachectx, &finfo);
1563 }
1564
1565 dircache_write_end(dircachectx);
1566
1567 }
1568
1569 /* free up the dirlist buffer and last name raw blob */
1570 SAFE_FREE(dirlist);
1571 data_blob_free(&last_name_raw);
1572 SAFE_FREE(mask);
1573 TALLOC_FREE(frame);
1574 return(total_received);
1575}
1576
1577
1578/*****************************************************
1579open a directory on the server
1580*******************************************************/
1581int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1582{
1583 if (!srv || !cli || !state || !*state->mask)
1584 {
1585 return maperror(EINVAL);
1586 }
1587 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);
1588 if (*srv->workgroup == 0 && *srv->server_name == 0)
1589 {
1590 smbwrp_special_add(".", state);
1591 smbwrp_special_add("..", state);
1592 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1593 smbwrp_share_add, state);
1594 } else
1595 if (*srv->server_name == 0)
1596 {
1597 smbwrp_special_add(".", state);
1598 smbwrp_special_add("..", state);
1599
1600 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1601 smbwrp_share_add, state);
1602 } else
1603 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1604 {
1605 smbwrp_special_add(".", state);
1606 smbwrp_special_add("..", state);
1607
1608 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1609 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1610 {
1611 return os2cli_errno(cli);
1612 }
1613 } else
1614 if (strncmp(cli->dev,"LPT",3) == 0)
1615 {
1616 smbwrp_special_add(".", state);
1617 smbwrp_special_add("..", state);
1618 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1619 {
1620 return os2cli_errno(cli);
1621 }
1622 }
1623 else
1624 {
1625#if 0
1626 if (strcmp(path,"\\") == 0) {
1627 smbwrp_special_add(".", state);
1628 smbwrp_special_add("..", state);
1629 }
1630#endif
1631#if 0
1632 if (cli_list(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1633 smbwrp_dir_add_old, state) < 0)
1634#else
1635 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1636 smbwrp_dir_add, state) < 0)
1637#endif
1638 {
1639 return os2cli_errno(cli);
1640 }
1641 }
1642
1643 return 0;
1644}
1645
1646/*****************************************************
1647a wrapper for chdir()
1648*******************************************************/
1649int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1650{
1651 unsigned short mode = aDIR;
1652 smbwrp_fileinfo finfo = {0};
1653 if (!cli || !fname)
1654 {
1655 return maperror(EINVAL);
1656 }
1657
1658 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1659 if (smbwrp_getattr(srv, cli, &finfo))
1660 {
1661 return os2cli_errno(cli);
1662 }
1663
1664 if (!(finfo.attr & aDIR)) {
1665 return maperror(ENOTDIR);
1666 }
1667
1668 return 0;
1669}
1670
1671
1672/*****************************************************
1673a wrapper for mkdir()
1674*******************************************************/
1675int _System smbwrp_mkdir(cli_state * cli, char *fname)
1676{
1677 if (!cli || !fname)
1678 {
1679 return maperror(EINVAL);
1680 }
1681
1682 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname)))
1683 {
1684 return os2cli_errno(cli);
1685 }
1686 return 0;
1687}
1688
1689/*****************************************************
1690a wrapper for rmdir()
1691*******************************************************/
1692int _System smbwrp_rmdir(cli_state * cli, char *fname)
1693{
1694 if (!cli || !fname)
1695 {
1696 return maperror(EINVAL);
1697 }
1698
1699 if (!NT_STATUS_IS_OK(cli_rmdir(cli, fname)))
1700 {
1701 return os2cli_errno(cli);
1702 }
1703 return 0;
1704}
1705
1706/*****************************************************
1707set EA for a path
1708*******************************************************/
1709int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1710{
1711 if (!cli || !fname || !name)
1712 {
1713 return maperror(EINVAL);
1714 }
1715 if (!cli_set_ea_path(cli, fname, name, value, size))
1716 {
1717 return os2cli_errno(cli);
1718 }
1719 return 0;
1720}
1721
1722/*****************************************************
1723set EA for a file
1724*******************************************************/
1725int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1726{
1727 if (!cli || !file || !name)
1728 {
1729 return maperror(EINVAL);
1730 }
1731 if (!cli_set_ea_fnum(cli, file->fd, name, value, size))
1732 {
1733 return os2cli_errno(cli);
1734 }
1735 return 0;
1736}
1737
1738
1739#pragma pack(1)
1740typedef struct _FEA /* fea */
1741{
1742 unsigned char fEA; /* flags */
1743 unsigned char cbName; /* name length not including NULL */
1744 unsigned short cbValue; /* value length */
1745} FEA;
1746
1747typedef struct _FEALIST /* feal */
1748{
1749 unsigned long cbList; /* total bytes of structure including full list */
1750 FEA list[1]; /* variable length FEA structures */
1751} FEALIST;
1752#pragma pack()
1753
1754static int unilistea(cli_state * cli, char *fname, smbwrp_file *file, void * buffer, unsigned long size)
1755{
1756 int fnum, i;
1757 int gotsize = sizeof(unsigned long);
1758 size_t num_eas;
1759 struct ea_struct *ea_list = NULL;
1760 TALLOC_CTX *mem_ctx;
1761 FEA * p;
1762 FEALIST * pfealist;
1763 char * q;
1764
1765 mem_ctx = talloc_init("%d: ealist", _gettid());
1766 pfealist = (FEALIST *)buffer;
1767 pfealist->cbList = 0;
1768
1769 if (file)
1770 {
1771 if (!cli_get_ea_list_fnum(cli, file->fd, mem_ctx, &num_eas, &ea_list))
1772 {
1773 debuglocal(4,"ea_get_fnum list failed - %s\n", cli_errstr(cli));
1774 talloc_destroy(mem_ctx);
1775 return os2cli_errno(cli);
1776 }
1777 }
1778 else
1779 {
1780 if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list))
1781 {
1782 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1783 talloc_destroy(mem_ctx);
1784 return os2cli_errno(cli);
1785 }
1786 }
1787
1788 debuglocal(4,"num_eas = %d\n", num_eas);
1789
1790 // we will count that os/2 max EA size for file is 64kb
1791 p = pfealist->list;
1792 for (i = 0; i < num_eas; i++)
1793 {
1794 int namelen = strlen(ea_list[i].name);
1795 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);
1796 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1797 {
1798 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1799 continue;
1800 }
1801 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1802 if (size >= gotsize)
1803 {
1804 p->fEA = 0;
1805 p->cbName = namelen;
1806 p->cbValue = ea_list[i].value.length;
1807 q = (char *)(p + 1);
1808 strncpy(q, ea_list[i].name, namelen + 1);
1809 q += namelen + 1;
1810 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1811 p = (FEA *)(q + ea_list[i].value.length);
1812 }
1813 }
1814 pfealist->cbList = gotsize;
1815 debuglocal(4,"ret size = %d\n", gotsize);
1816
1817 talloc_destroy(mem_ctx);
1818 return 0;
1819}
1820
1821/*****************************************************
1822lists EA of a path
1823*******************************************************/
1824int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1825{
1826 if (!cli || !fname || !buffer)
1827 {
1828 return maperror(EINVAL);
1829 }
1830
1831 debuglocal(4,"EALIst for <%s>\n", fname);
1832 return unilistea(cli, fname, NULL, buffer, size);
1833}
1834
1835/*****************************************************
1836lists EA of a file
1837*******************************************************/
1838int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1839{
1840 if (!cli || !file || !buffer)
1841 {
1842 return maperror(EINVAL);
1843 }
1844
1845 debuglocal(4,"FEALIst for <%s>/%d\n", file->fname, file->fd);
1846 return unilistea(cli, NULL, file, buffer, size);
1847}
1848
1849/****************************************************************************
1850Check the space on a device.
1851****************************************************************************/
1852int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1853{
1854 int total, bsize, avail;
1855
1856 if (!cli || !pfsa)
1857 {
1858 return maperror(EINVAL);
1859 }
1860
1861 if (!NT_STATUS_IS_OK(cli_dskattr(cli, &bsize, &total, &avail)))
1862 {
1863 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1864 return os2cli_errno(cli);
1865 }
1866
1867 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1868 total, bsize, avail);
1869
1870 // YD currently Samba return it in MB!
1871 pfsa->cSectorUnit = 1;
1872 if (bsize >= 65536)
1873 {
1874 pfsa->cUnit = total*1024;
1875 pfsa->cUnitAvail = avail*1024;
1876 pfsa->cbSector = bsize/1024;
1877 }
1878 else
1879 {
1880 pfsa->cUnit = total;
1881 pfsa->cUnitAvail = avail;
1882 pfsa->cbSector = bsize;
1883 }
1884
1885 return 0;
1886}
1887
Note: See TracBrowser for help on using the repository browser.