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

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

client 1.5: samba logging part1

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