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

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

Correct previous checking that changed type of smbwrp_printjob_add from void to NTSTATUS

  • Property svn:eol-style set to native
File size: 32.8 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, sharename, "?????",
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 Do a directory listing, calling fn on each file found.
920 Modified from cli_list
921****************************************************************************/
922static int list_files(struct cli_state *cli, const char *mask, uint16_t attribute,
923 void (*fn)(const char *, smbwrp_fileinfo *, const char *,
924 void *), void *state)
925{
926 TALLOC_CTX *frame = talloc_stackframe();
927 struct event_context *ev;
928 struct tevent_req *req;
929 NTSTATUS status = NT_STATUS_NO_MEMORY;
930 struct file_info *finfo;
931 size_t i, num_finfo;
932 uint16_t info_level;
933 void *dircachectx = NULL;
934 smbwrp_fileinfo wrpfinfo;
935
936 /* Try to get the listing from cache. */
937 if (dircache_list_files(fn, state, &num_finfo))
938 {
939 /* Got from cache. */
940 return(num_finfo);
941 }
942
943 if (smbXcli_conn_has_async_calls(cli->conn)) {
944 /*
945 * Can't use sync call while an async call is in flight
946 */
947 status = NT_STATUS_INVALID_PARAMETER;
948 goto fail;
949 }
950 ev = samba_tevent_context_init(frame);
951 if (ev == NULL) {
952 goto fail;
953 }
954
955 info_level = (smb1cli_conn_capabilities(cli->conn) & CAP_NT_SMBS)
956 ? SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_EA_SIZE;
957
958 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, mask);
959
960 req = cli_list_send(frame, ev, cli, mask, attribute, info_level);
961 if (req == NULL) {
962 goto fail;
963 }
964 if (!tevent_req_poll(req, ev)) {
965 status = map_nt_error_from_unix(errno);
966 goto fail;
967 }
968
969 status = cli_list_recv(req, frame, &finfo, &num_finfo);
970 if (!NT_STATUS_IS_OK(status)) {
971 goto fail;
972 }
973
974 dircachectx = dircache_write_begin(state, num_finfo);
975
976 debuglocal(4,"list_files: got %d files\n", num_finfo);
977
978
979 for (i=0; i<num_finfo; i++) {
980 //as samba and this client have different finfo, we need to convert
981 memset(&wrpfinfo, 0, sizeof(wrpfinfo));
982 wrpfinfo.size = finfo[i].size;
983 wrpfinfo.attr = finfo[i].mode;
984 wrpfinfo.ctime = convert_timespec_to_time_t(finfo[i].ctime_ts);
985 wrpfinfo.mtime = convert_timespec_to_time_t(finfo[i].mtime_ts);
986 wrpfinfo.atime = convert_timespec_to_time_t(finfo[i].atime_ts);
987 wrpfinfo.easize = finfo[i].easize;
988 strncpy(wrpfinfo.fname, finfo[i].name, sizeof(wrpfinfo.fname) -1);
989
990 fn(cli->dfs_mountpoint, &wrpfinfo, mask, state);
991 // Also add the entry to the cache.
992 dircache_write_entry(dircachectx, &wrpfinfo);
993 }
994
995 dircache_write_end(dircachectx);
996 fail:
997 TALLOC_FREE(frame);
998 return num_finfo;
999}
1000
1001/*****************************************************
1002open a directory on the server
1003*******************************************************/
1004int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1005{
1006 if (!srv || !cli || !state || !*state->mask)
1007 {
1008 return maperror(EINVAL);
1009 }
1010 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);
1011 if (*srv->workgroup == 0 && *srv->server_name == 0)
1012 {
1013 smbwrp_special_add(".", state);
1014 smbwrp_special_add("..", state);
1015 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1016 smbwrp_share_add, state);
1017 } else
1018 if (*srv->server_name == 0)
1019 {
1020 smbwrp_special_add(".", state);
1021 smbwrp_special_add("..", state);
1022
1023 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1024 smbwrp_share_add, state);
1025 } else
1026 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1027 {
1028 smbwrp_special_add(".", state);
1029 smbwrp_special_add("..", state);
1030
1031 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1032 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1033 {
1034 return os2cli_errno(cli);
1035 }
1036 } else
1037 if (strncmp(cli->dev,"LPT",3) == 0)
1038 {
1039 smbwrp_special_add(".", state);
1040 smbwrp_special_add("..", state);
1041 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1042 {
1043 return os2cli_errno(cli);
1044 }
1045 }
1046 else
1047 {
1048 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1049 smbwrp_dir_add, state) < 0)
1050 {
1051 return os2cli_errno(cli);
1052 }
1053 }
1054
1055 return 0;
1056}
1057
1058/*****************************************************
1059a wrapper for chdir()
1060*******************************************************/
1061int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1062{
1063 unsigned short mode = aDIR;
1064 smbwrp_fileinfo finfo = {0};
1065 if (!cli || !fname)
1066 {
1067 return maperror(EINVAL);
1068 }
1069
1070 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1071 if (smbwrp_getattr(srv, cli, &finfo))
1072 {
1073 return os2cli_errno(cli);
1074 }
1075
1076 if (!(finfo.attr & aDIR)) {
1077 return maperror(ENOTDIR);
1078 }
1079
1080 return 0;
1081}
1082
1083
1084/*****************************************************
1085a wrapper for mkdir()
1086*******************************************************/
1087int _System smbwrp_mkdir(cli_state * cli, char *fname)
1088{
1089 if (!cli || !fname)
1090 {
1091 return maperror(EINVAL);
1092 }
1093
1094 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname)))
1095 {
1096 return os2cli_errno(cli);
1097 }
1098 return 0;
1099}
1100
1101/*****************************************************
1102a wrapper for rmdir()
1103*******************************************************/
1104int _System smbwrp_rmdir(cli_state * cli, char *fname)
1105{
1106 if (!cli || !fname)
1107 {
1108 return maperror(EINVAL);
1109 }
1110
1111 if (!NT_STATUS_IS_OK(cli_rmdir(cli, fname)))
1112 {
1113 return os2cli_errno(cli);
1114 }
1115 return 0;
1116}
1117
1118/*****************************************************
1119set EA for a path
1120*******************************************************/
1121int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1122{
1123 if (!cli || !fname || !name)
1124 {
1125 return maperror(EINVAL);
1126 }
1127 if (!NT_STATUS_IS_OK(cli_set_ea_path(cli, fname, name, value, size)))
1128 {
1129 return os2cli_errno(cli);
1130 }
1131 return 0;
1132}
1133
1134/*****************************************************
1135set EA for a file
1136*******************************************************/
1137int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1138{
1139 if (!cli || !file || !name)
1140 {
1141 return maperror(EINVAL);
1142 }
1143 if (!NT_STATUS_IS_OK(cli_set_ea_fnum(cli, file->fd, name, value, size)))
1144 {
1145 return os2cli_errno(cli);
1146 }
1147 return 0;
1148}
1149
1150
1151#pragma pack(1)
1152typedef struct _FEA /* fea */
1153{
1154 unsigned char fEA; /* flags */
1155 unsigned char cbName; /* name length not including NULL */
1156 unsigned short cbValue; /* value length */
1157} FEA;
1158
1159typedef struct _FEALIST /* feal */
1160{
1161 unsigned long cbList; /* total bytes of structure including full list */
1162 FEA list[1]; /* variable length FEA structures */
1163} FEALIST;
1164#pragma pack()
1165
1166static int unilistea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1167{
1168 int fnum, i;
1169 int gotsize = sizeof(unsigned long);
1170 size_t num_eas;
1171 struct ea_struct *ea_list = NULL;
1172 TALLOC_CTX *mem_ctx;
1173 FEA * p;
1174 FEALIST * pfealist;
1175 char * q;
1176
1177 mem_ctx = talloc_init("%d: ealist", _gettid());
1178 pfealist = (FEALIST *)buffer;
1179 pfealist->cbList = 0;
1180
1181 if (!NT_STATUS_IS_OK(cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)))
1182 {
1183 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1184 talloc_destroy(mem_ctx);
1185 return os2cli_errno(cli);
1186 }
1187
1188 debuglocal(4,"num_eas = %d\n", num_eas);
1189
1190 // we will count that os/2 max EA size for file is 64kb
1191 p = pfealist->list;
1192 for (i = 0; i < num_eas; i++)
1193 {
1194 int namelen = strlen(ea_list[i].name);
1195 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);
1196 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1197 {
1198 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1199 continue;
1200 }
1201 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1202 if (size >= gotsize)
1203 {
1204 p->fEA = 0;
1205 p->cbName = namelen;
1206 p->cbValue = ea_list[i].value.length;
1207 q = (char *)(p + 1);
1208 strncpy(q, ea_list[i].name, namelen + 1);
1209 q += namelen + 1;
1210 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1211 p = (FEA *)(q + ea_list[i].value.length);
1212 }
1213 }
1214 pfealist->cbList = gotsize;
1215 debuglocal(4,"ret size = %d\n", gotsize);
1216
1217 talloc_destroy(mem_ctx);
1218 return 0;
1219}
1220
1221/*****************************************************
1222lists EA of a path
1223*******************************************************/
1224int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1225{
1226 if (!cli || !fname || !buffer)
1227 {
1228 return maperror(EINVAL);
1229 }
1230
1231 debuglocal(4,"EALIst for <%s>\n", fname);
1232 return unilistea(cli, fname, buffer, size);
1233}
1234
1235/*****************************************************
1236lists EA of a file
1237*******************************************************/
1238int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1239{
1240 if (!cli || !file || !buffer)
1241 {
1242 return maperror(EINVAL);
1243 }
1244
1245 debuglocal(4,"FEALIst for <%s>\n", file->fname);
1246 return unilistea(cli, file->fname, buffer, size);
1247}
1248
1249/****************************************************************************
1250Check the space on a device.
1251****************************************************************************/
1252int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1253{
1254 int total, bsize, avail;
1255
1256 if (!cli || !pfsa)
1257 {
1258 return maperror(EINVAL);
1259 }
1260
1261 if (!NT_STATUS_IS_OK(cli_dskattr(cli, &bsize, &total, &avail)))
1262 {
1263 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1264 return os2cli_errno(cli);
1265 }
1266
1267 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1268 total, bsize, avail);
1269
1270 // YD currently Samba return it in MB!
1271 pfsa->cSectorUnit = 1;
1272 if (bsize >= 65536)
1273 {
1274 pfsa->cUnit = total*1024;
1275 pfsa->cUnitAvail = avail*1024;
1276 pfsa->cbSector = bsize/1024;
1277 }
1278 else
1279 {
1280 pfsa->cUnit = total;
1281 pfsa->cUnitAvail = avail;
1282 pfsa->cbSector = bsize;
1283 }
1284
1285 return 0;
1286}
1287
1288/*****************************************************
1289Send an echo to the server to confirm it is still alive
1290*******************************************************/
1291int _System smbwrp_echo(cli_state * cli)
1292{
1293 debuglocal(4," smbwrp_echo\n");
1294 unsigned char garbage[16];
1295 NTSTATUS status;
1296 if (!cli)
1297 {
1298 return maperror(EINVAL);
1299 }
1300 /* Ping the server to keep the connection alive using SMBecho. */
1301 memset(garbage, 0xf0, sizeof(garbage));
1302 unsigned int old_timeout = cli->timeout;
1303 cli->timeout = 2000;// we don't want to wait 20 seconds
1304 status = cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage)));
1305 cli->timeout = old_timeout; // reset back to previous value
1306 if (NT_STATUS_IS_OK(status)) {
1307 return 0;
1308 } else {
1309 return -1;
1310 }
1311}
Note: See TracBrowser for help on using the repository browser.