source: branches/client-1.6/src/smbwrp.c@ 297

Last change on this file since 297 was 297, checked in by Silvan Scherrer, 16 years ago

first drop, still some problems

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