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

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

sambaclient 1.5: attemp to fix tz problems fixes ticket:56

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