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

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

Support file listings on SMB2+ connections

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