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

Last change on this file since 187 was 187, checked in by Herwig Bauernfeind, 16 years ago

Fix for Ticket #87 (by diver)

  • Property svn:eol-style set to native
File size: 44.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#ifndef DEBUG_PRINTF
26#define debug_printf( ...)
27#endif
28
29static int
30net_share_enum_rpc(struct cli_state *cli,
31 void (*fn)(const char *name,
32 uint32 type,
33 const char *comment,
34 void *state),
35 void *state)
36{
37 int i;
38 WERROR result;
39 ENUM_HND enum_hnd;
40 uint32 info_level = 1;
41 uint32 preferred_len = 0xffffffff;
42 uint32 type;
43 SRV_SHARE_INFO_CTR ctr;
44 fstring name = "";
45 fstring comment = "";
46 void *mem_ctx;
47 struct rpc_pipe_client *pipe_hnd;
48 NTSTATUS nt_status;
49
50 /* Open the server service pipe */
51 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &nt_status);
52 if (!pipe_hnd) {
53 DEBUG(1, ("net_share_enum_rpc pipe open fail!\n"));
54 return -1;
55 }
56
57 /* Allocate a context for parsing and for the entries in "ctr" */
58 mem_ctx = talloc_init("libsmbclient: net_share_enum_rpc");
59 if (mem_ctx == NULL) {
60 DEBUG(0, ("out of memory for net_share_enum_rpc!\n"));
61 cli_rpc_pipe_close(pipe_hnd);
62 return -1;
63 }
64
65 /* Issue the NetShareEnum RPC call and retrieve the response */
66 init_enum_hnd(&enum_hnd, 0);
67 result = rpccli_srvsvc_net_share_enum(pipe_hnd,
68 mem_ctx,
69 info_level,
70 &ctr,
71 preferred_len,
72 &enum_hnd);
73
74 /* Was it successful? */
75 if (!W_ERROR_IS_OK(result) || ctr.num_entries == 0) {
76 /* Nope. Go clean up. */
77 goto done;
78 }
79
80 /* For each returned entry... */
81 for (i = 0; i < ctr.num_entries; i++) {
82
83 /* pull out the share name */
84 rpcstr_pull_unistr2_fstring(
85 name, &ctr.share.info1[i].info_1_str.uni_netname);
86
87 /* pull out the share's comment */
88 rpcstr_pull_unistr2_fstring(
89 comment, &ctr.share.info1[i].info_1_str.uni_remark);
90
91 /* Get the type value */
92 type = ctr.share.info1[i].info_1.type;
93
94 /* Add this share to the list */
95 (*fn)(name, type, comment, state);
96 }
97
98done:
99 /* Close the server service pipe */
100 cli_rpc_pipe_close(pipe_hnd);
101
102 /* Free all memory which was allocated for this request */
103 TALLOC_FREE(mem_ctx);
104
105 /* Tell 'em if it worked */
106 return W_ERROR_IS_OK(result) ? 0 : -1;
107}
108
109/*
110 * Wrapper for cli_errno to return not connected error on negative fd
111 * Now returns an OS/2 return code instead of lerrno.
112 */
113int os2cli_errno(cli_state * cli)
114{
115 if (cli->fd == -1)
116 {
117 return maperror( ENOTCONN);
118 }
119 return maperror(cli_errno(cli));
120}
121
122int _System smbwrp_getclisize(void)
123{
124 return sizeof(struct cli_state);
125}
126
127/*****************************************************
128initialise structures
129*******************************************************/
130int _System smbwrp_init(void)
131{
132 static int initialised = 0;
133 char *p;
134 pstring line;
135
136 if (initialised)
137 {
138 return 0;
139 }
140 initialised = 1;
141
142 load_case_tables();
143
144 init_globals( True);
145
146 load_interfaces();
147
148 if (!init_names())
149 {
150 return 1;
151 }
152
153/*
154 if ((p=smbw_getshared("RESOLVE_ORDER"))) {
155 lp_set_name_resolve_order(p);
156 }
157*/
158 return 0;
159
160}
161
162#if 0
163/*****************************************************
164remove redundent stuff from a filename
165*******************************************************/
166void clean_fname(char *name)
167{
168 char *p, *p2;
169 int l;
170 int modified = 1;
171
172 if (!name) return;
173
174 while (modified) {
175 modified = 0;
176
177 if ((p=strstr(name,"/./"))) {
178 modified = 1;
179 while (*p) {
180 p[0] = p[2];
181 p++;
182 }
183 }
184
185 if ((p=strstr(name,"//"))) {
186 modified = 1;
187 while (*p) {
188 p[0] = p[1];
189 p++;
190 }
191 }
192
193 if (strcmp(name,"/../")==0) {
194 modified = 1;
195 name[1] = 0;
196 }
197
198 if ((p=strstr(name,"/../"))) {
199 modified = 1;
200 for (p2=(p>name?p-1:p);p2>name;p2--) {
201 if (p2[0] == '/') break;
202 }
203 while (*p2) {
204 p2[0] = p2[3];
205 p2++;
206 }
207 }
208
209 if (strcmp(name,"/..")==0) {
210 modified = 1;
211 name[1] = 0;
212 }
213
214 l = strlen(name);
215 p = l>=3?(name+l-3):name;
216 if (strcmp(p,"/..")==0) {
217 modified = 1;
218 for (p2=p-1;p2>name;p2--) {
219 if (p2[0] == '/') break;
220 }
221 if (p2==name) {
222 p[0] = '/';
223 p[1] = 0;
224 } else {
225 p2[0] = 0;
226 }
227 }
228
229 l = strlen(name);
230 p = l>=2?(name+l-2):name;
231 if (strcmp(p,"/.")==0) {
232 if (p == name) {
233 p[1] = 0;
234 } else {
235 p[0] = 0;
236 }
237 }
238
239 if (strncmp(p=name,"./",2) == 0) {
240 modified = 1;
241 do {
242 p[0] = p[2];
243 } while (*p++);
244 }
245
246 l = strlen(p=name);
247 if (l > 1 && p[l-1] == '/') {
248 modified = 1;
249 p[l-1] = 0;
250 }
251 }
252}
253#endif
254
255
256/****************************************************************************
257send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
258****************************************************************************/
259BOOL cli_qpathinfo3(struct cli_state *cli, const char *fname,
260 time_t *c_time, time_t *a_time, time_t *m_time,
261 time_t *w_time, off_t *size, uint16 *mode,
262 SMB_INO_T *ino)
263{
264 unsigned int data_len = 0;
265 unsigned int param_len = 0;
266 uint16 setup = TRANSACT2_QPATHINFO;
267 pstring param;
268 char *rparam=NULL, *rdata=NULL;
269 char *p;
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, sizeof(pstring)-6, 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 if (!cli_receive_trans(cli, SMBtrans2,
290 &rparam, &param_len,
291 &rdata, &data_len)) {
292 return False;
293 }
294
295 if (!rdata || data_len < 22) {
296 return False;
297 }
298
299 if (c_time) {
300 *c_time = convert_timespec_to_time_t(interpret_long_date(rdata+0));
301 }
302 if (a_time) {
303 *a_time = convert_timespec_to_time_t(interpret_long_date(rdata+8));
304 }
305 if (m_time) {
306 *m_time = convert_timespec_to_time_t(interpret_long_date(rdata+16));
307 }
308 if (w_time) {
309 *w_time = convert_timespec_to_time_t(interpret_long_date(rdata+24));
310 }
311 if (mode) {
312 *mode = SVAL(rdata, 32);
313 }
314 if (size) {
315 *size = IVAL2_TO_SMB_BIG_UINT(rdata, 48);
316 }
317 if (ino) {
318 *ino = IVAL(rdata, 64);
319 }
320
321 SAFE_FREE(rdata);
322 SAFE_FREE(rparam);
323 return True;
324}
325
326/****************************************************************************
327send a qfileinfo call
328****************************************************************************/
329BOOL cli_qfileinfo3(struct cli_state *cli, int fnum,
330 uint16 *mode, off_t *size,
331 time_t *c_time, time_t *a_time, time_t *m_time,
332 time_t *w_time, SMB_INO_T *ino)
333{
334 unsigned int data_len = 0;
335 unsigned int param_len = 0;
336 uint16 setup = TRANSACT2_QFILEINFO;
337 pstring param;
338 char *rparam=NULL, *rdata=NULL;
339
340 /* if its a win95 server then fail this - win95 totally screws it
341 up */
342 if (cli->win95) return False;
343
344 param_len = 4;
345
346 memset(param, 0, param_len);
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 in_addr ip;
410 NTSTATUS rc;
411 struct cli_state * c;
412 char* dev_type;
413 int loginerror = 0;
414
415 zero_ip(&ip);
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 in_addr sip;
421
422 if (*workgroup)
423 {
424 if (!find_master_ip(workgroup, &sip)) {
425 return 1;
426 }
427 fstrcpy(group, inet_ntoa(sip));
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), 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_ip(&ip);
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, &ip)))
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 pstring param;
672 char *rparam=NULL, *rdata=NULL;
673
674 memset(param, 0, param_len);
675 SSVAL(param,0,fnum);
676 SSVAL(param,2,SMB_SET_FILE_END_OF_FILE_INFO);
677
678 if (!cli_send_trans(cli, SMBtrans2,
679 NULL, /* name */
680 -1, 0, /* fid, flags */
681 &setup, 1, 0, /* setup, length, max */
682 param, param_len, 2, /* param, length, max */
683 (char *)&newsize, sizeof(newsize), cli->max_xmit /* data, length, max */
684 )) {
685 return False;
686 }
687
688 if (!cli_receive_trans(cli, SMBtrans2,
689 &rparam, &param_len,
690 &rdata, &data_len)) {
691 return False;
692 }
693
694 SAFE_FREE(rdata);
695 SAFE_FREE(rparam);
696
697 return True;
698}
699
700int _System smbwrp_setfilesize(cli_state * cli, smbwrp_file * file, long long newsize)
701{
702 int rc = 0;
703 if (!cli || !file)
704 {
705 return EINVAL;
706 }
707
708 debuglocal(4,"cli_setnewfileszie(%s) %lld\n", file->fname, newsize);
709 if (!cli_setfilenewsize(cli, file->fd, newsize))
710 {
711 if (newsize)
712 {
713 rc = os2cli_errno(cli);
714 }
715
716 if (!cli_close(cli, file->fd))
717 {
718 return os2cli_errno(cli);
719 }
720 file->fd = -1;
721 file->offset = 0;
722 file->openmode &= ~(O_CREAT | O_EXCL);
723 file->openmode |= O_TRUNC;
724 debuglocal(4,"cli_setnewfileszie : cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
725 file->fd = cli_open(cli, file->fname, file->openmode, file->denymode);
726 if (file->fd == -1)
727 {
728 return os2cli_errno(cli);
729 }
730 }
731 return 0;
732}
733
734/*****************************************************
735a wrapper for rename()
736*******************************************************/
737int _System smbwrp_rename(cli_state * cli, char *oldname, char *newname)
738{
739 if (!cli || !oldname || !newname)
740 {
741 return EINVAL;
742 }
743
744 debuglocal(1,"Rename <%s> -> <%s>\n", oldname, newname);
745 //cli_unlink(cli, newname);
746// if (!cli_rename(cli, oldname, newname) && !cli_ntrename(cli, oldname, newname))
747 if (!cli_rename(cli, oldname, newname))
748 {
749 return os2cli_errno(cli);
750 }
751 return 0;
752}
753
754
755/*****************************************************
756a wrapper for chmod()
757*******************************************************/
758int _System smbwrp_setattr(cli_state * cli, smbwrp_fileinfo *finfo)
759{
760 if (!cli || !finfo || !*finfo->fname)
761 {
762 return EINVAL;
763 }
764
765debuglocal(4,"Setting on <%s> attr %04x, time %lu/%lu\n", finfo->fname, finfo->attr, finfo->mtime, finfo->mtime + get_time_zone(finfo->mtime));
766 if (!cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime + (finfo->mtime == 0 ? 0 : get_time_zone(finfo->mtime)))
767 && !cli_setatr(cli, finfo->fname, finfo->attr, 0))
768 {
769 return os2cli_errno(cli);
770 }
771 return 0;
772}
773
774/*****************************************************
775a wrapper for unlink()
776*******************************************************/
777int _System smbwrp_unlink(cli_state * cli, const char *fname)
778{
779 if (!cli || !fname)
780 {
781 return EINVAL;
782 }
783#if 0
784 if (strncmp(cli->dev, "LPT", 3) == 0)
785 {
786 int job = smbw_stat_printjob(cli, fname, NULL, NULL);
787 if (job == -1)
788 {
789 goto failed;
790 }
791 if (cli_printjob_del(cli, job) != 0)
792 {
793 goto failed;
794 }
795 } else
796#endif
797 if (!cli_unlink(cli, fname))
798 {
799 return os2cli_errno(cli);
800 }
801 return 0;
802}
803
804/*****************************************************
805a wrapper for lseek()
806*******************************************************/
807int _System smbwrp_lseek(cli_state * cli, smbwrp_file * file, int whence, long long offset)
808{
809 off_t size;
810 if (!cli || !file)
811 {
812 return EINVAL;
813 }
814
815 debuglocal(4,"lseek %d %lld %lld\n", whence, offset, file->offset);
816
817 switch (whence) {
818 case SEEK_SET:
819 if (offset < 0)
820 {
821 return EINVAL;
822 }
823 file->offset = offset;
824 break;
825 case SEEK_CUR:
826 file->offset += offset;
827 break;
828 case SEEK_END:
829 if (offset > 0)
830 {
831 return EINVAL;
832 }
833 if (!cli_qfileinfo3(cli, file->fd,
834 NULL, &size, NULL, NULL, NULL,
835 NULL, NULL) &&
836 !cli_getattrE(cli, file->fd,
837 NULL, (SMB_BIG_UINT *)&size, NULL, NULL, NULL))
838 {
839 return os2cli_errno(cli);
840 }
841 file->offset = size + offset;
842 break;
843 default: return EINVAL;
844 }
845
846 return 0;
847}
848
849/*****************************************************
850try to do a QPATHINFO and if that fails then do a getatr
851this is needed because win95 sometimes refuses the qpathinfo
852*******************************************************/
853int _System smbwrp_getattr(smbwrp_server *srv, cli_state * cli, smbwrp_fileinfo *finfo)
854{
855 SMB_INO_T ino = 0;
856 if (!cli || !finfo || !*finfo->fname)
857 {
858 return EINVAL;
859 }
860 debug_printf( "smbwrp_getattr\n");
861 debuglocal(4,"getattr %d %d <%s>\n", cli->capabilities & CAP_NOPATHINFO2, cli->capabilities & CAP_NT_SMBS, finfo->fname);
862 if (!(cli->capabilities & CAP_NOPATHINFO2) &&
863 cli_qpathinfo3(cli, finfo->fname, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,
864 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino))
865 {
866 finfo->attr &= 0x7F;
867//debuglocal(2,("gotattr %08x <%s>\n", finfo->attr, finfo->fname));
868// finfo->ctime -= get_time_zone(finfo->ctime);
869// finfo->atime -= get_time_zone(finfo->atime);
870// finfo->mtime -= get_time_zone(finfo->mtime);
871 return 0;
872 }
873//debuglocal(2,("getattr rc1 %d\n", os2cli_errno(cli)));
874
875 /* If the path is not on a share (it is a workgroup or a server),
876 * then cli_qpathinfo3 obviously fails. Return some fake information
877 * about the directory.
878 */
879 if ( *srv->server_name == 0
880 || (strcmp(cli->dev,"IPC") == 0)
881 || *srv->share_name == 0
882 || (stricmp(srv->share_name,"IPC$") == 0)
883 || (strncmp(cli->dev,"LPT",3) == 0)
884 )
885 {
886 debuglocal(4,"getattr not a share.\n");
887 *(time_t *)&finfo->ctime = time (NULL);
888 *(time_t *)&finfo->atime = time (NULL);
889 *(time_t *)&finfo->mtime = time (NULL);
890 finfo->size = 0;
891 finfo->easize = 0;
892 finfo->attr = aDIR;
893 return 0;
894 }
895
896 /* if this is NT then don't bother with the getatr */
897 if (cli->capabilities & CAP_NT_SMBS && !(cli->capabilities & CAP_NOPATHINFO2))
898 {
899 int rc = os2cli_errno(cli);
900 // cli_qpathinfo* reports EINVAL when path of given file not exists
901 // thus there is no real situation when EINVAL should be returned to
902 // client at this point, we just replace it to ENOTDIR
903 if (rc == EINVAL)
904 {
905 rc = ENOTDIR;
906 }
907 return rc;
908 }
909
910 if (cli_getatr(cli, finfo->fname, (unsigned short *)&finfo->attr, &finfo->size, (time_t *)&finfo->mtime))
911 {
912//debuglocal(2,("gotattr1 %08x <%s>\n", finfo->attr, finfo->fname));
913 finfo->mtime -= get_time_zone(finfo->mtime);
914 finfo->atime = finfo->atime; //was mtime
915 finfo->ctime = finfo->ctime; //was mtime
916 cli->capabilities &= CAP_NOPATHINFO2;
917 return 0;
918 }
919 return os2cli_errno(cli);
920}
921
922/*****************************************************
923try to do a QPATHINFO and if that fails then do a getatr
924this is needed because win95 sometimes refuses the qpathinfo
925*******************************************************/
926int _System smbwrp_fgetattr(cli_state * cli, smbwrp_file *file, smbwrp_fileinfo *finfo)
927{
928 SMB_INO_T ino = 0;
929 if (!cli || !file || !finfo)
930 {
931 return EINVAL;
932 }
933
934 strncpy(finfo->fname, file->fname, sizeof(finfo->fname) - 1);
935 if (!cli_qfileinfo3(cli, file->fd,
936 (unsigned short *)&finfo->attr, (off_t *)&finfo->size, (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime, NULL,
937 &ino))
938 {
939 if (!cli_getattrE(cli, file->fd,
940 (unsigned short *)&finfo->attr, (SMB_BIG_UINT *)(&finfo->size), (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime))
941 {
942 return os2cli_errno(cli);
943 }
944 else
945 {
946 finfo->ctime -= get_time_zone(finfo->ctime);
947 finfo->atime -= get_time_zone(finfo->atime);
948 finfo->mtime -= get_time_zone(finfo->mtime);
949 }
950 }
951 else
952 {
953// finfo->ctime -= get_time_zone(finfo->ctime);
954// finfo->atime -= get_time_zone(finfo->atime);
955// finfo->mtime -= get_time_zone(finfo->mtime);
956 }
957
958 return 0;
959}
960
961// =============================DIRECTORY ROUTINES============================
962
963/*****************************************************
964add a entry to a directory listing
965*******************************************************/
966static void smbwrp_dir_add(const char* mnt, smbwrp_fileinfo *finfo, const char *mask, void *state)
967{
968 if (state && finfo)
969 {
970 filelist_state * st = (filelist_state *)state;
971 char fullname[ _MAX_PATH];
972 debuglocal(8,"adding <%s> %d %d\n", finfo->fname, sizeof(st->finfo), st->datalen);
973 memcpy(&st->finfo, finfo, sizeof(st->finfo));
974 StrCpy(fullname, st->dir);
975 StrCat(fullname, finfo->fname);
976 StrCpy(st->finfo.fname, fullname);
977 getfindinfoL( st->pConn, st->plist, &st->finfo, st->ulAttribute, st->dir_mask);
978 }
979}
980
981static void smbwrp_special_add(const char * name, void * state)
982{
983 smbwrp_fileinfo finfo = {0};
984
985 if (!name)
986 {
987 return;
988 }
989
990 ZERO_STRUCT(finfo);
991
992 strncpy(finfo.fname, name, sizeof(finfo.fname) - 1);
993 finfo.attr = aRONLY | aDIR;
994
995 smbwrp_dir_add("", &finfo, NULL, state);
996}
997
998static void smbwrp_printjob_add(struct print_job_info *job, void * state)
999{
1000 smbwrp_fileinfo finfo = {0};
1001
1002 ZERO_STRUCT(finfo);
1003
1004//printf("Printjob <%s>\n", job->name);
1005
1006 strncpy(finfo.fname, job->name, sizeof(finfo.fname) - 1);
1007 finfo.mtime = job->t - get_time_zone(job->t);
1008 finfo.atime = finfo.atime; //was mtime
1009 finfo.ctime = finfo.ctime; //was mtime
1010 finfo.attr = aRONLY;
1011 finfo.size = job->size;
1012
1013 smbwrp_dir_add("", &finfo, NULL, state);
1014}
1015
1016static void smbwrp_share_add(const char *share, uint32 type,
1017 const char *comment, void *state)
1018{
1019 smbwrp_fileinfo finfo = {0};
1020
1021 // strip administrative names and printers from list
1022 if (type == STYPE_PRINTQ || strcmp(share,"IPC$") == 0) return;
1023
1024 ZERO_STRUCT(finfo);
1025
1026 strncpy(finfo.fname, share, sizeof(finfo.fname) - 1);
1027 finfo.attr = aRONLY | aDIR;
1028
1029 smbwrp_dir_add("", &finfo, NULL, state);
1030}
1031
1032/****************************************************************************
1033 Interpret a long filename structure - this is mostly guesses at the moment.
1034 The length of the structure is returned
1035 The structure of a long filename depends on the info level. 260 is used
1036 by NT and 2 is used by OS/2
1037****************************************************************************/
1038// YD from libsmb\clilist.c
1039static size_t _os2_interpret_long_filename(struct cli_state *cli,
1040 int level,char *p, smbwrp_fileinfo *finfo,
1041 uint32 *p_resume_key, DATA_BLOB *p_last_name_raw, uint32 *p_last_name_raw_len)
1042{
1043 extern file_info def_finfo;
1044 int len;
1045 char *base = p;
1046 smbwrp_fileinfo finfo1;
1047
1048 if (!finfo) finfo = &finfo1;
1049
1050 if (p_resume_key) {
1051 *p_resume_key = 0;
1052 }
1053
1054 finfo->attr = def_finfo.mode;
1055 finfo->mtime = def_finfo.mtime_ts.tv_sec;
1056 finfo->atime = def_finfo.atime_ts.tv_sec;
1057 finfo->ctime = def_finfo.ctime_ts.tv_sec;
1058 strncpy(finfo->fname, def_finfo.name, sizeof(finfo->fname) - 1);
1059 debug_printf( "fname %s (serverzone %d, level %d)\n",finfo->fname, cli->serverzone, level);
1060
1061 switch (level) {
1062 case 1: /* OS/2 understands this */
1063 /* these dates are converted to GMT by
1064 make_unix_date */
1065 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1066 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1067 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1068 finfo->size = IVAL(p,16);
1069 finfo->attr = CVAL(p,24);
1070 len = CVAL(p, 26);
1071 p += 27;
1072 p += clistr_align_in(cli, p, 0);
1073 /* the len+2 below looks strange but it is
1074 important to cope with the differences
1075 between win2000 and win9x for this call
1076 (tridge) */
1077 p += clistr_pull(cli, finfo->fname, p,
1078 sizeof(finfo->fname),
1079 len+2,
1080 STR_TERMINATE);
1081 finfo->easize = -1;
1082 return PTR_DIFF(p, base);
1083
1084 case 2: /* this is what OS/2 uses mostly */
1085 /* these dates are converted to GMT by
1086 make_unix_date */
1087 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1088 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1089 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1090 finfo->size = IVAL(p,16);
1091 finfo->attr = CVAL(p,24);
1092 finfo->easize = IVAL(p,26);
1093 len = CVAL(p, 30);
1094 p += 31;
1095 /* check for unisys! */
1096 p += clistr_pull(cli, finfo->fname, p,
1097 sizeof(finfo->fname),
1098 len,
1099 STR_NOALIGN);
1100 return PTR_DIFF(p, base) + 1;
1101
1102 case 260: /* NT uses this, but also accepts 2 */
1103 {
1104 size_t namelen, slen;
1105 p += 4; /* next entry offset */
1106 if (p_resume_key) {
1107 *p_resume_key = IVAL(p,0);
1108 }
1109
1110 p += 4; /* fileindex */
1111
1112 /* Offset zero is "create time", not "change time". */
1113 p += 8;
1114 finfo->atime = interpret_long_date(p).tv_sec;
1115 p += 8;
1116 finfo->mtime = interpret_long_date(p).tv_sec;
1117 p += 8;
1118 finfo->ctime = interpret_long_date(p).tv_sec;
1119 p += 8;
1120 finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0);
1121 p += 8;
1122 p += 8; /* alloc size */
1123 finfo->attr = CVAL(p,0);
1124 p += 4;
1125 namelen = IVAL(p,0);
1126 p += 4;
1127 finfo->easize = IVAL(p,0);
1128 p += 4; /* EA size */
1129 slen = SVAL(p, 0);
1130 p += 2;
1131#if 0
1132 {
1133 /* stupid NT bugs. grr */
1134 int flags = 0;
1135 if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE;
1136 clistr_pull(cli, finfo->short_name, p,
1137 sizeof(finfo->short_name),
1138 slen, flags);
1139 }
1140#endif
1141 p += 24; /* short name? */
1142 clistr_pull(cli, finfo->fname, p,
1143 sizeof(finfo->fname),
1144 namelen, 0);
1145
1146 /* To be robust in the face of unicode conversion failures
1147 we need to copy the raw bytes of the last name seen here.
1148 Namelen doesn't include the terminating unicode null, so
1149 copy it here. */
1150#if 0
1151 if (p_last_name_raw && p_last_name_raw_len) {
1152 if (namelen + 2 > p_last_name_raw->length) {
1153 memset(p_last_name_raw->data, '\0', sizeof(p_last_name_raw->length));
1154 *p_last_name_raw_len = 0;
1155 } else {
1156 memcpy(p_last_name_raw->data, p, namelen);
1157 SSVAL(p_last_name_raw->data, namelen, 0);
1158 *p_last_name_raw_len = namelen + 2;
1159 }
1160 }
1161#endif
1162 return (size_t)IVAL(base, 0);
1163 }
1164 }
1165
1166 debuglocal(1,"Unknown long filename format %d\n",level);
1167 return (size_t)IVAL(base,0);
1168}
1169
1170/****************************************************************************
1171 Do a directory listing, calling fn on each file found.
1172 Modified from cli_list_new
1173****************************************************************************/
1174
1175static int list_files(struct cli_state *cli, const char *Mask, uint16 attribute,
1176 void (*fn)(const char*, smbwrp_fileinfo *, const char *, void *), void *state)
1177{
1178#if 1
1179 int max_matches = 1366; /* Match W2k - was 512. */
1180#else
1181 int max_matches = 512;
1182#endif
1183 int info_level;
1184 char *p, *p2;
1185 pstring mask;
1186 smbwrp_fileinfo finfo;
1187 int i;
1188 char *dirlist = NULL;
1189 int dirlist_len = 0;
1190 int total_received = -1;
1191 BOOL First = True;
1192 int ff_searchcount=0;
1193 int ff_eos=0;
1194 int ff_dir_handle=0;
1195 int loop_count = 0;
1196 char *rparam=NULL, *rdata=NULL;
1197 unsigned int param_len, data_len;
1198 uint16 setup;
1199 pstring param;
1200 const char *mnt;
1201 uint32 resume_key = 0;
1202 uint32 last_name_raw_len = 0;
1203 DATA_BLOB last_name_raw = data_blob(NULL, 2*sizeof(pstring));
1204
1205 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1206 info_level = (cli->capabilities&CAP_NT_SMBS)?260:2;
1207
1208 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, mask);
1209
1210 /* when getting a directory listing from a 2k dfs root share,
1211 we have to include the full path (\server\share\mask) here */
1212
1213 if ( cli->dfsroot )
1214 pstr_sprintf( mask, "\\%s\\%s\\%s", cli->desthost, cli->share, Mask );
1215 else
1216 pstrcpy(mask,Mask);
1217
1218 while (ff_eos == 0) {
1219 loop_count++;
1220 if (loop_count > 200) {
1221 debuglocal(0,"Error: Looping in FIND_NEXT??\n");
1222 break;
1223 }
1224
1225 if (First) {
1226 setup = TRANSACT2_FINDFIRST;
1227 SSVAL(param,0,attribute); /* attribute */
1228 SSVAL(param,2,max_matches); /* max count */
1229 SSVAL(param,4,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1230 SSVAL(param,6,info_level);
1231 SIVAL(param,8,0);
1232 p = param+12;
1233 p += clistr_push(cli, param+12, mask, sizeof(param)-12,
1234 STR_TERMINATE);
1235 } else {
1236 setup = TRANSACT2_FINDNEXT;
1237 SSVAL(param,0,ff_dir_handle);
1238 SSVAL(param,2,max_matches); /* max count */
1239 SSVAL(param,4,info_level);
1240 /* For W2K servers serving out FAT filesystems we *must* set the
1241 resume key. If it's not FAT then it's returned as zero. */
1242 SIVAL(param,6,resume_key); /* ff_resume_key */
1243 /* NB. *DON'T* use continue here. If you do it seems that W2K and bretheren
1244 can miss filenames. Use last filename continue instead. JRA */
1245 SSVAL(param,10,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1246 p = param+12;
1247 if (last_name_raw_len && (last_name_raw_len < (sizeof(param)-12))) {
1248 memcpy(p, last_name_raw.data, last_name_raw_len);
1249 p += last_name_raw_len;
1250 } else {
1251 p += clistr_push(cli, param+12, mask, sizeof(param)-12, STR_TERMINATE);
1252 }
1253 }
1254
1255 param_len = PTR_DIFF(p, param);
1256
1257 if (!cli_send_trans(cli, SMBtrans2,
1258 NULL, /* Name */
1259 -1, 0, /* fid, flags */
1260 &setup, 1, 0, /* setup, length, max */
1261 param, param_len, 10, /* param, length, max */
1262 NULL, 0,
1263#if 0
1264 /* w2k value. */
1265 MIN(16384,cli->max_xmit) /* data, length, max. */
1266#else
1267 cli->max_xmit /* data, length, max. */
1268#endif
1269 )) {
1270 break;
1271 }
1272
1273 if (!cli_receive_trans(cli, SMBtrans2,
1274 &rparam, &param_len,
1275 &rdata, &data_len) &&
1276 cli_is_dos_error(cli)) {
1277 /* we need to work around a Win95 bug - sometimes
1278 it gives ERRSRV/ERRerror temprarily */
1279 uint8 eclass;
1280 uint32 ecode;
1281
1282 SAFE_FREE(rdata);
1283 SAFE_FREE(rparam);
1284
1285 cli_dos_error(cli, &eclass, &ecode);
1286
1287 /*
1288 * OS/2 might return "no more files",
1289 * which just tells us, that searchcount is zero
1290 * in this search.
1291 * Guenter Kukkukk <linux@kukkukk.com>
1292 */
1293
1294 if (eclass == ERRDOS && ecode == ERRnofiles) {
1295 ff_searchcount = 0;
1296 cli_reset_error(cli);
1297 break;
1298 }
1299
1300 if (eclass != ERRSRV || ecode != ERRerror)
1301 break;
1302 smb_msleep(100);
1303 continue;
1304 }
1305
1306 if (cli_is_error(cli) || !rdata || !rparam)
1307 {
1308 if (First && info_level == 2)
1309 {
1310 // we have tried query ea size, but now will try without ea size
1311 info_level = 1;
1312 debuglocal(4,"list_files fallback to level %d\n", info_level);
1313 continue;
1314 }
1315 SAFE_FREE(rdata);
1316 SAFE_FREE(rparam);
1317 break;
1318 }
1319
1320 if (total_received == -1)
1321 total_received = 0;
1322
1323 /* parse out some important return info */
1324 p = rparam;
1325 if (First) {
1326 ff_dir_handle = SVAL(p,0);
1327 ff_searchcount = SVAL(p,2);
1328 ff_eos = SVAL(p,4);
1329 } else {
1330 ff_searchcount = SVAL(p,0);
1331 ff_eos = SVAL(p,2);
1332 }
1333 debuglocal(4,"list_files %d %d %d %d\n", ff_searchcount, ff_eos, "(ff_lastname)", First);
1334
1335 if (ff_searchcount == 0) {
1336 SAFE_FREE(rdata);
1337 SAFE_FREE(rparam);
1338 break;
1339 }
1340
1341 /* point to the data bytes */
1342 p = rdata;
1343
1344 memset(&finfo, 0, sizeof(finfo));
1345 finfo.easize = -1;
1346 /* we might need the lastname for continuations */
1347 for (p2=p,i=0;i<ff_searchcount;i++) {
1348 if ((info_level == 260) && (i == ff_searchcount-1)) {
1349 /* Last entry - fixup the last offset length. */
1350 SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2));
1351 }
1352 p2 += _os2_interpret_long_filename(cli,info_level,p2,&finfo,
1353 &resume_key,&last_name_raw,&last_name_raw_len);
1354
1355 if (!First && *mask && strcsequal(finfo.fname, mask)) {
1356 debuglocal(0,"Error: Looping in FIND_NEXT as name %s has already been seen?\n",
1357 finfo.fname);
1358 ff_eos = 1;
1359 break;
1360 }
1361 }
1362
1363 if (ff_searchcount > 0) {
1364 pstrcpy(mask, finfo.fname);
1365 } else {
1366 pstrcpy(mask,"");
1367 }
1368
1369 /* grab the data for later use */
1370 /* and add them to the dirlist pool */
1371 dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len);
1372
1373 if (!dirlist) {
1374 debuglocal(0,"cli_list_new: Failed to expand dirlist\n");
1375 SAFE_FREE(rdata);
1376 SAFE_FREE(rparam);
1377 break;
1378 }
1379
1380 memcpy(dirlist+dirlist_len,p,data_len);
1381 dirlist_len += data_len;
1382
1383 total_received += ff_searchcount;
1384
1385 SAFE_FREE(rdata);
1386 SAFE_FREE(rparam);
1387
1388 debuglocal(3,"received %d entries (eos=%d)\n",
1389 ff_searchcount,ff_eos);
1390
1391 if (ff_searchcount > 0)
1392 loop_count = 0;
1393
1394 First = False;
1395 }
1396
1397 mnt = cli_cm_get_mntpoint( cli );
1398
1399 /* see if the server disconnected or the connection otherwise failed */
1400 if (cli_is_error(cli)) {
1401 total_received = -1;
1402 } else {
1403 /* no connection problem. let user function add each entry */
1404 for (p=dirlist,i=0;i<total_received;i++) {
1405 p += _os2_interpret_long_filename(cli, info_level, p,
1406 &finfo,NULL,NULL,NULL);
1407 fn( mnt,&finfo, Mask, state );
1408 }
1409 }
1410
1411 /* free up the dirlist buffer and last name raw blob */
1412 SAFE_FREE(dirlist);
1413 data_blob_free(&last_name_raw);
1414 return(total_received);
1415}
1416
1417
1418/*****************************************************
1419open a directory on the server
1420*******************************************************/
1421int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1422{
1423 if (!srv || !cli || !state || !*state->mask)
1424 {
1425 return EINVAL;
1426 }
1427 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);
1428 debug_printf( "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);
1429 if (*srv->workgroup == 0 && *srv->server_name == 0)
1430 {
1431 smbwrp_special_add(".", state);
1432 smbwrp_special_add("..", state);
1433 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1434 smbwrp_share_add, state);
1435 } else
1436 if (*srv->server_name == 0)
1437 {
1438 smbwrp_special_add(".", state);
1439 smbwrp_special_add("..", state);
1440
1441 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1442 smbwrp_share_add, state);
1443 } else
1444 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1445 {
1446 smbwrp_special_add(".", state);
1447 smbwrp_special_add("..", state);
1448
1449 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1450 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1451 {
1452 return os2cli_errno(cli);
1453 }
1454 } else
1455 if (strncmp(cli->dev,"LPT",3) == 0)
1456 {
1457 smbwrp_special_add(".", state);
1458 smbwrp_special_add("..", state);
1459 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1460 {
1461 return os2cli_errno(cli);
1462 }
1463 }
1464 else
1465 {
1466#if 0
1467 if (strcmp(path,"\\") == 0) {
1468 smbwrp_special_add(".", state);
1469 smbwrp_special_add("..", state);
1470 }
1471#endif
1472#if 0
1473 if (cli_list(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1474 smbwrp_dir_add_old, state) < 0)
1475#else
1476 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1477 smbwrp_dir_add, state) < 0)
1478#endif
1479 {
1480 return os2cli_errno(cli);
1481 }
1482 }
1483
1484 return 0;
1485}
1486
1487/*****************************************************
1488a wrapper for chdir()
1489*******************************************************/
1490int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1491{
1492 unsigned short mode = aDIR;
1493 smbwrp_fileinfo finfo = {0};
1494 if (!cli || !fname)
1495 {
1496 return EINVAL;
1497 }
1498
1499 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1500 if (smbwrp_getattr(srv, cli, &finfo))
1501 {
1502 return os2cli_errno(cli);
1503 }
1504
1505 if (!(finfo.attr & aDIR)) {
1506 return ENOTDIR;
1507 }
1508
1509 return 0;
1510}
1511
1512
1513/*****************************************************
1514a wrapper for mkdir()
1515*******************************************************/
1516int _System smbwrp_mkdir(cli_state * cli, char *fname)
1517{
1518 if (!cli || !fname)
1519 {
1520 return EINVAL;
1521 }
1522
1523 if (!cli_mkdir(cli, fname))
1524 {
1525 return os2cli_errno(cli);
1526 }
1527 return 0;
1528}
1529
1530/*****************************************************
1531a wrapper for rmdir()
1532*******************************************************/
1533int _System smbwrp_rmdir(cli_state * cli, char *fname)
1534{
1535 if (!cli || !fname)
1536 {
1537 return EINVAL;
1538 }
1539
1540 if (!cli_rmdir(cli, fname))
1541 {
1542 return os2cli_errno(cli);
1543 }
1544 return 0;
1545}
1546
1547/*****************************************************
1548set EA for a path
1549*******************************************************/
1550int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1551{
1552 if (!cli || !fname || !name)
1553 {
1554 return EINVAL;
1555 }
1556 if (!cli_set_ea_path(cli, fname, name, value, size))
1557 {
1558 return os2cli_errno(cli);
1559 }
1560 return 0;
1561}
1562
1563/*****************************************************
1564set EA for a file
1565*******************************************************/
1566int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1567{
1568 if (!cli || !file || !name)
1569 {
1570 return EINVAL;
1571 }
1572 if (!cli_set_ea_fnum(cli, file->fd, name, value, size))
1573 {
1574 return os2cli_errno(cli);
1575 }
1576 return 0;
1577}
1578
1579
1580#pragma pack(1)
1581typedef struct _FEA /* fea */
1582{
1583 unsigned char fEA; /* flags */
1584 unsigned char cbName; /* name length not including NULL */
1585 unsigned short cbValue; /* value length */
1586} FEA;
1587
1588typedef struct _FEALIST /* feal */
1589{
1590 unsigned long cbList; /* total bytes of structure including full list */
1591 FEA list[1]; /* variable length FEA structures */
1592} FEALIST;
1593#pragma pack()
1594
1595static int unilistea(cli_state * cli, char *fname, smbwrp_file *file, void * buffer, unsigned long size)
1596{
1597 int fnum, i;
1598 int gotsize = sizeof(unsigned long);
1599 size_t num_eas;
1600 struct ea_struct *ea_list = NULL;
1601 TALLOC_CTX *mem_ctx;
1602 FEA * p;
1603 FEALIST * pfealist;
1604 char * q;
1605
1606 mem_ctx = talloc_init("%d: ealist", _gettid());
1607 pfealist = (FEALIST *)buffer;
1608 pfealist->cbList = 0;
1609
1610 if (file)
1611 {
1612 if (!cli_get_ea_list_fnum(cli, file->fd, mem_ctx, &num_eas, &ea_list))
1613 {
1614 debuglocal(4,"ea_get_fnum list failed - %s\n", cli_errstr(cli));
1615 talloc_destroy(mem_ctx);
1616 return os2cli_errno(cli);
1617 }
1618 }
1619 else
1620 {
1621 if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list))
1622 {
1623 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1624 talloc_destroy(mem_ctx);
1625 return os2cli_errno(cli);
1626 }
1627 }
1628
1629 debuglocal(4,"num_eas = %d\n", num_eas);
1630
1631 // we will count that os/2 max EA size for file is 64kb
1632 p = pfealist->list;
1633 for (i = 0; i < num_eas; i++)
1634 {
1635 int namelen = strlen(ea_list[i].name);
1636 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);
1637 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1638 {
1639 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1640 continue;
1641 }
1642 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1643 if (size >= gotsize)
1644 {
1645 p->fEA = 0;
1646 p->cbName = namelen;
1647 p->cbValue = ea_list[i].value.length;
1648 q = (char *)(p + 1);
1649 strncpy(q, ea_list[i].name, namelen + 1);
1650 q += namelen + 1;
1651 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1652 p = (FEA *)(q + ea_list[i].value.length);
1653 }
1654 }
1655 pfealist->cbList = gotsize;
1656 debuglocal(4,"ret size = %d\n", gotsize);
1657
1658 talloc_destroy(mem_ctx);
1659 return 0;
1660}
1661
1662/*****************************************************
1663lists EA of a path
1664*******************************************************/
1665int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1666{
1667 if (!cli || !fname || !buffer)
1668 {
1669 return EINVAL;
1670 }
1671
1672 debuglocal(4,"EALIst for <%s>\n", fname);
1673 return unilistea(cli, fname, NULL, buffer, size);
1674}
1675
1676/*****************************************************
1677lists EA of a file
1678*******************************************************/
1679int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1680{
1681 if (!cli || !file || !buffer)
1682 {
1683 return EINVAL;
1684 }
1685
1686 debuglocal(4,"FEALIst for <%s>/%d\n", file->fname, file->fd);
1687 return unilistea(cli, NULL, file, buffer, size);
1688}
1689
1690/****************************************************************************
1691Check the space on a device.
1692****************************************************************************/
1693int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1694{
1695 int total, bsize, avail;
1696
1697 if (!cli || !pfsa)
1698 {
1699 return EINVAL;
1700 }
1701
1702 if (!cli_dskattr(cli, &bsize, &total, &avail))
1703 {
1704 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1705 return os2cli_errno(cli);
1706 }
1707
1708 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1709 total, bsize, avail);
1710
1711 // YD currently Samba return it in MB!
1712 pfsa->cSectorUnit = 1;
1713 if (bsize >= 65536)
1714 {
1715 pfsa->cUnit = total*1024;
1716 pfsa->cUnitAvail = avail*1024;
1717 pfsa->cbSector = bsize/1024;
1718 }
1719 else
1720 {
1721 pfsa->cUnit = total;
1722 pfsa->cUnitAvail = avail;
1723 pfsa->cbSector = bsize;
1724 }
1725
1726 return 0;
1727}
1728
Note: See TracBrowser for help on using the repository browser.