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

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

Samba Client 2.0: sigpipe crash, cosmetic and text

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