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

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

samba client 1.6: made it build

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