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

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

Final fix for Ticket #88 (by diver)

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