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

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

client 1.5: samba logging part 2

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