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

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

samba client 1.5: removed duplicated include

  • Property svn:eol-style set to native
File size: 45.4 KB
Line 
1/*
2 Netdrive Samba client plugin
3 samba library wrappers
4 Copyright (C) netlabs.org 2003-2008
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include "includes.h"
22#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 t = get_time_zone(file->mtime);
594 debuglocal(4,"cli_open mtime %lu %lu\n", file->mtime, t);
595 file->mtime -= t;
596 }
597 file->offset = 0;
598 return 0;
599}
600
601/*****************************************************
602a wrapper for read()
603*******************************************************/
604int _System smbwrp_read(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
605{
606 int ret;
607
608 if (!cli || !file || !buf || !result)
609 {
610 return EINVAL;
611 }
612
613 *result = 0;
614 ret = cli_read(cli, file->fd, buf, file->offset, count);
615 if (ret == -1)
616 {
617 return os2cli_errno(cli);
618 }
619
620 file->offset += ret;
621 *result = ret;
622 return 0;
623}
624
625
626
627/*****************************************************
628a wrapper for write()
629*******************************************************/
630int _System smbwrp_write(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
631{
632 int ret;
633
634 if (!cli || !file || !buf || !result)
635 {
636 return EINVAL;
637 }
638
639 *result = 0;
640//debuglocal(1,("Write %x %d %lld %d", cli, file->fd, file->offset, count));
641 ret = cli_write(cli, file->fd, 0, buf, file->offset, count);
642 if (ret == -1)
643 {
644 return os2cli_errno(cli);
645 }
646
647 file->offset += ret;
648 *result = ret;
649 return 0;
650}
651
652/*****************************************************
653a wrapper for close()
654*******************************************************/
655int _System smbwrp_close(cli_state * cli, smbwrp_file * file)
656{
657 int rc = 0;
658 if (!cli || !file)
659 {
660 return EINVAL;
661 }
662
663
664 if (!cli_close(cli, file->fd))
665 {
666 return os2cli_errno(cli);
667 }
668 file->fd = -1;
669 file->offset = 0;
670 if (file->openattr || file->mtime)
671 {
672 debuglocal(4,"Set attr on close %s %08x %d %d\n", file->fname, file->openattr, file->mtime, file->mtime);
673 if (!cli_setatr(cli, file->fname, file->openattr, file->mtime))
674 {
675 debuglocal(4,"Set attr on close failed %d\n", os2cli_errno(cli));
676 //rc = os2cli_errno(cli);
677 }
678 file->openattr = 0;
679 file->mtime = 0;
680 }
681 *file->fname = 0;
682 return rc;
683}
684
685/*****************************************************
686a wrapper for setfilesize()
687*******************************************************/
688int cli_setfilenewsize(struct cli_state *cli, int fnum, off_t newsize)
689{
690 unsigned int data_len = 8;
691 unsigned int param_len = 6;
692 uint16 setup = TRANSACT2_SETFILEINFO;
693 pstring param;
694 char *rparam=NULL, *rdata=NULL;
695
696 memset(param, 0, param_len);
697 SSVAL(param,0,fnum);
698 SSVAL(param,2,SMB_SET_FILE_END_OF_FILE_INFO);
699
700 if (!cli_send_trans(cli, SMBtrans2,
701 NULL, /* name */
702 -1, 0, /* fid, flags */
703 &setup, 1, 0, /* setup, length, max */
704 param, param_len, 2, /* param, length, max */
705 (char *)&newsize, sizeof(newsize), cli->max_xmit /* data, length, max */
706 )) {
707 return False;
708 }
709
710 if (!cli_receive_trans(cli, SMBtrans2,
711 &rparam, &param_len,
712 &rdata, &data_len)) {
713 return False;
714 }
715
716 SAFE_FREE(rdata);
717 SAFE_FREE(rparam);
718
719 return True;
720}
721
722int _System smbwrp_setfilesize(cli_state * cli, smbwrp_file * file, long long newsize)
723{
724 int rc = 0;
725 if (!cli || !file)
726 {
727 return EINVAL;
728 }
729
730 debuglocal(4,"cli_setnewfileszie(%s) %lld\n", file->fname, newsize);
731 if (!cli_setfilenewsize(cli, file->fd, newsize))
732 {
733 if (newsize)
734 {
735 rc = os2cli_errno(cli);
736 }
737
738 if (!cli_close(cli, file->fd))
739 {
740 return os2cli_errno(cli);
741 }
742 file->fd = -1;
743 file->offset = 0;
744 file->openmode &= ~(O_CREAT | O_EXCL);
745 file->openmode |= O_TRUNC;
746 debuglocal(4,"cli_setnewfileszie : cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
747 file->fd = cli_open(cli, file->fname, file->openmode, file->denymode);
748 if (file->fd == -1)
749 {
750 return os2cli_errno(cli);
751 }
752 }
753 return 0;
754}
755
756/*****************************************************
757a wrapper for rename()
758*******************************************************/
759int _System smbwrp_rename(cli_state * cli, char *oldname, char *newname)
760{
761 if (!cli || !oldname || !newname)
762 {
763 return EINVAL;
764 }
765
766 debuglocal(1,"Rename <%s> -> <%s>\n", oldname, newname);
767 //cli_unlink(cli, newname);
768// if (!cli_rename(cli, oldname, newname) && !cli_ntrename(cli, oldname, newname))
769 if (!cli_rename(cli, oldname, newname))
770 {
771 return os2cli_errno(cli);
772 }
773 return 0;
774}
775
776
777/*****************************************************
778a wrapper for chmod()
779*******************************************************/
780int _System smbwrp_setattr(cli_state * cli, smbwrp_fileinfo *finfo)
781{
782 if (!cli || !finfo || !*finfo->fname)
783 {
784 return EINVAL;
785 }
786
787debuglocal(4,"Setting on <%s> attr %04x, time %lu/%lu\n", finfo->fname, finfo->attr, finfo->mtime, finfo->mtime + get_time_zone(finfo->mtime));
788 if (!cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime + (finfo->mtime == 0 ? 0 : get_time_zone(finfo->mtime)))
789 && !cli_setatr(cli, finfo->fname, finfo->attr, 0))
790 {
791 return os2cli_errno(cli);
792 }
793 return 0;
794}
795
796/*****************************************************
797a wrapper for unlink()
798*******************************************************/
799int _System smbwrp_unlink(cli_state * cli, const char *fname)
800{
801 if (!cli || !fname)
802 {
803 return EINVAL;
804 }
805#if 0
806 if (strncmp(cli->dev, "LPT", 3) == 0)
807 {
808 int job = smbw_stat_printjob(cli, fname, NULL, NULL);
809 if (job == -1)
810 {
811 goto failed;
812 }
813 if (cli_printjob_del(cli, job) != 0)
814 {
815 goto failed;
816 }
817 } else
818#endif
819 if (!cli_unlink(cli, fname))
820 {
821 return os2cli_errno(cli);
822 }
823 return 0;
824}
825
826/*****************************************************
827a wrapper for lseek()
828*******************************************************/
829int _System smbwrp_lseek(cli_state * cli, smbwrp_file * file, int whence, long long offset)
830{
831 off_t size;
832 if (!cli || !file)
833 {
834 return EINVAL;
835 }
836
837 debuglocal(4,"lseek %d %lld %lld\n", whence, offset, file->offset);
838
839 switch (whence) {
840 case SEEK_SET:
841 if (offset < 0)
842 {
843 return EINVAL;
844 }
845 file->offset = offset;
846 break;
847 case SEEK_CUR:
848 file->offset += offset;
849 break;
850 case SEEK_END:
851 if (offset > 0)
852 {
853 return EINVAL;
854 }
855 if (!cli_qfileinfo3(cli, file->fd,
856 NULL, &size, NULL, NULL, NULL,
857 NULL, NULL) &&
858 !cli_getattrE(cli, file->fd,
859 NULL, (SMB_BIG_UINT *)&size, NULL, NULL, NULL))
860 {
861 return os2cli_errno(cli);
862 }
863 file->offset = size + offset;
864 break;
865 default: return EINVAL;
866 }
867
868 return 0;
869}
870
871/*****************************************************
872try to do a QPATHINFO and if that fails then do a getatr
873this is needed because win95 sometimes refuses the qpathinfo
874*******************************************************/
875int _System smbwrp_getattr(smbwrp_server *srv, cli_state * cli, smbwrp_fileinfo *finfo)
876{
877 SMB_INO_T ino = 0;
878 if (!cli || !finfo || !*finfo->fname)
879 {
880 return EINVAL;
881 }
882 debuglocal(4,"getattr %d %d <%s>\n", cli->capabilities & CAP_NOPATHINFO2, cli->capabilities & CAP_NT_SMBS, finfo->fname);
883 if (!(cli->capabilities & CAP_NOPATHINFO2) &&
884 cli_qpathinfo3(cli, finfo->fname, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,
885 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino))
886 {
887 finfo->attr &= 0x7F;
888//debuglocal(2,("gotattr %08x <%s>\n", finfo->attr, finfo->fname));
889// finfo->ctime -= get_time_zone(finfo->ctime);
890// finfo->atime -= get_time_zone(finfo->atime);
891// finfo->mtime -= get_time_zone(finfo->mtime);
892 return 0;
893 }
894//debuglocal(2,("getattr rc1 %d\n", os2cli_errno(cli)));
895
896 /* If the path is not on a share (it is a workgroup or a server),
897 * then cli_qpathinfo3 obviously fails. Return some fake information
898 * about the directory.
899 */
900 if ( *srv->server_name == 0
901 || (strcmp(cli->dev,"IPC") == 0)
902 || *srv->share_name == 0
903 || (stricmp(srv->share_name,"IPC$") == 0)
904 || (strncmp(cli->dev,"LPT",3) == 0)
905 )
906 {
907 debuglocal(4,"getattr not a share.\n");
908 *(time_t *)&finfo->ctime = time (NULL);
909 *(time_t *)&finfo->atime = time (NULL);
910 *(time_t *)&finfo->mtime = time (NULL);
911 finfo->size = 0;
912 finfo->easize = 0;
913 finfo->attr = aDIR;
914 return 0;
915 }
916
917 /* if this is NT then don't bother with the getatr */
918 if (cli->capabilities & CAP_NT_SMBS && !(cli->capabilities & CAP_NOPATHINFO2))
919 {
920 int rc = os2cli_errno(cli);
921 // cli_qpathinfo* reports EINVAL when path of given file not exists
922 // thus there is no real situation when EINVAL should be returned to
923 // client at this point, we just replace it to ENOTDIR
924 if (rc == EINVAL)
925 {
926 rc = ENOTDIR;
927 }
928 return rc;
929 }
930
931 if (cli_getatr(cli, finfo->fname, (unsigned short *)&finfo->attr, &finfo->size, (time_t *)&finfo->mtime))
932 {
933//debuglocal(2,("gotattr1 %08x <%s>\n", finfo->attr, finfo->fname));
934 finfo->mtime -= get_time_zone(finfo->mtime);
935 finfo->atime = finfo->atime; //was mtime
936 finfo->ctime = finfo->ctime; //was mtime
937 cli->capabilities &= CAP_NOPATHINFO2;
938 return 0;
939 }
940 return os2cli_errno(cli);
941}
942
943/*****************************************************
944try to do a QPATHINFO and if that fails then do a getatr
945this is needed because win95 sometimes refuses the qpathinfo
946*******************************************************/
947int _System smbwrp_fgetattr(cli_state * cli, smbwrp_file *file, smbwrp_fileinfo *finfo)
948{
949 SMB_INO_T ino = 0;
950 if (!cli || !file || !finfo)
951 {
952 return EINVAL;
953 }
954
955 strncpy(finfo->fname, file->fname, sizeof(finfo->fname) - 1);
956 if (!cli_qfileinfo3(cli, file->fd,
957 (unsigned short *)&finfo->attr, (off_t *)&finfo->size, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,
958 &ino))
959 {
960 if (!cli_getattrE(cli, file->fd,
961 (unsigned short *)&finfo->attr, (SMB_BIG_UINT *)(&finfo->size), (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime))
962 {
963 return os2cli_errno(cli);
964 }
965 else
966 {
967 finfo->ctime -= get_time_zone(finfo->ctime);
968 finfo->atime -= get_time_zone(finfo->atime);
969 finfo->mtime -= get_time_zone(finfo->mtime);
970 }
971 }
972 else
973 {
974// finfo->ctime -= get_time_zone(finfo->ctime);
975// finfo->atime -= get_time_zone(finfo->atime);
976// finfo->mtime -= get_time_zone(finfo->mtime);
977 }
978
979 return 0;
980}
981
982// =============================DIRECTORY ROUTINES============================
983
984/*****************************************************
985add a entry to a directory listing
986*******************************************************/
987static void smbwrp_dir_add(const char* mnt, smbwrp_fileinfo *finfo, const char *mask, void *state)
988{
989 if (state && finfo)
990 {
991 filelist_state * st = (filelist_state *)state;
992 char fullname[ _MAX_PATH];
993 debuglocal(8,"adding <%s> %d %d\n", finfo->fname, sizeof(st->finfo), st->datalen);
994 memcpy(&st->finfo, finfo, sizeof(st->finfo));
995 StrCpy(fullname, st->dir);
996 StrCat(fullname, finfo->fname);
997 StrCpy(st->finfo.fname, fullname);
998 getfindinfoL( st->pConn, st->plist, &st->finfo, st->ulAttribute, st->dir_mask);
999 }
1000}
1001
1002static void smbwrp_special_add(const char * name, void * state)
1003{
1004 smbwrp_fileinfo finfo = {0};
1005
1006 if (!name)
1007 {
1008 return;
1009 }
1010
1011 ZERO_STRUCT(finfo);
1012
1013 strncpy(finfo.fname, name, sizeof(finfo.fname) - 1);
1014 finfo.attr = aRONLY | aDIR;
1015
1016 smbwrp_dir_add("", &finfo, NULL, state);
1017}
1018
1019static void smbwrp_printjob_add(struct print_job_info *job, void * state)
1020{
1021 smbwrp_fileinfo finfo = {0};
1022
1023 ZERO_STRUCT(finfo);
1024
1025//printf("Printjob <%s>\n", job->name);
1026
1027 strncpy(finfo.fname, job->name, sizeof(finfo.fname) - 1);
1028 finfo.mtime = job->t - get_time_zone(job->t);
1029 finfo.atime = finfo.atime; //was mtime
1030 finfo.ctime = finfo.ctime; //was mtime
1031 finfo.attr = aRONLY;
1032 finfo.size = job->size;
1033
1034 smbwrp_dir_add("", &finfo, NULL, state);
1035}
1036
1037static void smbwrp_share_add(const char *share, uint32 type,
1038 const char *comment, void *state)
1039{
1040 smbwrp_fileinfo finfo = {0};
1041
1042 // strip administrative names and printers from list
1043 if (type == STYPE_PRINTQ || strcmp(share,"IPC$") == 0) return;
1044
1045 ZERO_STRUCT(finfo);
1046
1047 strncpy(finfo.fname, share, sizeof(finfo.fname) - 1);
1048 finfo.attr = aRONLY | aDIR;
1049
1050 smbwrp_dir_add("", &finfo, NULL, state);
1051}
1052
1053/****************************************************************************
1054 Interpret a long filename structure - this is mostly guesses at the moment.
1055 The length of the structure is returned
1056 The structure of a long filename depends on the info level. 260 is used
1057 by NT and 2 is used by OS/2
1058****************************************************************************/
1059// YD from libsmb\clilist.c
1060static size_t _os2_interpret_long_filename(struct cli_state *cli,
1061 int level,char *p, smbwrp_fileinfo *finfo,
1062 uint32 *p_resume_key, DATA_BLOB *p_last_name_raw, uint32 *p_last_name_raw_len)
1063{
1064 extern file_info def_finfo;
1065 int len;
1066 char *base = p;
1067 smbwrp_fileinfo finfo1;
1068
1069 if (!finfo) finfo = &finfo1;
1070
1071 if (p_resume_key) {
1072 *p_resume_key = 0;
1073 }
1074
1075 finfo->attr = def_finfo.mode;
1076 finfo->mtime = def_finfo.mtime_ts.tv_sec;
1077 finfo->atime = def_finfo.atime_ts.tv_sec;
1078 finfo->ctime = def_finfo.ctime_ts.tv_sec;
1079 strncpy(finfo->fname, def_finfo.name, sizeof(finfo->fname) - 1);
1080 debuglocal(9,"fname %s (serverzone %d, level %d)\n",finfo->fname, cli->serverzone, level);
1081
1082 switch (level) {
1083 case 1: /* OS/2 understands this */
1084 /* these dates are converted to GMT by
1085 make_unix_date */
1086 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1087 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1088 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1089 finfo->size = IVAL(p,16);
1090 finfo->attr = CVAL(p,24);
1091 len = CVAL(p, 26);
1092 p += 27;
1093 p += clistr_align_in(cli, p, 0);
1094 /* the len+2 below looks strange but it is
1095 important to cope with the differences
1096 between win2000 and win9x for this call
1097 (tridge) */
1098 p += clistr_pull(cli, finfo->fname, p,
1099 sizeof(finfo->fname),
1100 len+2,
1101 STR_TERMINATE);
1102 finfo->easize = -1;
1103 return PTR_DIFF(p, base);
1104
1105 case 2: /* this is what OS/2 uses mostly */
1106 /* these dates are converted to GMT by
1107 make_unix_date */
1108 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1109 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1110 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1111 finfo->size = IVAL(p,16);
1112 finfo->attr = CVAL(p,24);
1113 finfo->easize = IVAL(p,26);
1114 len = CVAL(p, 30);
1115 p += 31;
1116 /* check for unisys! */
1117 p += clistr_pull(cli, finfo->fname, p,
1118 sizeof(finfo->fname),
1119 len,
1120 STR_NOALIGN);
1121 return PTR_DIFF(p, base) + 1;
1122
1123 case 260: /* NT uses this, but also accepts 2 */
1124 {
1125 size_t namelen, slen;
1126 p += 4; /* next entry offset */
1127 if (p_resume_key) {
1128 *p_resume_key = IVAL(p,0);
1129 }
1130
1131 p += 4; /* fileindex */
1132
1133 /* Offset zero is "create time", not "change time". */
1134 p += 8;
1135 finfo->atime = interpret_long_date(p).tv_sec;
1136 p += 8;
1137 finfo->mtime = interpret_long_date(p).tv_sec;
1138 p += 8;
1139 finfo->ctime = interpret_long_date(p).tv_sec;
1140 p += 8;
1141 finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0);
1142 p += 8;
1143 p += 8; /* alloc size */
1144 finfo->attr = CVAL(p,0);
1145 p += 4;
1146 namelen = IVAL(p,0);
1147 p += 4;
1148 finfo->easize = IVAL(p,0);
1149 p += 4; /* EA size */
1150 slen = SVAL(p, 0);
1151 p += 2;
1152#if 0
1153 {
1154 /* stupid NT bugs. grr */
1155 int flags = 0;
1156 if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE;
1157 clistr_pull(cli, finfo->short_name, p,
1158 sizeof(finfo->short_name),
1159 slen, flags);
1160 }
1161#endif
1162 p += 24; /* short name? */
1163 clistr_pull(cli, finfo->fname, p,
1164 sizeof(finfo->fname),
1165 namelen, 0);
1166
1167 /* To be robust in the face of unicode conversion failures
1168 we need to copy the raw bytes of the last name seen here.
1169 Namelen doesn't include the terminating unicode null, so
1170 copy it here. */
1171#if 0
1172 if (p_last_name_raw && p_last_name_raw_len) {
1173 if (namelen + 2 > p_last_name_raw->length) {
1174 memset(p_last_name_raw->data, '\0', sizeof(p_last_name_raw->length));
1175 *p_last_name_raw_len = 0;
1176 } else {
1177 memcpy(p_last_name_raw->data, p, namelen);
1178 SSVAL(p_last_name_raw->data, namelen, 0);
1179 *p_last_name_raw_len = namelen + 2;
1180 }
1181 }
1182#endif
1183 return (size_t)IVAL(base, 0);
1184 }
1185 }
1186
1187 debuglocal(1,"Unknown long filename format %d\n",level);
1188 return (size_t)IVAL(base,0);
1189}
1190
1191/****************************************************************************
1192 Do a directory listing, calling fn on each file found.
1193 Modified from cli_list_new
1194****************************************************************************/
1195
1196static int list_files(struct cli_state *cli, const char *Mask, uint16 attribute,
1197 void (*fn)(const char*, smbwrp_fileinfo *, const char *, void *), void *state)
1198{
1199#if 1
1200 int max_matches = 1366; /* Match W2k - was 512. */
1201#else
1202 int max_matches = 512;
1203#endif
1204 int info_level;
1205 char *p, *p2;
1206 pstring mask;
1207 smbwrp_fileinfo finfo;
1208 int i;
1209 char *dirlist = NULL;
1210 int dirlist_len = 0;
1211 int total_received = -1;
1212 BOOL First = True;
1213 int ff_searchcount=0;
1214 int ff_eos=0;
1215 int ff_dir_handle=0;
1216 int loop_count = 0;
1217 char *rparam=NULL, *rdata=NULL;
1218 unsigned int param_len, data_len;
1219 uint16 setup;
1220 pstring param;
1221 const char *mnt;
1222 uint32 resume_key = 0;
1223 uint32 last_name_raw_len = 0;
1224 DATA_BLOB last_name_raw = data_blob(NULL, 2*sizeof(pstring));
1225
1226 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1227 info_level = (cli->capabilities&CAP_NT_SMBS)?260:2;
1228
1229 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, mask);
1230
1231 /* when getting a directory listing from a 2k dfs root share,
1232 we have to include the full path (\server\share\mask) here */
1233
1234 if ( cli->dfsroot )
1235 pstr_sprintf( mask, "\\%s\\%s\\%s", cli->desthost, cli->share, Mask );
1236 else
1237 pstrcpy(mask,Mask);
1238
1239 while (ff_eos == 0) {
1240 loop_count++;
1241 if (loop_count > 200) {
1242 debuglocal(0,"Error: Looping in FIND_NEXT??\n");
1243 break;
1244 }
1245
1246 if (First) {
1247 setup = TRANSACT2_FINDFIRST;
1248 SSVAL(param,0,attribute); /* attribute */
1249 SSVAL(param,2,max_matches); /* max count */
1250 SSVAL(param,4,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1251 SSVAL(param,6,info_level);
1252 SIVAL(param,8,0);
1253 p = param+12;
1254 p += clistr_push(cli, param+12, mask, sizeof(param)-12,
1255 STR_TERMINATE);
1256 } else {
1257 setup = TRANSACT2_FINDNEXT;
1258 SSVAL(param,0,ff_dir_handle);
1259 SSVAL(param,2,max_matches); /* max count */
1260 SSVAL(param,4,info_level);
1261 /* For W2K servers serving out FAT filesystems we *must* set the
1262 resume key. If it's not FAT then it's returned as zero. */
1263 SIVAL(param,6,resume_key); /* ff_resume_key */
1264 /* NB. *DON'T* use continue here. If you do it seems that W2K and bretheren
1265 can miss filenames. Use last filename continue instead. JRA */
1266 SSVAL(param,10,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1267 p = param+12;
1268 if (last_name_raw_len && (last_name_raw_len < (sizeof(param)-12))) {
1269 memcpy(p, last_name_raw.data, last_name_raw_len);
1270 p += last_name_raw_len;
1271 } else {
1272 p += clistr_push(cli, param+12, mask, sizeof(param)-12, STR_TERMINATE);
1273 }
1274 }
1275
1276 param_len = PTR_DIFF(p, param);
1277
1278 if (!cli_send_trans(cli, SMBtrans2,
1279 NULL, /* Name */
1280 -1, 0, /* fid, flags */
1281 &setup, 1, 0, /* setup, length, max */
1282 param, param_len, 10, /* param, length, max */
1283 NULL, 0,
1284#if 0
1285 /* w2k value. */
1286 MIN(16384,cli->max_xmit) /* data, length, max. */
1287#else
1288 cli->max_xmit /* data, length, max. */
1289#endif
1290 )) {
1291 break;
1292 }
1293
1294 if (!cli_receive_trans(cli, SMBtrans2,
1295 &rparam, &param_len,
1296 &rdata, &data_len) &&
1297 cli_is_dos_error(cli)) {
1298 /* we need to work around a Win95 bug - sometimes
1299 it gives ERRSRV/ERRerror temprarily */
1300 uint8 eclass;
1301 uint32 ecode;
1302
1303 SAFE_FREE(rdata);
1304 SAFE_FREE(rparam);
1305
1306 cli_dos_error(cli, &eclass, &ecode);
1307
1308 /*
1309 * OS/2 might return "no more files",
1310 * which just tells us, that searchcount is zero
1311 * in this search.
1312 * Guenter Kukkukk <linux@kukkukk.com>
1313 */
1314
1315 if (eclass == ERRDOS && ecode == ERRnofiles) {
1316 ff_searchcount = 0;
1317 cli_reset_error(cli);
1318 break;
1319 }
1320
1321 if (eclass != ERRSRV || ecode != ERRerror)
1322 break;
1323 smb_msleep(100);
1324 continue;
1325 }
1326
1327 if (cli_is_error(cli) || !rdata || !rparam)
1328 {
1329 if (First && info_level == 2)
1330 {
1331 // we have tried query ea size, but now will try without ea size
1332 info_level = 1;
1333 debuglocal(4,"list_files fallback to level %d\n", info_level);
1334 continue;
1335 }
1336 SAFE_FREE(rdata);
1337 SAFE_FREE(rparam);
1338 break;
1339 }
1340
1341 if (total_received == -1)
1342 total_received = 0;
1343
1344 /* parse out some important return info */
1345 p = rparam;
1346 if (First) {
1347 ff_dir_handle = SVAL(p,0);
1348 ff_searchcount = SVAL(p,2);
1349 ff_eos = SVAL(p,4);
1350 } else {
1351 ff_searchcount = SVAL(p,0);
1352 ff_eos = SVAL(p,2);
1353 }
1354 debuglocal(4,"list_files %d %d %d %d\n", ff_searchcount, ff_eos, "(ff_lastname)", First);
1355
1356 if (ff_searchcount == 0) {
1357 SAFE_FREE(rdata);
1358 SAFE_FREE(rparam);
1359 break;
1360 }
1361
1362 /* point to the data bytes */
1363 p = rdata;
1364
1365 memset(&finfo, 0, sizeof(finfo));
1366 finfo.easize = -1;
1367 /* we might need the lastname for continuations */
1368 for (p2=p,i=0;i<ff_searchcount;i++) {
1369 if ((info_level == 260) && (i == ff_searchcount-1)) {
1370 /* Last entry - fixup the last offset length. */
1371 SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2));
1372 }
1373 p2 += _os2_interpret_long_filename(cli,info_level,p2,&finfo,
1374 &resume_key,&last_name_raw,&last_name_raw_len);
1375
1376 if (!First && *mask && strcsequal(finfo.fname, mask)) {
1377 debuglocal(0,"Error: Looping in FIND_NEXT as name %s has already been seen?\n",
1378 finfo.fname);
1379 ff_eos = 1;
1380 break;
1381 }
1382 }
1383
1384 if (ff_searchcount > 0) {
1385 pstrcpy(mask, finfo.fname);
1386 } else {
1387 pstrcpy(mask,"");
1388 }
1389
1390 /* grab the data for later use */
1391 /* and add them to the dirlist pool */
1392 dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len);
1393
1394 if (!dirlist) {
1395 debuglocal(0,"cli_list_new: Failed to expand dirlist\n");
1396 SAFE_FREE(rdata);
1397 SAFE_FREE(rparam);
1398 break;
1399 }
1400
1401 memcpy(dirlist+dirlist_len,p,data_len);
1402 dirlist_len += data_len;
1403
1404 total_received += ff_searchcount;
1405
1406 SAFE_FREE(rdata);
1407 SAFE_FREE(rparam);
1408
1409 debuglocal(3,"received %d entries (eos=%d)\n",
1410 ff_searchcount,ff_eos);
1411
1412 if (ff_searchcount > 0)
1413 loop_count = 0;
1414
1415 First = False;
1416 }
1417
1418 mnt = cli_cm_get_mntpoint( cli );
1419
1420 /* see if the server disconnected or the connection otherwise failed */
1421 if (cli_is_error(cli)) {
1422 total_received = -1;
1423 } else {
1424 /* no connection problem. let user function add each entry */
1425 for (p=dirlist,i=0;i<total_received;i++) {
1426 p += _os2_interpret_long_filename(cli, info_level, p,
1427 &finfo,NULL,NULL,NULL);
1428 fn( mnt,&finfo, Mask, state );
1429 }
1430 }
1431
1432 /* free up the dirlist buffer and last name raw blob */
1433 SAFE_FREE(dirlist);
1434 data_blob_free(&last_name_raw);
1435 return(total_received);
1436}
1437
1438
1439/*****************************************************
1440open a directory on the server
1441*******************************************************/
1442int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1443{
1444 if (!srv || !cli || !state || !*state->mask)
1445 {
1446 return EINVAL;
1447 }
1448 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);
1449 if (*srv->workgroup == 0 && *srv->server_name == 0)
1450 {
1451 smbwrp_special_add(".", state);
1452 smbwrp_special_add("..", state);
1453 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1454 smbwrp_share_add, state);
1455 } else
1456 if (*srv->server_name == 0)
1457 {
1458 smbwrp_special_add(".", state);
1459 smbwrp_special_add("..", state);
1460
1461 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1462 smbwrp_share_add, state);
1463 } else
1464 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1465 {
1466 smbwrp_special_add(".", state);
1467 smbwrp_special_add("..", state);
1468
1469 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1470 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1471 {
1472 return os2cli_errno(cli);
1473 }
1474 } else
1475 if (strncmp(cli->dev,"LPT",3) == 0)
1476 {
1477 smbwrp_special_add(".", state);
1478 smbwrp_special_add("..", state);
1479 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1480 {
1481 return os2cli_errno(cli);
1482 }
1483 }
1484 else
1485 {
1486#if 0
1487 if (strcmp(path,"\\") == 0) {
1488 smbwrp_special_add(".", state);
1489 smbwrp_special_add("..", state);
1490 }
1491#endif
1492#if 0
1493 if (cli_list(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1494 smbwrp_dir_add_old, state) < 0)
1495#else
1496 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1497 smbwrp_dir_add, state) < 0)
1498#endif
1499 {
1500 return os2cli_errno(cli);
1501 }
1502 }
1503
1504 return 0;
1505}
1506
1507/*****************************************************
1508a wrapper for chdir()
1509*******************************************************/
1510int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1511{
1512 unsigned short mode = aDIR;
1513 smbwrp_fileinfo finfo = {0};
1514 if (!cli || !fname)
1515 {
1516 return EINVAL;
1517 }
1518
1519 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1520 if (smbwrp_getattr(srv, cli, &finfo))
1521 {
1522 return os2cli_errno(cli);
1523 }
1524
1525 if (!(finfo.attr & aDIR)) {
1526 return ENOTDIR;
1527 }
1528
1529 return 0;
1530}
1531
1532
1533/*****************************************************
1534a wrapper for mkdir()
1535*******************************************************/
1536int _System smbwrp_mkdir(cli_state * cli, char *fname)
1537{
1538 if (!cli || !fname)
1539 {
1540 return EINVAL;
1541 }
1542
1543 if (!cli_mkdir(cli, fname))
1544 {
1545 return os2cli_errno(cli);
1546 }
1547 return 0;
1548}
1549
1550/*****************************************************
1551a wrapper for rmdir()
1552*******************************************************/
1553int _System smbwrp_rmdir(cli_state * cli, char *fname)
1554{
1555 if (!cli || !fname)
1556 {
1557 return EINVAL;
1558 }
1559
1560 if (!cli_rmdir(cli, fname))
1561 {
1562 return os2cli_errno(cli);
1563 }
1564 return 0;
1565}
1566
1567/*****************************************************
1568set EA for a path
1569*******************************************************/
1570int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1571{
1572 if (!cli || !fname || !name)
1573 {
1574 return EINVAL;
1575 }
1576 if (!cli_set_ea_path(cli, fname, name, value, size))
1577 {
1578 return os2cli_errno(cli);
1579 }
1580 return 0;
1581}
1582
1583/*****************************************************
1584set EA for a file
1585*******************************************************/
1586int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1587{
1588 if (!cli || !file || !name)
1589 {
1590 return EINVAL;
1591 }
1592 if (!cli_set_ea_fnum(cli, file->fd, name, value, size))
1593 {
1594 return os2cli_errno(cli);
1595 }
1596 return 0;
1597}
1598
1599
1600#pragma pack(1)
1601typedef struct _FEA /* fea */
1602{
1603 unsigned char fEA; /* flags */
1604 unsigned char cbName; /* name length not including NULL */
1605 unsigned short cbValue; /* value length */
1606} FEA;
1607
1608typedef struct _FEALIST /* feal */
1609{
1610 unsigned long cbList; /* total bytes of structure including full list */
1611 FEA list[1]; /* variable length FEA structures */
1612} FEALIST;
1613#pragma pack()
1614
1615static int unilistea(cli_state * cli, char *fname, smbwrp_file *file, void * buffer, unsigned long size)
1616{
1617 int fnum, i;
1618 int gotsize = sizeof(unsigned long);
1619 size_t num_eas;
1620 struct ea_struct *ea_list = NULL;
1621 TALLOC_CTX *mem_ctx;
1622 FEA * p;
1623 FEALIST * pfealist;
1624 char * q;
1625
1626 mem_ctx = talloc_init("%d: ealist", _gettid());
1627 pfealist = (FEALIST *)buffer;
1628 pfealist->cbList = 0;
1629
1630 if (file)
1631 {
1632 if (!cli_get_ea_list_fnum(cli, file->fd, mem_ctx, &num_eas, &ea_list))
1633 {
1634 debuglocal(4,"ea_get_fnum list failed - %s\n", cli_errstr(cli));
1635 talloc_destroy(mem_ctx);
1636 return os2cli_errno(cli);
1637 }
1638 }
1639 else
1640 {
1641 if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list))
1642 {
1643 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1644 talloc_destroy(mem_ctx);
1645 return os2cli_errno(cli);
1646 }
1647 }
1648
1649 debuglocal(4,"num_eas = %d\n", num_eas);
1650
1651 // we will count that os/2 max EA size for file is 64kb
1652 p = pfealist->list;
1653 for (i = 0; i < num_eas; i++)
1654 {
1655 int namelen = strlen(ea_list[i].name);
1656 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);
1657 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1658 {
1659 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1660 continue;
1661 }
1662 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1663 if (size >= gotsize)
1664 {
1665 p->fEA = 0;
1666 p->cbName = namelen;
1667 p->cbValue = ea_list[i].value.length;
1668 q = (char *)(p + 1);
1669 strncpy(q, ea_list[i].name, namelen + 1);
1670 q += namelen + 1;
1671 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1672 p = (FEA *)(q + ea_list[i].value.length);
1673 }
1674 }
1675 pfealist->cbList = gotsize;
1676 debuglocal(4,"ret size = %d\n", gotsize);
1677
1678 talloc_destroy(mem_ctx);
1679 return 0;
1680}
1681
1682/*****************************************************
1683lists EA of a path
1684*******************************************************/
1685int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1686{
1687 if (!cli || !fname || !buffer)
1688 {
1689 return EINVAL;
1690 }
1691
1692 debuglocal(4,"EALIst for <%s>\n", fname);
1693 return unilistea(cli, fname, NULL, buffer, size);
1694}
1695
1696/*****************************************************
1697lists EA of a file
1698*******************************************************/
1699int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1700{
1701 if (!cli || !file || !buffer)
1702 {
1703 return EINVAL;
1704 }
1705
1706 debuglocal(4,"FEALIst for <%s>/%d\n", file->fname, file->fd);
1707 return unilistea(cli, NULL, file, buffer, size);
1708}
1709
1710/****************************************************************************
1711Check the space on a device.
1712****************************************************************************/
1713int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1714{
1715 int total, bsize, avail;
1716
1717 if (!cli || !pfsa)
1718 {
1719 return EINVAL;
1720 }
1721
1722 if (!cli_dskattr(cli, &bsize, &total, &avail))
1723 {
1724 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1725 return os2cli_errno(cli);
1726 }
1727
1728 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1729 total, bsize, avail);
1730
1731 // YD currently Samba return it in MB!
1732 pfsa->cSectorUnit = 1;
1733 if (bsize >= 65536)
1734 {
1735 pfsa->cUnit = total*1024;
1736 pfsa->cUnitAvail = avail*1024;
1737 pfsa->cbSector = bsize/1024;
1738 }
1739 else
1740 {
1741 pfsa->cUnit = total;
1742 pfsa->cUnitAvail = avail;
1743 pfsa->cbSector = bsize;
1744 }
1745
1746 return 0;
1747}
1748
Note: See TracBrowser for help on using the repository browser.