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

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

client-3.0: revert mistaken commit of dircache.c, add cache support to list_files_smb2

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