source: branches/client-2.0/src/smbwrp.c@ 520

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

Samba Client 2.0: another bunch of updates

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