source: branches/client-2.0/src/smbwrp.c@ 497

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

samba client: caching

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