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

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

Client 3.0 - source tidy ups

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