source: branches/client-3.0/src/smbwrp.c@ 1006

Last change on this file since 1006 was 1006, checked in by Paul Smedley, 9 years ago

Add support for enabling/disabling encryption - fixes #289

  • Property svn:eol-style set to native
File size: 38.9 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 "rpc_client/cli_pipe.h"
23#include "librpc/gen_ndr/ndr_srvsvc_c.h"
24#include "libsmb/libsmb.h"
25#include "libsmb/clirap.h"
26#include "param.h"
27#include "smb/smbXcli_base.h"
28#include "trans2.h"
29#include "smbwrp.h"
30#include "util.h"
31
32struct smb2_hnd {
33 uint64_t fid_persistent;
34 uint64_t fid_volatile;
35};
36
37/*
38 * Wrapper for cli_errno to return not connected error on negative fd
39 * Now returns an OS/2 return code instead of lerrno.
40 */
41int os2cli_errno(cli_state * cli)
42{
43#if 0 // cli->fd not available in Samba 4.x
44 if (cli->fd == -1)
45 {
46 return maperror( ENOTCONN);
47 }
48#endif
49 return maperror(cli_errno(cli));
50}
51
52void smbwrp_Logging()
53{
54 char slogfile[_MAX_PATH +1] = {0};
55 char slogfilename[] = "log.smbc";
56 char *env = getenv("LOGFILES");
57 if (env != NULL)
58 {
59 strncpy(slogfile, env, sizeof(slogfile) -1);
60 strncat(slogfile, "\\", sizeof(slogfile) - strlen(slogfile) -1);
61 strncat(slogfile, slogfilename, sizeof(slogfile) - strlen(slogfile) -1);
62 }
63 else
64 {
65 strncpy(slogfile, slogfilename, sizeof(slogfile) -1);
66 }
67
68 // init samba for debug messages
69 setup_logging(slogfile, DEBUG_FILE);
70 lp_set_logfile(slogfile);
71 reopen_logs();
72}
73
74const char * smbwrp_getVersion()
75{
76 return samba_version_string();
77}
78
79int _System smbwrp_getclisize(void)
80{
81 return sizeof(struct cli_state);
82}
83
84/*****************************************************
85initialise structures
86*******************************************************/
87int _System smbwrp_init(void)
88{
89 static int initialised = 0;
90 char *p;
91
92 struct loadparm_context *lp_ctx;
93 TALLOC_CTX *frame = talloc_stackframe();
94
95 if (initialised)
96 {
97 return 0;
98 }
99 initialised = 1;
100
101 smb_init_locale();
102
103 if (!lp_load_client(get_dyn_CONFIGFILE())) {
104 debuglocal(0,("Can't load %s, defaults are used!\n",get_dyn_CONFIGFILE()));
105 }
106 load_interfaces();
107
108 if (!init_names())
109 {
110 return 1;
111 }
112
113 if (writeLog())
114 {
115 smbwrp_Logging();
116 }
117
118/*
119 if ((p=smbw_getshared("RESOLVE_ORDER"))) {
120 lp_set_name_resolve_order(p);
121 }
122*/
123 return 0;
124
125}
126
127void smbwrp_initthread(void)
128{
129 /*
130 Block SIGPIPE (from lib/util_sock.c: write())
131 It is not needed and should not stop execution
132 */
133 BlockSignals(True, SIGPIPE);
134}
135
136#if 0
137/*****************************************************
138remove redundent stuff from a filename
139*******************************************************/
140void clean_fname(char *name)
141{
142 char *p, *p2;
143 int l;
144 int modified = 1;
145
146 if (!name) return;
147
148 while (modified) {
149 modified = 0;
150
151 if ((p=strstr(name,"/./"))) {
152 modified = 1;
153 while (*p) {
154 p[0] = p[2];
155 p++;
156 }
157 }
158
159 if ((p=strstr(name,"//"))) {
160 modified = 1;
161 while (*p) {
162 p[0] = p[1];
163 p++;
164 }
165 }
166
167 if (strcmp(name,"/../")==0) {
168 modified = 1;
169 name[1] = 0;
170 }
171
172 if ((p=strstr(name,"/../"))) {
173 modified = 1;
174 for (p2=(p>name?p-1:p);p2>name;p2--) {
175 if (p2[0] == '/') break;
176 }
177 while (*p2) {
178 p2[0] = p2[3];
179 p2++;
180 }
181 }
182
183 if (strcmp(name,"/..")==0) {
184 modified = 1;
185 name[1] = 0;
186 }
187
188 l = strlen(name);
189 p = l>=3?(name+l-3):name;
190 if (strcmp(p,"/..")==0) {
191 modified = 1;
192 for (p2=p-1;p2>name;p2--) {
193 if (p2[0] == '/') break;
194 }
195 if (p2==name) {
196 p[0] = '/';
197 p[1] = 0;
198 } else {
199 p2[0] = 0;
200 }
201 }
202
203 l = strlen(name);
204 p = l>=2?(name+l-2):name;
205 if (strcmp(p,"/.")==0) {
206 if (p == name) {
207 p[1] = 0;
208 } else {
209 p[0] = 0;
210 }
211 }
212
213 if (strncmp(p=name,"./",2) == 0) {
214 modified = 1;
215 do {
216 p[0] = p[2];
217 } while (*p++);
218 }
219
220 l = strlen(p=name);
221 if (l > 1 && p[l-1] == '/') {
222 modified = 1;
223 p[l-1] = 0;
224 }
225 }
226}
227#endif
228
229/*****************************************************
230return a connection to a server
231loosely based on do_connect() from libsmb/clidfs.c
232*******************************************************/
233int _System smbwrp_connect( Resource* pRes, cli_state ** cli)
234{
235 smbwrp_server * srv = &pRes->srv;
236 char * server = srv->server_name;
237 char * share = *(srv->share_name) ? srv->share_name : "IPC$";
238 char * workgroup = srv->workgroup;
239 struct nmb_name called, calling;
240 char *p, *server_n = server;
241 struct cli_state * c;
242 char* dev_type;
243 int loginerror = 0;
244 NTSTATUS status;
245 int max_protocol = lp__client_max_protocol();
246 int port = 0; //NBT_SMB_PORT;
247 int name_type= 0x20;
248 int flags = 0;
249 int signing_state = SMB_SIGNING_DEFAULT;
250 enum protocol_types protocol;
251 const char *name = NULL;
252
253 if (!pRes->krb5support)
254 debuglocal(1,"Connecting to \\\\%s:*********@%s:%s\\%s. Master %s:%d\n", srv->username, workgroup, server, share, srv->master, srv->ifmastergroup);
255 else
256 debuglocal(1,"Connecting to \\\\%s:%s\\%s using kerberos authentication. Master %s:%d\n", workgroup, server, share, srv->master, srv->ifmastergroup);
257
258 if (pRes->krb5support) {
259 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
260 }
261
262 if (pRes->ntlmv1support) {
263 lp_set_cmdline("client ntlmv2 auth","no");
264 }
265
266 if (pRes->encryptionsupport) {
267 signing_state = SMB_SIGNING_REQUIRED;
268 }
269
270 status = cli_connect_nb(
271 server, NULL, port, name_type, NULL,
272 signing_state, flags, &c);
273
274 if (!NT_STATUS_IS_OK(status)) {
275 debuglocal(4,"Connection to %s failed (Error %s)\n",
276 server,
277 nt_errstr(status));
278 return 3;
279 }
280
281 if (max_protocol == PROTOCOL_DEFAULT) {
282 max_protocol = PROTOCOL_LATEST;
283 }
284 DEBUG(4,(" session request ok, c->timeout = %d\n",c->timeout));
285
286 status = smbXcli_negprot(c->conn, c->timeout,
287 lp_client_min_protocol(),
288 max_protocol);
289
290 if (!NT_STATUS_IS_OK(status)) {
291 debuglocal(4,"protocol negotiation failed: %s\n",
292 nt_errstr(status));
293 cli_shutdown(c);
294 return status;
295 }
296
297 protocol = smbXcli_conn_protocol(c->conn);
298
299 switch (protocol) {
300 case PROTOCOL_CORE:
301 name = "CORE";
302 break;
303 case PROTOCOL_COREPLUS:
304 name = "COREPLUS";
305 break;
306 case PROTOCOL_LANMAN1:
307 name = "LANMAN1";
308 break;
309 case PROTOCOL_LANMAN2:
310 name = "LANMAN2";
311 break;
312 case PROTOCOL_NT1:
313 name = "NT1";
314 break;
315 case PROTOCOL_SMB2_02:
316 name = "SMB2_02";
317 break;
318 case PROTOCOL_SMB2_10:
319 name = "SMB2_10";
320 break;
321 case PROTOCOL_SMB2_22:
322 name = "SMB2_22";
323 break;
324 case PROTOCOL_SMB2_24:
325 name = "SMB2_24";
326 break;
327 case PROTOCOL_SMB3_00:
328 name = "SMB3_00";
329 break;
330 case PROTOCOL_SMB3_02:
331 name = "SMB3_02";
332 break;
333 case PROTOCOL_SMB3_10:
334 name = "SMB3_10";
335 break;
336 case PROTOCOL_SMB3_11:
337 name = "SMB3_11";
338 break;
339 default:
340 name = "Unknown";
341 break;
342 }
343
344 debuglocal(4,"Server supports %s protocol\n", name);
345
346 if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) {
347 /* Ensure we ask for some initial credits. */
348 smb2cli_conn_set_max_credits(c->conn, DEFAULT_SMB2_MAX_CREDITS);
349 }
350
351 if (!NT_STATUS_IS_OK(cli_session_setup(c, srv->username,
352 srv->password, strlen(srv->password),
353 srv->password, strlen(srv->password),
354 workgroup))) {
355 debuglocal(4,"%s/******** login failed\n", srv->username);
356 loginerror = 1; // save the login error
357
358 /* try an anonymous login if it failed */
359
360 /* If a password was not supplied then
361 * try again with a null username. */
362 if (srv->password[0] || !srv->username[0] ||
363 pRes->krb5support ||
364 !NT_STATUS_IS_OK(status = cli_session_setup(c, "",
365 "", 0,
366 "", 0,
367 workgroup))) {
368 debuglocal(1,"session setup failed: %s\n",
369 nt_errstr(status));
370
371 if ((NT_STATUS_EQUAL(status,
372 NT_STATUS_MORE_PROCESSING_REQUIRED)) ||
373 NT_STATUS_EQUAL(status,
374 NT_STATUS_INTERNAL_ERROR)){
375 debuglocal(4,"did you forget to run kinit?\n");
376 } else
377 debuglocal(4,"Anonymous login failed\n");
378
379 cli_shutdown(c);
380 return 6;
381 }
382 debuglocal(4,"Anonymous login successful\n");
383 }
384
385 if (!NT_STATUS_IS_OK(status)) {
386 debuglocal(4,"cli_init_creds() failed\n");
387 cli_shutdown(c);
388 // if loginerror is != 0 means normal login failed, but anonymous login worked
389 if (loginerror !=0)
390 return 6;
391 else
392 return 7;
393 }
394
395 debuglocal(4," session setup ok. Sending tconx <%s> <********>\n", share);
396
397#if 0 /* Causes connections to fail with Samba 4.x */
398 // YD ticket:58 we need to check resource type to avoid connecting to printers.
399 // dev type is set to IPC for IPC$, A: for everything else (printers use LPT1:)
400 if (!strcmp( share, "IPC$"))
401 dev_type = "IPC";
402 else
403 dev_type = "A:";
404
405 if (!NT_STATUS_IS_OK(cli_tcon_andx(c, share, dev_type,
406 srv->password, strlen(srv->password)+1))) {
407 cli_shutdown(c);
408 // if loginerror is != 0 means normal login failed, but anonymous login worked
409 if (loginerror !=0)
410 return 6;
411 else
412 return 7;
413 }
414#endif
415
416 /* must be a normal share */
417
418 status = cli_tree_connect(c, share, "?????",
419 srv->password, strlen(srv->password)+1);
420 if (!NT_STATUS_IS_OK(status)) {
421 debuglocal(4,"tree connect failed: %s\n", nt_errstr(status));
422 cli_shutdown(c);
423 return status;
424 }
425
426 if (pRes->encryptionsupport) {
427 debuglocal(4,"Attempting to force encryption\n");
428 status = cli_cm_force_encryption(c,
429 srv->username,
430 srv->password,
431 workgroup,
432 share);
433 if (!NT_STATUS_IS_OK(status)) {
434 debuglocal(4,"cli_cm_force_encryption failed: %s\n", nt_errstr(status));
435 cli_shutdown(c);
436 return status;
437 }
438 debuglocal(4,"Forcing encryption succeeded!\n");
439 }
440
441 debuglocal(4," tconx ok.\n");
442
443 // save cli_state pointer
444 *cli = c;
445
446 return 0;
447}
448
449/*****************************************************
450close a connection to a server
451*******************************************************/
452void _System smbwrp_disconnect( Resource* pRes, cli_state * cli)
453{
454 if (pRes && cli)
455 {
456 // this call will free all buffers, close handles and free cli mem
457 cli_shutdown( cli);
458 }
459}
460
461
462
463/*****************************************************
464a wrapper for open()
465*******************************************************/
466int _System smbwrp_open(cli_state * cli, smbwrp_file * file)
467{
468 uint16_t fd = 0;
469
470 if (!cli || !file || !*file->fname)
471 {
472 return maperror(EINVAL);
473 }
474 if (file->denymode < DENY_ALL || file->denymode > DENY_NONE)
475 {
476 file->denymode = DENY_NONE;
477 }
478
479 debuglocal(4,"cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
480 if (!NT_STATUS_IS_OK(cli_open(cli, file->fname, file->openmode, file->denymode, &fd)))
481 {
482 return os2cli_errno(cli);
483 }
484 file->fd = fd;
485 file->updatetime = 0;
486 file->offset = 0;
487 return 0;
488}
489
490/*****************************************************
491a wrapper for read()
492*******************************************************/
493int _System smbwrp_read(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
494{
495 int ret;
496
497 if (!cli || !file || !buf || !result)
498 {
499 return maperror(EINVAL);
500 }
501 size_t nread;
502 *result = 0;
503 ret = cli_read(cli, file->fd, buf, file->offset, count, &nread);
504 if (ret == -1)
505 {
506 debuglocal(4," smbwrp_read - cli_read ret = %d\n",ret);
507 return os2cli_errno(cli);
508 }
509
510 file->offset += nread;
511 *result = nread;
512 debuglocal(4," smbwrp_read successful, nread = %d, ret = %d\n",nread,ret);
513 return 0;
514}
515
516
517
518/*****************************************************
519a wrapper for write()
520*******************************************************/
521int _System smbwrp_write(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
522{
523 NTSTATUS status;
524 size_t ret;
525
526 if (!cli || !file || !buf || !result)
527 {
528 return maperror(EINVAL);
529 }
530
531 *result = 0;
532//debuglocal(1,("Write %x %d %lld %d", cli, file->fd, file->offset, count));
533 status = cli_writeall(cli, file->fd, 0, buf, file->offset, count, &ret);
534 if (!NT_STATUS_IS_OK(status)) {
535 return os2cli_errno(cli);
536 }
537
538 file->updatetime = 1;
539 file->offset += ret;
540 *result = ret;
541 return 0;
542}
543
544/*****************************************************
545a wrapper for close()
546*******************************************************/
547int _System smbwrp_close(cli_state * cli, smbwrp_file * file)
548{
549 int rc = 0;
550 if (!cli || !file)
551 {
552 return maperror(EINVAL);
553 }
554
555 debuglocal(4,"smpwrp_close updatetime: %d\n", file->updatetime);
556
557 if (file->updatetime == 1)
558 {
559 file->mtime = time(NULL);
560 debuglocal(4,"cli_close new mtime %lu\n", file->mtime);
561 }
562
563 if (!NT_STATUS_IS_OK(cli_close(cli, file->fd)))
564 {
565 rc = os2cli_errno(cli);
566 }
567
568 if (!rc && (file->openattr || file->mtime || file->ctime))
569 {
570 debuglocal(4,"Set pathinfo on close %s %08x %d %d\n", file->fname, file->openattr, file->mtime, file->ctime);
571 if (!NT_STATUS_IS_OK(cli_setpathinfo_basic(cli, file->fname, file->ctime, 0, file->mtime, 0, file->openattr)))
572 {
573 debuglocal(4,"Set pathinfo on close failed %d\n", os2cli_errno(cli));
574 //rc = os2cli_errno(cli);
575 }
576 }
577
578 file->openattr = 0;
579 file->mtime = 0;
580 file->ctime = 0;
581 file->updatetime = 0;
582 file->fd = -1;
583 file->offset = 0;
584 *file->fname = 0;
585 return rc;
586}
587
588int _System smbwrp_setfilesize(cli_state * cli, smbwrp_file * file, long long newsize)
589{
590 int rc = 0;
591 if (!cli || !file)
592 {
593 return maperror(EINVAL);
594 }
595
596 debuglocal(4,"smbwrp_setnewfilesize(%s) %lld\n", file->fname, newsize);
597 if (!NT_STATUS_IS_OK(cli_ftruncate(cli, file->fd, newsize)))
598 {
599 debuglocal(4,"smbwrp_setnewfilesize - cli_ftruncate errno = %d\n",cli_errno(cli));
600#if 0 /* This is all sorts of bad - if cli_ftruncate fails, it creates a new file in it's place */
601 if (newsize)
602 {
603 rc = os2cli_errno(cli);
604 }
605
606 if (!NT_STATUS_IS_OK(cli_close(cli, file->fd)))
607 {
608 return os2cli_errno(cli);
609 }
610 uint16_t fd = 0;
611 file->fd = -1;
612 file->offset = 0;
613 file->openmode &= ~(O_CREAT | O_EXCL);
614 file->openmode |= O_TRUNC;
615 debuglocal(4,"smbwrp_setnewfilesize : cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
616 if (!NT_STATUS_IS_OK(cli_open(cli, file->fname, file->openmode, file->denymode, &fd)))
617 {
618 return os2cli_errno(cli);
619 }
620 file->fd = fd;
621#endif
622 }
623 return 0;
624}
625
626/*****************************************************
627a wrapper for rename()
628*******************************************************/
629int _System smbwrp_rename(cli_state * cli, char *oldname, char *newname)
630{
631 if (!cli || !oldname || !newname)
632 {
633 return maperror(EINVAL);
634 }
635
636 debuglocal(1,"Rename <%s> -> <%s>\n", oldname, newname);
637 if (!NT_STATUS_IS_OK(cli_rename(cli, oldname, newname)))
638 {
639 return os2cli_errno(cli);
640 }
641 return 0;
642}
643
644
645/*****************************************************
646a wrapper for chmod()
647*******************************************************/
648int _System smbwrp_setattr(cli_state * cli, smbwrp_fileinfo *finfo)
649{
650 if (!cli || !finfo || !*finfo->fname)
651 {
652 return maperror(EINVAL);
653 }
654
655debuglocal(4,"Setting on <%s> attr %04x, time %lu (timezone /%lu\n", finfo->fname, finfo->attr, finfo->mtime, finfo->mtime + get_time_zone(finfo->mtime));
656 // we already have gmt time, so no need to add timezone
657 // if (!cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime + (finfo->mtime == 0 ? 0 : get_time_zone(finfo->mtime)))
658 if (!NT_STATUS_IS_OK(cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime))
659 && !NT_STATUS_IS_OK(cli_setatr(cli, finfo->fname, finfo->attr, 0)))
660 {
661 return os2cli_errno(cli);
662 }
663 return 0;
664}
665
666/*****************************************************
667a wrapper for unlink()
668*******************************************************/
669int _System smbwrp_unlink(cli_state * cli, const char *fname)
670{
671 if (!cli || !fname)
672 {
673 return maperror(EINVAL);
674 }
675#if 0
676 if (strncmp(cli->dev, "LPT", 3) == 0)
677 {
678 int job = smbw_stat_printjob(cli, fname, NULL, NULL);
679 if (job == -1)
680 {
681 goto failed;
682 }
683 if (cli_printjob_del(cli, job) != 0)
684 {
685 goto failed;
686 }
687 } else
688#endif
689 if (!NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN)))
690 {
691 return os2cli_errno(cli);
692 }
693 return 0;
694}
695
696/*****************************************************
697a wrapper for lseek()
698*******************************************************/
699int _System smbwrp_lseek(cli_state * cli, smbwrp_file * file, int whence, long long offset)
700{
701 off_t size;
702 if (!cli || !file)
703 {
704 return maperror(EINVAL);
705 }
706
707 debuglocal(4,"lseek %d %lld %lld\n", whence, offset, file->offset);
708
709 switch (whence) {
710 case SEEK_SET:
711 if (offset < 0)
712 {
713 return maperror(EINVAL);
714 }
715 file->offset = offset;
716 break;
717 case SEEK_CUR:
718 file->offset += offset;
719 break;
720 case SEEK_END:
721 if (offset > 0)
722 {
723 return maperror(EINVAL);
724 }
725 if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(cli, file->fd,
726 NULL, &size, NULL, NULL, NULL,
727 NULL, NULL)) &&
728 !NT_STATUS_IS_OK(cli_getattrE(cli, file->fd,
729 NULL, &size, NULL, NULL, NULL)))
730 {
731 return os2cli_errno(cli);
732 }
733 file->offset = size + offset;
734 break;
735 default: return maperror(EINVAL);
736 }
737
738 return 0;
739}
740
741/*****************************************************
742try to do a QPATHINFO and if that fails then do a getatr
743this is needed because win95 sometimes refuses the qpathinfo
744loosely based on SMBC_getatr() from source3/libsmb/libsmb_file.c
745*******************************************************/
746int _System smbwrp_getattr(smbwrp_server *srv, cli_state * cli, smbwrp_fileinfo *finfo)
747{
748 SMB_INO_T ino = 0;
749 struct timespec ctime;
750 struct timespec mtime;
751 struct timespec atime;
752
753 if (!cli || !finfo || !*finfo->fname)
754 {
755 return maperror(EINVAL);
756 }
757 debuglocal(4,"getattr %d %d <%s>\n", smb1cli_conn_capabilities(cli->conn) & CAP_NOPATHINFO2, smb1cli_conn_capabilities(cli->conn) & CAP_NT_SMBS, finfo->fname);
758
759 if (NT_STATUS_IS_OK(cli_qpathinfo2(cli, finfo->fname, &ctime, &atime, &mtime, NULL,
760 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino)))
761 {
762 finfo->attr &= 0x7F;
763 finfo->ctime = convert_timespec_to_time_t(ctime);
764 finfo->atime = convert_timespec_to_time_t(atime);
765 finfo->mtime = convert_timespec_to_time_t(mtime);
766 return 0;
767 }
768
769#if 0 // cli->fd not available in Samba 4.x
770 if (cli->fd == -1)
771 {
772 /* fd == -1 means the connection is broken */
773 return maperror(ENOTCONN);
774 }
775#endif
776
777 debuglocal(4, "smbwrp_getattr, calling cli_qpathinfo3\n");
778 if (NT_STATUS_IS_OK(cli_qpathinfo3(cli, finfo->fname, &ctime, &atime, &mtime, NULL,
779 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino)))
780 {
781 finfo->attr &= 0x7F;
782 finfo->ctime = convert_timespec_to_time_t(ctime);
783 finfo->atime = convert_timespec_to_time_t(atime);
784 finfo->mtime = convert_timespec_to_time_t(mtime);
785 return 0;
786 }
787
788 /* If the path is not on a share (it is a workgroup or a server),
789 * then cli_qpathinfo2 obviously fails. Return some fake information
790 * about the directory.
791 */
792 if ( *srv->server_name == 0
793#if 0 /* Causes crashes with Samba 4.x */
794 || (strcmp(cli->dev,"IPC") == 0)
795#endif
796 || *srv->share_name == 0
797 || (stricmp(srv->share_name,"IPC$") == 0)
798#if 0 /* Causes crashes with Samba 4.x */
799 || (strncmp(cli->dev,"LPT",3) == 0)
800#endif
801 )
802 {
803 debuglocal(4,"getattr not a share.\n");
804 *(time_t *)&finfo->ctime = time (NULL);
805 *(time_t *)&finfo->atime = time (NULL);
806 *(time_t *)&finfo->mtime = time (NULL);
807 finfo->size = 0;
808 finfo->easize = 0;
809 finfo->attr = aDIR;
810 return 0;
811 }
812
813 /* if this is NT then don't bother with the getatr */
814 if (smb1cli_conn_capabilities(cli->conn) & CAP_NT_SMBS/* && !(smb1cli_conn_capabilities(cli->conn) & CAP_NOPATHINFO2)*/)
815 {
816 int ret = cli_errno(cli);
817 // cli_qpathinfo* reports EINVAL when path of given file not exists
818 // thus there is no real situation when EINVAL should be returned to
819 // client at this point, we just replace it to ENOTDIR
820 if (ret == EINVAL)
821 {
822 ret = ENOTDIR;
823 }
824 return maperror(ret);
825 }
826
827 if (NT_STATUS_IS_OK(cli_getatr(cli, finfo->fname, (unsigned short *)&finfo->attr, &finfo->size, (time_t *)&finfo->mtime)))
828 {
829//debuglocal(2,("gotattr1 %08x <%s>\n", finfo->attr, finfo->fname));
830 finfo->mtime -= get_time_zone(finfo->mtime);
831 finfo->atime = finfo->atime; //was mtime
832 finfo->ctime = finfo->ctime; //was mtime
833 return 0;
834 }
835 return os2cli_errno(cli);
836}
837
838/*****************************************************
839try to do a QPATHINFO and if that fails then do a getatr
840this is needed because win95 sometimes refuses the qpathinfo
841*******************************************************/
842int _System smbwrp_fgetattr(cli_state * cli, smbwrp_file *file, smbwrp_fileinfo *finfo)
843{
844 struct timespec ctime;
845 struct timespec mtime;
846 struct timespec atime;
847 SMB_INO_T ino = 0;
848
849 if (!cli || !file || !finfo)
850 {
851 return maperror(EINVAL);
852 }
853
854 strncpy(finfo->fname, file->fname, sizeof(finfo->fname) - 1);
855 if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(cli, file->fd,
856 (unsigned short *)&finfo->attr, (off_t *)&finfo->size, &ctime, &atime, &mtime, NULL,
857 &ino)))
858 {
859 if (!NT_STATUS_IS_OK(cli_getattrE(cli, file->fd,
860 (unsigned short *)&finfo->attr, (&finfo->size), (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime)))
861 {
862 return os2cli_errno(cli);
863 }
864 else
865 {
866 finfo->ctime -= get_time_zone(finfo->ctime);
867 finfo->atime -= get_time_zone(finfo->atime);
868 finfo->mtime -= get_time_zone(finfo->mtime);
869 }
870 }
871 else
872 {
873 finfo->ctime = convert_timespec_to_time_t(ctime);
874 finfo->atime = convert_timespec_to_time_t(atime);
875 finfo->mtime = convert_timespec_to_time_t(mtime);
876 }
877
878 return 0;
879}
880
881// =============================DIRECTORY ROUTINES============================
882
883/*****************************************************
884add a entry to a directory listing
885*******************************************************/
886static NTSTATUS smbwrp_dir_add(const char* mnt, smbwrp_fileinfo *finfo, const char *mask, void *state)
887{
888 if (state && finfo)
889 {
890 filelist_state * st = (filelist_state *)state;
891 char fullname[ _MAX_PATH] = {0};
892 debuglocal(8,"adding <%s> %d %d %d\n", finfo->fname, sizeof(st->finfo), st->datalen, sizeof(st->finfo.fname));
893 memcpy(&st->finfo, finfo, sizeof(st->finfo));
894 strncpy(fullname, st->dir, strlen(st->dir));
895 strncat(fullname, finfo->fname, sizeof(fullname) - strlen(fullname) -1);
896 strncpy(st->finfo.fname, fullname, sizeof(st->finfo.fname));
897 getfindinfoL( st->pConn, st->plist, &st->finfo, st->ulAttribute, st->dir_mask);
898 }
899}
900
901static void smbwrp_special_add(const char * name, void * state)
902{
903 smbwrp_fileinfo finfo = {0};
904
905 if (!name)
906 {
907 return;
908 }
909
910 ZERO_STRUCT(finfo);
911
912 strncpy(finfo.fname, name, sizeof(finfo.fname) - 1);
913 finfo.attr = aRONLY | aDIR;
914
915 smbwrp_dir_add("", &finfo, NULL, state);
916}
917
918static void smbwrp_printjob_add(struct print_job_info *job, void * state)
919{
920 smbwrp_fileinfo finfo = {0};
921
922 ZERO_STRUCT(finfo);
923
924//printf("Printjob <%s>\n", job->name);
925
926 strncpy(finfo.fname, job->name, sizeof(finfo.fname) - 1);
927 finfo.mtime = job->t - get_time_zone(job->t);
928 finfo.atime = finfo.atime; //was mtime
929 finfo.ctime = finfo.ctime; //was mtime
930 finfo.attr = aRONLY;
931 finfo.size = job->size;
932
933 smbwrp_dir_add("", &finfo, NULL, state);
934}
935
936static void smbwrp_share_add(const char *share, uint32_t type,
937 const char *comment, void *state)
938{
939 smbwrp_fileinfo finfo = {0};
940
941 // strip administrative names and printers from list
942 if (type == STYPE_PRINTQ || strcmp(share,"IPC$") == 0) return;
943
944 ZERO_STRUCT(finfo);
945
946 strncpy(finfo.fname, share, sizeof(finfo.fname) - 1);
947 finfo.attr = aRONLY | aDIR;
948
949 smbwrp_dir_add("", &finfo, NULL, state);
950}
951
952/***************************************************************
953 Wrapper that allows SMB2 to list a directory.
954 Synchronous only.
955 Based on cli_smb2_list
956***************************************************************/
957
958NTSTATUS list_files_smb2(struct cli_state *cli,
959 const char *pathname,
960 uint16_t attribute,
961 NTSTATUS (*fn)(const char *,
962 struct smbwrp_fileinfo *,
963 const char *,
964 void *),
965 void *state)
966{
967 NTSTATUS status;
968 uint16_t fnum = 0xffff;
969 char *parent_dir = NULL;
970 const char *mask = NULL;
971 struct smb2_hnd *ph = NULL;
972 bool processed_file = false;
973 TALLOC_CTX *frame = talloc_stackframe();
974 TALLOC_CTX *subframe = NULL;
975 bool mask_has_wild;
976 void *dircachectx = NULL;
977 smbwrp_fileinfo wrpfinfo;
978
979 //Init cache - don't know number of files so init with 128
980 dircachectx = dircache_write_begin(state, 128);
981
982 if (smbXcli_conn_has_async_calls(cli->conn)) {
983 /*
984 * Can't use sync call while an async call is in flight
985 */
986 status = NT_STATUS_INVALID_PARAMETER;
987 goto fail;
988 }
989
990 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
991 status = NT_STATUS_INVALID_PARAMETER;
992 goto fail;
993 }
994
995 /* Get the directory name. */
996 if (!windows_parent_dirname(frame,
997 pathname,
998 &parent_dir,
999 &mask)) {
1000 status = NT_STATUS_NO_MEMORY;
1001 goto fail;
1002 }
1003
1004 mask_has_wild = ms_has_wild(mask);
1005
1006 status = cli_smb2_create_fnum(cli,
1007 parent_dir,
1008 0, /* create_flags */
1009 SEC_DIR_LIST|SEC_DIR_READ_ATTRIBUTE,/* desired_access */
1010 FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
1011 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
1012 FILE_OPEN, /* create_disposition */
1013 FILE_DIRECTORY_FILE, /* create_options */
1014 &fnum,
1015 NULL);
1016
1017 if (!NT_STATUS_IS_OK(status)) {
1018 goto fail;
1019 }
1020
1021 status = map_fnum_to_smb2_handle(cli,
1022 fnum,
1023 &ph);
1024 if (!NT_STATUS_IS_OK(status)) {
1025 goto fail;
1026 }
1027
1028 do {
1029 uint8_t *dir_data = NULL;
1030 uint32_t dir_data_length = 0;
1031 uint32_t next_offset = 0;
1032 subframe = talloc_stackframe();
1033
1034 status = smb2cli_query_directory(cli->conn,
1035 cli->timeout,
1036 cli->smb2.session,
1037 cli->smb2.tcon,
1038 SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
1039 0, /* flags */
1040 0, /* file_index */
1041 ph->fid_persistent,
1042 ph->fid_volatile,
1043 mask,
1044 0xffff,
1045 subframe,
1046 &dir_data,
1047 &dir_data_length);
1048
1049 if (!NT_STATUS_IS_OK(status)) {
1050 if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES)) {
1051 break;
1052 }
1053 goto fail;
1054 }
1055
1056 do {
1057 struct file_info *finfo = talloc_zero(subframe,
1058 struct file_info);
1059
1060 if (finfo == NULL) {
1061 status = NT_STATUS_NO_MEMORY;
1062 goto fail;
1063 }
1064
1065 status = parse_finfo_id_both_directory_info(dir_data,
1066 dir_data_length,
1067 finfo,
1068 &next_offset);
1069
1070 if (!NT_STATUS_IS_OK(status)) {
1071 goto fail;
1072 }
1073
1074 if (dir_check_ftype((uint32_t)finfo->mode,
1075 (uint32_t)attribute)) {
1076 /*
1077 * Only process if attributes match.
1078 * On SMB1 server does this, so on
1079 * SMB2 we need to emulate in the
1080 * client.
1081 *
1082 * https://bugzilla.samba.org/show_bug.cgi?id=10260
1083 */
1084 processed_file = true;
1085
1086 //as samba and this client have different finfo, we need to convert
1087 memset(&wrpfinfo, 0, sizeof(wrpfinfo));
1088 wrpfinfo.size = finfo[0].size;
1089 wrpfinfo.attr = finfo[0].mode;
1090 wrpfinfo.ctime = convert_timespec_to_time_t(finfo[0].ctime_ts);
1091 wrpfinfo.mtime = convert_timespec_to_time_t(finfo[0].mtime_ts);
1092 wrpfinfo.atime = convert_timespec_to_time_t(finfo[0].atime_ts);
1093 wrpfinfo.easize = finfo[0].easize;
1094 strncpy(wrpfinfo.fname, finfo[0].name, sizeof(wrpfinfo.fname) -1);
1095
1096 status = fn(cli->dfs_mountpoint,
1097 &wrpfinfo,
1098 pathname,
1099 state);
1100 // Also add the entry to the cache.
1101 dircache_write_entry(dircachectx, &wrpfinfo);
1102
1103 if (!NT_STATUS_IS_OK(status)) {
1104 /* not sure why this is required on OS/2 */
1105 if (status != NT_STATUS_WAIT_1)
1106 break;
1107 }
1108 }
1109
1110 TALLOC_FREE(finfo);
1111
1112 /* Move to next entry. */
1113 if (next_offset) {
1114 dir_data += next_offset;
1115 dir_data_length -= next_offset;
1116 }
1117 } while (next_offset != 0);
1118
1119 TALLOC_FREE(subframe);
1120
1121 if (!mask_has_wild) {
1122 /*
1123 * MacOSX 10 doesn't set STATUS_NO_MORE_FILES
1124 * when handed a non-wildcard path. Do it
1125 * for the server (with a non-wildcard path
1126 * there should only ever be one file returned.
1127 */
1128 status = STATUS_NO_MORE_FILES;
1129 break;
1130 }
1131
1132 } while (NT_STATUS_IS_OK(status));
1133
1134 if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES)) {
1135 status = NT_STATUS_OK;
1136 }
1137
1138 if (NT_STATUS_IS_OK(status) && !processed_file) {
1139 /*
1140 * In SMB1 findfirst returns NT_STATUS_NO_SUCH_FILE
1141 * if no files match. Emulate this in the client.
1142 */
1143 status = NT_STATUS_NO_SUCH_FILE;
1144 }
1145 dircache_write_end(dircachectx);
1146 fail:
1147
1148 if (fnum != 0xffff) {
1149 cli_smb2_close_fnum(cli, fnum);
1150 }
1151 TALLOC_FREE(subframe);
1152 TALLOC_FREE(frame);
1153 return status;
1154}
1155
1156
1157/****************************************************************************
1158 Do a directory listing, calling fn on each file found.
1159 Modified from cli_list
1160****************************************************************************/
1161static int list_files(struct cli_state *cli, const char *mask, uint16_t attribute,
1162 void (*fn)(const char *, smbwrp_fileinfo *, const char *,
1163 void *), void *state)
1164{
1165 TALLOC_CTX *frame = talloc_stackframe();
1166 struct event_context *ev;
1167 struct tevent_req *req;
1168 NTSTATUS status = NT_STATUS_NO_MEMORY;
1169 struct file_info *finfo;
1170 size_t i, num_finfo;
1171 uint16_t info_level;
1172 void *dircachectx = NULL;
1173 smbwrp_fileinfo wrpfinfo;
1174
1175 /* Try to get the listing from cache. */
1176 if (dircache_list_files(fn, state, &num_finfo))
1177 {
1178 /* Got from cache. */
1179 return(num_finfo);
1180 }
1181
1182 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1183 debuglocal(4,"SMB2 detected, calling list_files_smb2()\n");
1184 return list_files_smb2(cli, mask, attribute, fn, state);
1185 }
1186
1187 if (smbXcli_conn_has_async_calls(cli->conn)) {
1188 /*
1189 * Can't use sync call while an async call is in flight
1190 */
1191 status = NT_STATUS_INVALID_PARAMETER;
1192 goto fail;
1193 }
1194 ev = samba_tevent_context_init(frame);
1195 if (ev == NULL) {
1196 goto fail;
1197 }
1198
1199 info_level = (smb1cli_conn_capabilities(cli->conn) & CAP_NT_SMBS)
1200 ? SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_EA_SIZE;
1201
1202 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, mask);
1203
1204 req = cli_list_send(frame, ev, cli, mask, attribute, info_level);
1205 if (req == NULL) {
1206 goto fail;
1207 }
1208 if (!tevent_req_poll(req, ev)) {
1209 status = map_nt_error_from_unix(errno);
1210 goto fail;
1211 }
1212
1213 status = cli_list_recv(req, frame, &finfo, &num_finfo);
1214 if (!NT_STATUS_IS_OK(status)) {
1215 goto fail;
1216 }
1217
1218 dircachectx = dircache_write_begin(state, num_finfo);
1219
1220 debuglocal(4,"list_files: got %d files\n", num_finfo);
1221
1222
1223 for (i=0; i<num_finfo; i++) {
1224 //as samba and this client have different finfo, we need to convert
1225 memset(&wrpfinfo, 0, sizeof(wrpfinfo));
1226 wrpfinfo.size = finfo[i].size;
1227 wrpfinfo.attr = finfo[i].mode;
1228 wrpfinfo.ctime = convert_timespec_to_time_t(finfo[i].ctime_ts);
1229 wrpfinfo.mtime = convert_timespec_to_time_t(finfo[i].mtime_ts);
1230 wrpfinfo.atime = convert_timespec_to_time_t(finfo[i].atime_ts);
1231 wrpfinfo.easize = finfo[i].easize;
1232 strncpy(wrpfinfo.fname, finfo[i].name, sizeof(wrpfinfo.fname) -1);
1233
1234 fn(cli->dfs_mountpoint, &wrpfinfo, mask, state);
1235 // Also add the entry to the cache.
1236 dircache_write_entry(dircachectx, &wrpfinfo);
1237 }
1238
1239 dircache_write_end(dircachectx);
1240 fail:
1241 TALLOC_FREE(frame);
1242 return num_finfo;
1243}
1244
1245/*****************************************************
1246open a directory on the server
1247*******************************************************/
1248int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1249{
1250 if (!srv || !cli || !state || !*state->mask)
1251 {
1252 return maperror(EINVAL);
1253 }
1254 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);
1255 if (*srv->workgroup == 0 && *srv->server_name == 0)
1256 {
1257 smbwrp_special_add(".", state);
1258 smbwrp_special_add("..", state);
1259 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1260 smbwrp_share_add, state);
1261 } else
1262 if (*srv->server_name == 0)
1263 {
1264 smbwrp_special_add(".", state);
1265 smbwrp_special_add("..", state);
1266
1267 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1268 smbwrp_share_add, state);
1269 } else
1270#if 0 /* Causes crashes with Samba 4.x */
1271 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1272#else
1273 if (/*(strcmp(cli->dev,"IPC") == 0) ||*/ *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1274#endif
1275 {
1276 smbwrp_special_add(".", state);
1277 smbwrp_special_add("..", state);
1278
1279 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1280 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1281 {
1282 return os2cli_errno(cli);
1283 }
1284 } else
1285#if 0 /* Causes crashes with Samba 4.x */
1286 if (strncmp(cli->dev,"LPT",3) == 0)
1287 {
1288 smbwrp_special_add(".", state);
1289 smbwrp_special_add("..", state);
1290 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1291 {
1292 return os2cli_errno(cli);
1293 }
1294 }
1295 else
1296#endif
1297 {
1298 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1299 smbwrp_dir_add, state) < 0)
1300 {
1301 return os2cli_errno(cli);
1302 }
1303 }
1304
1305 return 0;
1306}
1307
1308/*****************************************************
1309a wrapper for chdir()
1310*******************************************************/
1311int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1312{
1313 unsigned short mode = aDIR;
1314 smbwrp_fileinfo finfo = {0};
1315 if (!cli || !fname)
1316 {
1317 return maperror(EINVAL);
1318 }
1319
1320 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1321 if (smbwrp_getattr(srv, cli, &finfo))
1322 {
1323 return os2cli_errno(cli);
1324 }
1325
1326 if (!(finfo.attr & aDIR)) {
1327 return maperror(ENOTDIR);
1328 }
1329
1330 return 0;
1331}
1332
1333
1334/*****************************************************
1335a wrapper for mkdir()
1336*******************************************************/
1337int _System smbwrp_mkdir(cli_state * cli, char *fname)
1338{
1339 if (!cli || !fname)
1340 {
1341 return maperror(EINVAL);
1342 }
1343
1344 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname)))
1345 {
1346 return os2cli_errno(cli);
1347 }
1348 return 0;
1349}
1350
1351/*****************************************************
1352a wrapper for rmdir()
1353*******************************************************/
1354int _System smbwrp_rmdir(cli_state * cli, char *fname)
1355{
1356 if (!cli || !fname)
1357 {
1358 return maperror(EINVAL);
1359 }
1360
1361 if (!NT_STATUS_IS_OK(cli_rmdir(cli, fname)))
1362 {
1363 return os2cli_errno(cli);
1364 }
1365 return 0;
1366}
1367
1368/*****************************************************
1369set EA for a path
1370*******************************************************/
1371int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1372{
1373 if (!cli || !fname || !name)
1374 {
1375 return maperror(EINVAL);
1376 }
1377 if (!NT_STATUS_IS_OK(cli_set_ea_path(cli, fname, name, value, size)))
1378 {
1379 return os2cli_errno(cli);
1380 }
1381 return 0;
1382}
1383
1384/*****************************************************
1385set EA for a file
1386*******************************************************/
1387int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1388{
1389 if (!cli || !file || !name)
1390 {
1391 return maperror(EINVAL);
1392 }
1393 if (!NT_STATUS_IS_OK(cli_set_ea_fnum(cli, file->fd, name, value, size)))
1394 {
1395 return os2cli_errno(cli);
1396 }
1397 return 0;
1398}
1399
1400
1401#pragma pack(1)
1402typedef struct _FEA /* fea */
1403{
1404 unsigned char fEA; /* flags */
1405 unsigned char cbName; /* name length not including NULL */
1406 unsigned short cbValue; /* value length */
1407} FEA;
1408
1409typedef struct _FEALIST /* feal */
1410{
1411 unsigned long cbList; /* total bytes of structure including full list */
1412 FEA list[1]; /* variable length FEA structures */
1413} FEALIST;
1414#pragma pack()
1415
1416static int unilistea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1417{
1418 int fnum, i;
1419 int gotsize = sizeof(unsigned long);
1420 size_t num_eas;
1421 struct ea_struct *ea_list = NULL;
1422 TALLOC_CTX *mem_ctx;
1423 FEA * p;
1424 FEALIST * pfealist;
1425 char * q;
1426
1427 mem_ctx = talloc_init("%d: ealist", _gettid());
1428 pfealist = (FEALIST *)buffer;
1429 pfealist->cbList = 0;
1430
1431 if (!NT_STATUS_IS_OK(cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)))
1432 {
1433 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1434 talloc_destroy(mem_ctx);
1435 return os2cli_errno(cli);
1436 }
1437
1438 debuglocal(4,"num_eas = %d\n", num_eas);
1439
1440 // we will count that os/2 max EA size for file is 64kb
1441 p = pfealist->list;
1442 for (i = 0; i < num_eas; i++)
1443 {
1444 int namelen = strlen(ea_list[i].name);
1445 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);
1446 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1447 {
1448 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1449 continue;
1450 }
1451 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1452 if (size >= gotsize)
1453 {
1454 p->fEA = 0;
1455 p->cbName = namelen;
1456 p->cbValue = ea_list[i].value.length;
1457 q = (char *)(p + 1);
1458 strncpy(q, ea_list[i].name, namelen + 1);
1459 q += namelen + 1;
1460 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1461 p = (FEA *)(q + ea_list[i].value.length);
1462 }
1463 }
1464 pfealist->cbList = gotsize;
1465 debuglocal(4,"ret size = %d\n", gotsize);
1466
1467 talloc_destroy(mem_ctx);
1468 return 0;
1469}
1470
1471/*****************************************************
1472lists EA of a path
1473*******************************************************/
1474int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1475{
1476 if (!cli || !fname || !buffer)
1477 {
1478 return maperror(EINVAL);
1479 }
1480
1481 debuglocal(4,"EALIst for <%s>\n", fname);
1482 return unilistea(cli, fname, buffer, size);
1483}
1484
1485/*****************************************************
1486lists EA of a file
1487*******************************************************/
1488int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1489{
1490 if (!cli || !file || !buffer)
1491 {
1492 return maperror(EINVAL);
1493 }
1494
1495 debuglocal(4,"FEALIst for <%s>\n", file->fname);
1496 return unilistea(cli, file->fname, buffer, size);
1497}
1498
1499/****************************************************************************
1500Check the space on a device.
1501****************************************************************************/
1502int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1503{
1504 uint64_t total, bsize, avail;
1505
1506 if (!cli || !pfsa)
1507 {
1508 return maperror(EINVAL);
1509 }
1510
1511 if (!NT_STATUS_IS_OK(cli_disk_size(cli, "", &bsize, &total, &avail)))
1512 {
1513 debuglocal(4,"Error in cli_disk_size: %s\n",cli_errstr(cli));
1514 return os2cli_errno(cli);
1515 }
1516
1517 debuglocal(4,"\n\t\t%" PRIu64
1518 " blocks of size %" PRIu64
1519 ". %" PRIu64 " blocks available\n",
1520 total, bsize, avail);
1521
1522 // YD currently Samba return it in MB!
1523 pfsa->cSectorUnit = 1;
1524 if (bsize >= 65536)
1525 {
1526 pfsa->cUnit = total*1024;
1527 pfsa->cUnitAvail = avail*1024;
1528 pfsa->cbSector = bsize/1024;
1529 }
1530 else
1531 {
1532 pfsa->cUnit = total;
1533 pfsa->cUnitAvail = avail;
1534 pfsa->cbSector = bsize;
1535 }
1536
1537 return 0;
1538}
1539
1540/*****************************************************
1541Send an echo to the server to confirm it is still alive
1542*******************************************************/
1543int _System smbwrp_echo(cli_state * cli)
1544{
1545 unsigned char garbage[16];
1546 NTSTATUS status;
1547 if (!cli)
1548 {
1549 return maperror(EINVAL);
1550 }
1551 /* Ping the server to keep the connection alive using SMBecho. */
1552 memset(garbage, 0xf0, sizeof(garbage));
1553 unsigned int old_timeout = cli->timeout;
1554 cli->timeout = 2000;// we don't want to wait 20 seconds
1555 status = cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage)));
1556 cli->timeout = old_timeout; // reset back to previous value
1557 if (NT_STATUS_IS_OK(status)) {
1558 return 0;
1559 } else {
1560 debuglocal(4," cli_echo failed: %s\n", nt_errstr(status));
1561 return -1;
1562 }
1563}
Note: See TracBrowser for help on using the repository browser.