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

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

Samba Client 2.2: Fix Ticket #227 (wrongly updated time stamps) by _diver

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