source: branches/client-1.5/src/smbwrp.c@ 437

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

client 1.5: samba logging final version

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