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

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

samba client 1.6: added all remaining 1.5 changes

  • Property svn:eol-style set to native
File size: 46.6 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 def_finfo is not available anymore, probably the complete function needs more work
1069// in the longrun we have to 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 extern file_info def_finfo;
1076 int len;
1077 char *base = p;
1078 smbwrp_fileinfo finfo1;
1079
1080 if (!finfo) finfo = &finfo1;
1081
1082 if (p_resume_key) {
1083 *p_resume_key = 0;
1084 }
1085
1086 finfo->attr = def_finfo.mode;
1087 finfo->mtime = def_finfo.mtime_ts.tv_sec;
1088 finfo->atime = def_finfo.atime_ts.tv_sec;
1089 finfo->ctime = def_finfo.ctime_ts.tv_sec;
1090 strncpy(finfo->fname, def_finfo.name, sizeof(finfo->fname) - 1);
1091 debuglocal(9,"fname %s (serverzone %d, level %d)\n",finfo->fname, cli->serverzone, level);
1092
1093 switch (level) {
1094 case 1: /* OS/2 understands this */
1095 /* these dates are converted to GMT by
1096 make_unix_date */
1097 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1098 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1099 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1100 finfo->size = IVAL(p,16);
1101 finfo->attr = CVAL(p,24);
1102 len = CVAL(p, 26);
1103 p += 27;
1104 p += clistr_align_in(cli, p, 0);
1105 /* the len+2 below looks strange but it is
1106 important to cope with the differences
1107 between win2000 and win9x for this call
1108 (tridge) */
1109 p += clistr_pull(cli, finfo->fname, p,
1110 sizeof(finfo->fname),
1111 len+2,
1112 STR_TERMINATE);
1113 finfo->easize = -1;
1114 return PTR_DIFF(p, base);
1115
1116 case 2: /* this is what OS/2 uses mostly */
1117 /* these dates are converted to GMT by
1118 make_unix_date */
1119 finfo->ctime = cli_make_unix_date2(cli, p+4) - cli->serverzone;
1120 finfo->atime = cli_make_unix_date2(cli, p+8) - cli->serverzone;
1121 finfo->mtime = cli_make_unix_date2(cli, p+12) - cli->serverzone;
1122 finfo->size = IVAL(p,16);
1123 finfo->attr = CVAL(p,24);
1124 finfo->easize = IVAL(p,26);
1125 len = CVAL(p, 30);
1126 p += 31;
1127 /* check for unisys! */
1128 p += clistr_pull(cli, finfo->fname, p,
1129 sizeof(finfo->fname),
1130 len,
1131 STR_NOALIGN);
1132 return PTR_DIFF(p, base) + 1;
1133
1134 case 260: /* NT uses this, but also accepts 2 */
1135 {
1136 size_t namelen, slen;
1137 p += 4; /* next entry offset */
1138 if (p_resume_key) {
1139 *p_resume_key = IVAL(p,0);
1140 }
1141
1142 p += 4; /* fileindex */
1143
1144 /* Offset zero is "create time", not "change time". */
1145 p += 8;
1146 finfo->atime = interpret_long_date(p).tv_sec;
1147 p += 8;
1148 finfo->mtime = interpret_long_date(p).tv_sec;
1149 p += 8;
1150 finfo->ctime = interpret_long_date(p).tv_sec;
1151 p += 8;
1152 finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0);
1153 p += 8;
1154 p += 8; /* alloc size */
1155 finfo->attr = CVAL(p,0);
1156 p += 4;
1157 namelen = IVAL(p,0);
1158 p += 4;
1159 finfo->easize = IVAL(p,0);
1160 p += 4; /* EA size */
1161 slen = SVAL(p, 0);
1162 p += 2;
1163#if 0
1164 {
1165 /* stupid NT bugs. grr */
1166 int flags = 0;
1167 if (p[1] == 0 && namelen > 1) flags |= STR_UNICODE;
1168 clistr_pull(cli, finfo->short_name, p,
1169 sizeof(finfo->short_name),
1170 slen, flags);
1171 }
1172#endif
1173 p += 24; /* short name? */
1174 clistr_pull(cli, finfo->fname, p,
1175 sizeof(finfo->fname),
1176 namelen, 0);
1177
1178 /* To be robust in the face of unicode conversion failures
1179 we need to copy the raw bytes of the last name seen here.
1180 Namelen doesn't include the terminating unicode null, so
1181 copy it here. */
1182#if 0
1183 if (p_last_name_raw && p_last_name_raw_len) {
1184 if (namelen + 2 > p_last_name_raw->length) {
1185 memset(p_last_name_raw->data, '\0', sizeof(p_last_name_raw->length));
1186 *p_last_name_raw_len = 0;
1187 } else {
1188 memcpy(p_last_name_raw->data, p, namelen);
1189 SSVAL(p_last_name_raw->data, namelen, 0);
1190 *p_last_name_raw_len = namelen + 2;
1191 }
1192 }
1193#endif
1194 return (size_t)IVAL(base, 0);
1195 }
1196 }
1197
1198 debuglocal(1,"Unknown long filename format %d\n",level);
1199 return (size_t)IVAL(base,0);
1200}
1201
1202/****************************************************************************
1203 Do a directory listing, calling fn on each file found.
1204 Modified from cli_list_new
1205****************************************************************************/
1206
1207static int list_files(struct cli_state *cli, const char *Mask, uint16 attribute,
1208 void (*fn)(const char*, smbwrp_fileinfo *, const char *, void *), void *state)
1209{
1210#if 1
1211 int max_matches = 1366; /* Match W2k - was 512. */
1212#else
1213 int max_matches = 512;
1214#endif
1215 int info_level;
1216 char *p, *p2, *rdata_end;
1217 char *mask=NULL;
1218 smbwrp_fileinfo finfo;
1219 int i;
1220 char *dirlist = NULL;
1221 int dirlist_len = 0;
1222 int total_received = -1;
1223 bool First = True;
1224 int ff_searchcount=0;
1225 int ff_eos=0;
1226 int ff_dir_handle=0;
1227 int loop_count = 0;
1228 char *rparam=NULL, *rdata=NULL;
1229 unsigned int param_len, data_len;
1230 uint16 setup;
1231 char *param;
1232 const char *mnt;
1233 uint32 resume_key = 0;
1234 uint32 last_name_raw_len = 0;
1235 DATA_BLOB last_name_raw = data_blob(NULL, 0);
1236
1237 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1238 info_level = (cli->capabilities&CAP_NT_SMBS)?260:2;
1239
1240 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, Mask);
1241
1242 /* when getting a directory listing from a 2k dfs root share,
1243 we have to include the full path (\server\share\mask) here */
1244
1245 if ( cli->dfsroot ) {
1246 mask = talloc_asprintf(mask, "\\%s\\%s\\%s", cli->desthost, cli->share, Mask );
1247 } else {
1248 mask = SMB_STRDUP(Mask);
1249 if (!mask) {
1250 return -1;
1251 }
1252 }
1253
1254 while (ff_eos == 0) {
1255 loop_count++;
1256 if (loop_count > 200) {
1257 debuglocal(0,"Error: Looping in FIND_NEXT??\n");
1258 break;
1259 }
1260
1261 size_t nlen = 2*(strlen(mask)+1);
1262 param = SMB_MALLOC_ARRAY(char, 12+nlen+last_name_raw.length+2);
1263 if (!param) {
1264 break;
1265 }
1266
1267 if (First) {
1268 setup = TRANSACT2_FINDFIRST;
1269 SSVAL(param,0,attribute); /* attribute */
1270 SSVAL(param,2,max_matches); /* max count */
1271 SSVAL(param,4,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1272 SSVAL(param,6,info_level);
1273 SIVAL(param,8,0);
1274 p = param+12;
1275 p += clistr_push(cli, param+12, mask, nlen,
1276 STR_TERMINATE);
1277 } else {
1278 setup = TRANSACT2_FINDNEXT;
1279 SSVAL(param,0,ff_dir_handle);
1280 SSVAL(param,2,max_matches); /* max count */
1281 SSVAL(param,4,info_level);
1282 /* For W2K servers serving out FAT filesystems we *must* set the
1283 resume key. If it's not FAT then it's returned as zero. */
1284 SIVAL(param,6,resume_key); /* ff_resume_key */
1285 /* NB. *DON'T* use continue here. If you do it seems that W2K and bretheren
1286 can miss filenames. Use last filename continue instead. JRA */
1287 SSVAL(param,10,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
1288 p = param+12;
1289 if (last_name_raw.length) {
1290 memcpy(p, last_name_raw.data, last_name_raw.length);
1291 p += last_name_raw.length;
1292 } else {
1293 p += clistr_push(cli, param+12, mask, nlen, STR_TERMINATE);
1294 }
1295 }
1296
1297 param_len = PTR_DIFF(p, param);
1298
1299 if (!cli_send_trans(cli, SMBtrans2,
1300 NULL, /* Name */
1301 -1, 0, /* fid, flags */
1302 &setup, 1, 0, /* setup, length, max */
1303 param, param_len, 10, /* param, length, max */
1304 NULL, 0,
1305#if 0
1306 /* w2k value. */
1307 MIN(16384,cli->max_xmit) /* data, length, max. */
1308#else
1309 cli->max_xmit /* data, length, max. */
1310#endif
1311 )) {
1312 SAFE_FREE(param);
1313 break;
1314 }
1315
1316 SAFE_FREE(param);
1317
1318 if (!cli_receive_trans(cli, SMBtrans2,
1319 &rparam, &param_len,
1320 &rdata, &data_len) &&
1321 cli_is_dos_error(cli)) {
1322 /* we need to work around a Win95 bug - sometimes
1323 it gives ERRSRV/ERRerror temprarily */
1324 uint8 eclass;
1325 uint32 ecode;
1326
1327 SAFE_FREE(rdata);
1328 SAFE_FREE(rparam);
1329
1330 cli_dos_error(cli, &eclass, &ecode);
1331
1332 /*
1333 * OS/2 might return "no more files",
1334 * which just tells us, that searchcount is zero
1335 * in this search.
1336 * Guenter Kukkukk <linux@kukkukk.com>
1337 */
1338
1339 if (eclass == ERRDOS && ecode == ERRnofiles) {
1340 ff_searchcount = 0;
1341 cli_reset_error(cli);
1342 break;
1343 }
1344
1345 if (eclass != ERRSRV || ecode != ERRerror)
1346 break;
1347 smb_msleep(100);
1348 continue;
1349 }
1350
1351 if (cli_is_error(cli) || !rdata || !rparam)
1352 {
1353 if (First && info_level == 2)
1354 {
1355 // we have tried query ea size, but now will try without ea size
1356 info_level = 1;
1357 debuglocal(4,"list_files fallback to level %d\n", info_level);
1358 continue;
1359 }
1360 SAFE_FREE(rdata);
1361 SAFE_FREE(rparam);
1362 break;
1363 }
1364
1365 if (total_received == -1)
1366 total_received = 0;
1367
1368 /* parse out some important return info */
1369 p = rparam;
1370 if (First) {
1371 ff_dir_handle = SVAL(p,0);
1372 ff_searchcount = SVAL(p,2);
1373 ff_eos = SVAL(p,4);
1374 } else {
1375 ff_searchcount = SVAL(p,0);
1376 ff_eos = SVAL(p,2);
1377 }
1378 debuglocal(4,"list_files %d %d %d %d\n", ff_searchcount, ff_eos, "(ff_lastname)", First);
1379
1380 if (ff_searchcount == 0) {
1381 SAFE_FREE(rdata);
1382 SAFE_FREE(rparam);
1383 break;
1384 }
1385
1386 /* point to the data bytes */
1387 p = rdata;
1388 rdata_end = rdata + data_len;
1389
1390 memset(&finfo, 0, sizeof(finfo));
1391 finfo.easize = -1;
1392 /* we might need the lastname for continuations */
1393 for (p2=p,i=0;i<ff_searchcount && p2 < rdata_end;i++) {
1394 if ((info_level == 260) && (i == ff_searchcount-1)) {
1395 /* Last entry - fixup the last offset length. */
1396 SIVAL(p2,0,PTR_DIFF((rdata + data_len),p2));
1397 }
1398 p2 += _os2_interpret_long_filename(cli,info_level,p2,&finfo,
1399 &resume_key,&last_name_raw,&last_name_raw.length);
1400
1401 if (!finfo.fname) {
1402 debuglocal(0,("Error: unable to parse name from info level %d\n",
1403 info_level));
1404 ff_eos = 1;
1405 break;
1406 }
1407
1408 if (!First && *mask && strcsequal(finfo.fname, mask)) {
1409 debuglocal(0,"Error: Looping in FIND_NEXT as name %s has already been seen?\n",
1410 finfo.fname);
1411 ff_eos = 1;
1412 break;
1413 }
1414 }
1415
1416 SAFE_FREE(mask);
1417 if (ff_searchcount > 0) {
1418 mask = SMB_STRDUP(finfo.fname);
1419 } else {
1420 mask = SMB_STRDUP("");
1421 }
1422 if (!mask) {
1423 SAFE_FREE(rdata);
1424 SAFE_FREE(rparam);
1425 break;
1426 }
1427
1428 /* grab the data for later use */
1429 /* and add them to the dirlist pool */
1430 dirlist = (char *)SMB_REALLOC(dirlist,dirlist_len + data_len);
1431
1432 if (!dirlist) {
1433 debuglocal(0,"cli_list_new: Failed to expand dirlist\n");
1434 SAFE_FREE(rdata);
1435 SAFE_FREE(rparam);
1436 break;
1437 }
1438
1439 memcpy(dirlist+dirlist_len,p,data_len);
1440 dirlist_len += data_len;
1441
1442 total_received += ff_searchcount;
1443
1444 SAFE_FREE(rdata);
1445 SAFE_FREE(rparam);
1446
1447 debuglocal(3,"received %d entries (eos=%d)\n",
1448 ff_searchcount,ff_eos);
1449
1450 if (ff_searchcount > 0)
1451 loop_count = 0;
1452
1453 First = False;
1454 }
1455
1456 mnt = cli_cm_get_mntpoint( cli );
1457
1458 /* see if the server disconnected or the connection otherwise failed */
1459 if (cli_is_error(cli)) {
1460 total_received = -1;
1461 } else {
1462 /* no connection problem. let user function add each entry */
1463 for (p=dirlist,i=0;i<total_received;i++) {
1464 p += _os2_interpret_long_filename(cli, info_level, p,
1465 &finfo,NULL,NULL,NULL);
1466 fn( mnt,&finfo, Mask, state );
1467 }
1468 }
1469
1470 /* free up the dirlist buffer and last name raw blob */
1471 SAFE_FREE(dirlist);
1472 SAFE_FREE(mask);
1473 data_blob_free(&last_name_raw);
1474 return(total_received);
1475}
1476
1477
1478/*****************************************************
1479open a directory on the server
1480*******************************************************/
1481int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1482{
1483 if (!srv || !cli || !state || !*state->mask)
1484 {
1485 return EINVAL;
1486 }
1487 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);
1488 if (*srv->workgroup == 0 && *srv->server_name == 0)
1489 {
1490 smbwrp_special_add(".", state);
1491 smbwrp_special_add("..", state);
1492 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1493 smbwrp_share_add, state);
1494 } else
1495 if (*srv->server_name == 0)
1496 {
1497 smbwrp_special_add(".", state);
1498 smbwrp_special_add("..", state);
1499
1500 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1501 smbwrp_share_add, state);
1502 } else
1503 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1504 {
1505 smbwrp_special_add(".", state);
1506 smbwrp_special_add("..", state);
1507
1508 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1509 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1510 {
1511 return os2cli_errno(cli);
1512 }
1513 } else
1514 if (strncmp(cli->dev,"LPT",3) == 0)
1515 {
1516 smbwrp_special_add(".", state);
1517 smbwrp_special_add("..", state);
1518 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1519 {
1520 return os2cli_errno(cli);
1521 }
1522 }
1523 else
1524 {
1525#if 0
1526 if (strcmp(path,"\\") == 0) {
1527 smbwrp_special_add(".", state);
1528 smbwrp_special_add("..", state);
1529 }
1530#endif
1531#if 0
1532 if (cli_list(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1533 smbwrp_dir_add_old, state) < 0)
1534#else
1535 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1536 smbwrp_dir_add, state) < 0)
1537#endif
1538 {
1539 return os2cli_errno(cli);
1540 }
1541 }
1542
1543 return 0;
1544}
1545
1546/*****************************************************
1547a wrapper for chdir()
1548*******************************************************/
1549int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1550{
1551 unsigned short mode = aDIR;
1552 smbwrp_fileinfo finfo = {0};
1553 if (!cli || !fname)
1554 {
1555 return EINVAL;
1556 }
1557
1558 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1559 if (smbwrp_getattr(srv, cli, &finfo))
1560 {
1561 return os2cli_errno(cli);
1562 }
1563
1564 if (!(finfo.attr & aDIR)) {
1565 return ENOTDIR;
1566 }
1567
1568 return 0;
1569}
1570
1571
1572/*****************************************************
1573a wrapper for mkdir()
1574*******************************************************/
1575int _System smbwrp_mkdir(cli_state * cli, char *fname)
1576{
1577 if (!cli || !fname)
1578 {
1579 return EINVAL;
1580 }
1581
1582 if (!cli_mkdir(cli, fname))
1583 {
1584 return os2cli_errno(cli);
1585 }
1586 return 0;
1587}
1588
1589/*****************************************************
1590a wrapper for rmdir()
1591*******************************************************/
1592int _System smbwrp_rmdir(cli_state * cli, char *fname)
1593{
1594 if (!cli || !fname)
1595 {
1596 return EINVAL;
1597 }
1598
1599 if (!cli_rmdir(cli, fname))
1600 {
1601 return os2cli_errno(cli);
1602 }
1603 return 0;
1604}
1605
1606/*****************************************************
1607set EA for a path
1608*******************************************************/
1609int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1610{
1611 if (!cli || !fname || !name)
1612 {
1613 return EINVAL;
1614 }
1615 if (!cli_set_ea_path(cli, fname, name, value, size))
1616 {
1617 return os2cli_errno(cli);
1618 }
1619 return 0;
1620}
1621
1622/*****************************************************
1623set EA for a file
1624*******************************************************/
1625int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1626{
1627 if (!cli || !file || !name)
1628 {
1629 return EINVAL;
1630 }
1631 if (!cli_set_ea_fnum(cli, file->fd, name, value, size))
1632 {
1633 return os2cli_errno(cli);
1634 }
1635 return 0;
1636}
1637
1638
1639#pragma pack(1)
1640typedef struct _FEA /* fea */
1641{
1642 unsigned char fEA; /* flags */
1643 unsigned char cbName; /* name length not including NULL */
1644 unsigned short cbValue; /* value length */
1645} FEA;
1646
1647typedef struct _FEALIST /* feal */
1648{
1649 unsigned long cbList; /* total bytes of structure including full list */
1650 FEA list[1]; /* variable length FEA structures */
1651} FEALIST;
1652#pragma pack()
1653
1654static int unilistea(cli_state * cli, char *fname, smbwrp_file *file, void * buffer, unsigned long size)
1655{
1656 int fnum, i;
1657 int gotsize = sizeof(unsigned long);
1658 size_t num_eas;
1659 struct ea_struct *ea_list = NULL;
1660 TALLOC_CTX *mem_ctx;
1661 FEA * p;
1662 FEALIST * pfealist;
1663 char * q;
1664
1665 mem_ctx = talloc_init("%d: ealist", _gettid());
1666 pfealist = (FEALIST *)buffer;
1667 pfealist->cbList = 0;
1668
1669 if (file)
1670 {
1671 if (!cli_get_ea_list_fnum(cli, file->fd, mem_ctx, &num_eas, &ea_list))
1672 {
1673 debuglocal(4,"ea_get_fnum list failed - %s\n", cli_errstr(cli));
1674 talloc_destroy(mem_ctx);
1675 return os2cli_errno(cli);
1676 }
1677 }
1678 else
1679 {
1680 if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list))
1681 {
1682 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1683 talloc_destroy(mem_ctx);
1684 return os2cli_errno(cli);
1685 }
1686 }
1687
1688 debuglocal(4,"num_eas = %d\n", num_eas);
1689
1690 // we will count that os/2 max EA size for file is 64kb
1691 p = pfealist->list;
1692 for (i = 0; i < num_eas; i++)
1693 {
1694 int namelen = strlen(ea_list[i].name);
1695 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);
1696 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1697 {
1698 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1699 continue;
1700 }
1701 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1702 if (size >= gotsize)
1703 {
1704 p->fEA = 0;
1705 p->cbName = namelen;
1706 p->cbValue = ea_list[i].value.length;
1707 q = (char *)(p + 1);
1708 strncpy(q, ea_list[i].name, namelen + 1);
1709 q += namelen + 1;
1710 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1711 p = (FEA *)(q + ea_list[i].value.length);
1712 }
1713 }
1714 pfealist->cbList = gotsize;
1715 debuglocal(4,"ret size = %d\n", gotsize);
1716
1717 talloc_destroy(mem_ctx);
1718 return 0;
1719}
1720
1721/*****************************************************
1722lists EA of a path
1723*******************************************************/
1724int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1725{
1726 if (!cli || !fname || !buffer)
1727 {
1728 return EINVAL;
1729 }
1730
1731 debuglocal(4,"EALIst for <%s>\n", fname);
1732 return unilistea(cli, fname, NULL, buffer, size);
1733}
1734
1735/*****************************************************
1736lists EA of a file
1737*******************************************************/
1738int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1739{
1740 if (!cli || !file || !buffer)
1741 {
1742 return EINVAL;
1743 }
1744
1745 debuglocal(4,"FEALIst for <%s>/%d\n", file->fname, file->fd);
1746 return unilistea(cli, NULL, file, buffer, size);
1747}
1748
1749/****************************************************************************
1750Check the space on a device.
1751****************************************************************************/
1752int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1753{
1754 int total, bsize, avail;
1755
1756 if (!cli || !pfsa)
1757 {
1758 return EINVAL;
1759 }
1760
1761 if (!cli_dskattr(cli, &bsize, &total, &avail))
1762 {
1763 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1764 return os2cli_errno(cli);
1765 }
1766
1767 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1768 total, bsize, avail);
1769
1770 // YD currently Samba return it in MB!
1771 pfsa->cSectorUnit = 1;
1772 if (bsize >= 65536)
1773 {
1774 pfsa->cUnit = total*1024;
1775 pfsa->cUnitAvail = avail*1024;
1776 pfsa->cbSector = bsize/1024;
1777 }
1778 else
1779 {
1780 pfsa->cUnit = total;
1781 pfsa->cUnitAvail = avail;
1782 pfsa->cbSector = bsize;
1783 }
1784
1785 return 0;
1786}
1787
Note: See TracBrowser for help on using the repository browser.