2
Unix SMB/Netbios implementation.
5
Copyright (C) Andrew Tridgell 1998
6
Copyright (C) Derrell Lipman 2003-2005
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29
#include "bsd-strlfunc.h"
31
typedef enum StartupType
37
int smbw_fd_map[__FD_SETSIZE];
38
int smbw_ref_count[__FD_SETSIZE];
39
char smbw_cwd[PATH_MAX];
40
char smbw_prefix[] = SMBW_PREFIX;
42
/* needs to be here because of dumb include files on some systems */
43
int creat_bits = O_WRONLY|O_CREAT|O_TRUNC;
45
int smbw_initialized = 0;
47
static int debug_level = 0;
49
static SMBCCTX *smbw_ctx;
51
extern int smbw_debug;
54
/*****************************************************
55
smbw_ref -- manipulate reference counts
56
******************************************************/
57
int smbw_ref(int client_fd, Ref_Count_Type type, ...)
61
/* client id values begin at SMBC_BASE_FC. */
62
client_fd -= SMBC_BASE_FD;
67
case SMBW_RCT_Increment:
68
return ++smbw_ref_count[client_fd];
70
case SMBW_RCT_Decrement:
71
return --smbw_ref_count[client_fd];
74
return smbw_ref_count[client_fd];
77
return (smbw_ref_count[client_fd] = va_arg(ap, int));
87
* Return a username and password given a server and share name
89
* Returns 0 upon success;
90
* non-zero otherwise, and errno is set to indicate the error.
92
static void get_envvar_auth_data(const char *srv,
102
/* Fall back to environment variables */
104
w = getenv("WORKGROUP");
105
if (w == NULL) w = "";
108
if (u == NULL) u = "";
110
p = getenv("PASSWORD");
111
if (p == NULL) p = "";
113
smbw_strlcpy(wg, w, wglen);
114
smbw_strlcpy(un, u, unlen);
115
smbw_strlcpy(pw, p, pwlen);
118
static smbc_get_auth_data_fn get_auth_data_fn = get_envvar_auth_data;
120
/*****************************************************
121
set the get auth data function
122
******************************************************/
123
void smbw_set_auth_data_fn(smbc_get_auth_data_fn fn)
125
get_auth_data_fn = fn;
129
/*****************************************************
130
ensure that all connections are terminated upon exit
131
******************************************************/
132
static void do_shutdown(void)
134
if (smbw_ctx != NULL) {
135
smbc_free_context(smbw_ctx, 1);
140
/*****************************************************
141
initialise structures
142
*******************************************************/
143
static void do_init(StartupType startupType)
148
smbw_initialized = 1; /* this must be first to avoid recursion! */
150
smbw_ctx = NULL; /* don't free context until it's established */
152
/* initially, no file descriptors are mapped */
153
for (i = 0; i < __FD_SETSIZE; i++) {
155
smbw_ref_count[i] = 0;
158
/* See if we've been told to start in a particular directory */
159
if ((p=getenv("SMBW_DIR")) != NULL) {
160
smbw_strlcpy(smbw_cwd, p, PATH_MAX);
162
/* we don't want the old directory to be busy */
163
(* smbw_libc.chdir)("/");
169
if ((p=getenv("DEBUG"))) {
170
debug_level = atoi(p);
173
if ((smbw_ctx = smbc_new_context()) == NULL) {
174
fprintf(stderr, "Could not create a context.\n");
178
smbw_ctx->debug = debug_level;
179
smbw_ctx->callbacks.auth_fn = get_auth_data_fn;
180
smbw_ctx->options.browse_max_lmb_count = 0;
181
smbw_ctx->options.urlencode_readdir_entries = 1;
182
smbw_ctx->options.one_share_per_server = 1;
184
if (smbc_init_context(smbw_ctx) == NULL) {
185
fprintf(stderr, "Could not initialize context.\n");
189
smbc_set_context(smbw_ctx);
191
/* if not real startup, exit handler has already been established */
192
if (startupType == StartupType_Real) {
197
/*****************************************************
198
initialise structures, real start up vs a fork()
199
*******************************************************/
202
do_init(StartupType_Real);
206
/*****************************************************
207
determine if a file descriptor is a smb one
208
*******************************************************/
209
int smbw_fd(int smbw_fd)
213
return (smbw_fd >= 0 &&
214
smbw_fd < __FD_SETSIZE &&
215
smbw_fd_map[smbw_fd] >= SMBC_BASE_FD); /* minimum smbc_ fd */
219
/*****************************************************
220
determine if a path is a smb one
221
*******************************************************/
222
int smbw_path(const char *name)
232
len = strlen(smbw_prefix);
234
ret = ((strncmp(name, smbw_prefix, len) == 0 &&
235
(name[len] == '\0' || name[len] == '/')) ||
236
(*name != '/' && *smbw_cwd != '\0'));
243
/*****************************************************
244
remove redundent stuff from a filename
245
*******************************************************/
246
void smbw_clean_fname(char *name)
254
DEBUG(10, ("Clean [%s]...\n", name));
259
if ((p=strstr(name,"/./"))) {
265
DEBUG(10, ("\tclean 1 (/./) produced [%s]\n", name));
268
if ((p=strstr(name,"//"))) {
274
DEBUG(10, ("\tclean 2 (//) produced [%s]\n", name));
277
if (strcmp(name,"/../")==0) {
280
DEBUG(10,("\tclean 3 (^/../$) produced [%s]\n", name));
283
if ((p=strstr(name,"/../"))) {
285
for (p2 = (p > name ? p-1 : p); p2 > name; p2--) {
286
if (p2[0] == '/') break;
294
DEBUG(10, ("\tclean 4 (/../) produced [%s]\n", name));
297
if (strcmp(name,"/..")==0) {
300
DEBUG(10, ("\tclean 5 (^/..$) produced [%s]\n", name));
304
p = l>=3?(name+l-3):name;
305
if (strcmp(p,"/..")==0) {
307
for (p2=p-1;p2>name;p2--) {
308
if (p2[0] == '/') break;
316
DEBUG(10, ("\tclean 6 (/..) produced [%s]\n", name));
320
p = l>=2?(name+l-2):name;
321
if (strcmp(p,"/.")==0) {
328
DEBUG(10, ("\tclean 7 (/.) produced [%s]\n", name));
331
if (strncmp(p=name,"./",2) == 0) {
336
DEBUG(10, ("\tclean 8 (^./) produced [%s]\n", name));
340
if (l > 1 && p[l-1] == '/') {
343
DEBUG(10, ("\tclean 9 (/) produced [%s]\n", name));
348
void smbw_fix_path(const char *src, char *dest)
351
int len = strlen(smbw_prefix);
354
for (p = src + len; *p == '/'; p++)
356
snprintf(dest, PATH_MAX, "smb://%s", p);
358
snprintf(dest, PATH_MAX, "%s/%s", smbw_cwd, src);
361
smbw_clean_fname(dest + 5);
363
DEBUG(10, ("smbw_fix_path(%s) returning [%s]\n", src, dest));
368
/*****************************************************
370
*******************************************************/
371
int smbw_open(const char *fname, int flags, mode_t mode)
384
smbw_fd = (smbw_libc.open)(SMBW_DUMMY, O_WRONLY, 0200);
390
smbw_fix_path(fname, path);
391
if (flags == creat_bits) {
392
client_fd = smbc_creat(path, mode);
394
client_fd = smbc_open(path, flags, mode);
398
(* smbw_libc.close)(smbw_fd);
402
smbw_fd_map[smbw_fd] = client_fd;
403
smbw_ref(client_fd, SMBW_RCT_Increment);
408
/*****************************************************
409
a wrapper for pread()
411
there should really be an smbc_pread() to avoid the two
412
lseek()s required in this kludge.
413
*******************************************************/
414
ssize_t smbw_pread(int smbw_fd, void *buf, size_t count, SMBW_OFF_T ofs)
425
client_fd = smbw_fd_map[smbw_fd];
427
if ((old_ofs = smbc_lseek(client_fd, 0, SEEK_CUR)) < 0 ||
428
smbc_lseek(client_fd, ofs, SEEK_SET) < 0) {
432
if ((ret = smbc_read(client_fd, buf, count)) < 0) {
434
(void) smbc_lseek(client_fd, old_ofs, SEEK_SET);
442
/*****************************************************
444
*******************************************************/
445
ssize_t smbw_read(int smbw_fd, void *buf, size_t count)
449
client_fd = smbw_fd_map[smbw_fd];
451
return smbc_read(client_fd, buf, count);
456
/*****************************************************
457
a wrapper for write()
458
*******************************************************/
459
ssize_t smbw_write(int smbw_fd, void *buf, size_t count)
463
client_fd = smbw_fd_map[smbw_fd];
465
return smbc_write(client_fd, buf, count);
468
/*****************************************************
469
a wrapper for pwrite()
470
*******************************************************/
471
ssize_t smbw_pwrite(int smbw_fd, void *buf, size_t count, SMBW_OFF_T ofs)
482
client_fd = smbw_fd_map[smbw_fd];
484
if ((old_ofs = smbc_lseek(client_fd, 0, SEEK_CUR)) < 0 ||
485
smbc_lseek(client_fd, ofs, SEEK_SET) < 0) {
489
if ((ret = smbc_write(client_fd, buf, count)) < 0) {
491
(void) smbc_lseek(client_fd, old_ofs, SEEK_SET);
499
/*****************************************************
500
a wrapper for close()
501
*******************************************************/
502
int smbw_close(int smbw_fd)
506
client_fd = smbw_fd_map[smbw_fd];
508
if (smbw_ref(client_fd, SMBW_RCT_Decrement) > 0) {
512
(* smbw_libc.close)(smbw_fd);
513
smbw_fd_map[smbw_fd] = -1;
514
return smbc_close(client_fd);
518
/*****************************************************
519
a wrapper for fcntl()
520
*******************************************************/
521
int smbw_fcntl(int smbw_fd, int cmd, long arg)
527
/*****************************************************
528
a wrapper for access()
529
*******************************************************/
530
int smbw_access(const char *name, int mode)
536
if (smbw_stat(name, &st)) return -1;
538
if (((mode & R_OK) && !(st.s_mode & S_IRUSR)) ||
539
((mode & W_OK) && !(st.s_mode & S_IWUSR)) ||
540
((mode & X_OK) && !(st.s_mode & S_IXUSR))) {
548
/*****************************************************
549
a wrapper for readlink() - needed for correct errno setting
550
*******************************************************/
551
int smbw_readlink(const char *fname, char *buf, size_t bufsize)
558
ret = smbw_stat(fname, &st);
563
/* it exists - say it isn't a link */
569
/*****************************************************
570
a wrapper for unlink()
571
*******************************************************/
572
int smbw_unlink(const char *fname)
578
smbw_fix_path(fname, path);
579
return smbc_unlink(path);
583
/*****************************************************
584
a wrapper for rename()
585
*******************************************************/
586
int smbw_rename(const char *oldname, const char *newname)
588
char path_old[PATH_MAX];
589
char path_new[PATH_MAX];
593
smbw_fix_path(oldname, path_old);
594
smbw_fix_path(newname, path_new);
595
return smbc_rename(path_old, path_new);
599
/*****************************************************
601
*******************************************************/
602
int smbw_utimes(const char *fname, void *buf)
606
smbw_fix_path(fname, path);
607
return smbc_utimes(path, buf);
611
/*****************************************************
613
*******************************************************/
614
int smbw_utime(const char *fname, void *buf)
618
smbw_fix_path(fname, path);
619
return smbc_utime(path, buf);
622
/*****************************************************
623
a wrapper for chown()
624
*******************************************************/
625
int smbw_chown(const char *fname, uid_t owner, gid_t group)
627
/* always indiciate that this is not supported. */
632
/*****************************************************
633
a wrapper for chmod()
634
*******************************************************/
635
int smbw_chmod(const char *fname, mode_t newmode)
639
smbw_fix_path(fname, path);
640
return smbc_chmod(path, newmode);
644
/*****************************************************
645
a wrapper for lseek()
646
*******************************************************/
647
SMBW_OFF_T smbw_lseek(int smbw_fd,
654
client_fd = smbw_fd_map[smbw_fd];
656
ret = smbc_lseek(client_fd, offset, whence);
659
printf("smbw_lseek(%d/%d, 0x%llx) returned 0x%llx\n",
661
(unsigned long long) offset,
662
(unsigned long long) ret);
667
/*****************************************************
669
*******************************************************/
670
int smbw_dup(int smbw_fd)
674
fd2 = (smbw_libc.dup)(smbw_fd);
679
smbw_fd_map[fd2] = smbw_fd_map[smbw_fd];
680
smbw_ref(smbw_fd_map[smbw_fd], SMBW_RCT_Increment);
685
/*****************************************************
687
*******************************************************/
688
int smbw_dup2(int smbw_fd, int fd2)
690
if ((* smbw_libc.dup2)(smbw_fd, fd2) != fd2) {
694
smbw_fd_map[fd2] = smbw_fd_map[smbw_fd];
695
smbw_ref(smbw_fd_map[smbw_fd], SMBW_RCT_Increment);
700
/*****************************************************
701
when we fork we have to close all connections and files
703
*******************************************************/
713
if (pipe(p)) return (* smbw_libc.fork)();
715
child_pid = (* smbw_libc.fork)();
718
/* block the parent for a moment until the sockets are
720
(* smbw_libc.close)(p[1]);
721
(* smbw_libc.read)(p[0], &c, 1);
722
(* smbw_libc.close)(p[0]);
726
(* smbw_libc.close)(p[0]);
728
/* close all server connections and locally-opened files */
729
for (i = 0; i < __FD_SETSIZE; i++) {
730
if (smbw_fd_map[i] > 0 &&
731
smbw_ref(smbw_fd_map[i], SMBW_RCT_Get) > 0) {
733
smbc_close(smbw_fd_map[i]);
734
smbw_ref(smbw_fd_map[i], SMBW_RCT_Set, 0);
735
(* smbw_libc.close)(i);
741
/* unblock the parent */
743
(* smbw_libc.close)(p[1]);
745
/* specify directory to start in, if it's simulated smb */
746
if (*smbw_cwd != '\0') {
747
setenv("SMBW_DIR", smbw_cwd, 1);
749
unsetenv("SMBW_DIR");
752
/* Re-initialize this library for the child */
753
do_init(StartupType_Fake);
755
/* and continue in the child */
759
int smbw_setxattr(const char *fname,
767
if (strcmp(name, "system.posix_acl_access") == 0)
772
smbw_fix_path(fname, path);
773
return smbc_setxattr(path, name, value, size, flags);
776
int smbw_lsetxattr(const char *fname,
784
if (strcmp(name, "system.posix_acl_access") == 0)
789
smbw_fix_path(fname, path);
790
return smbc_lsetxattr(path, name, value, size, flags);
793
int smbw_fsetxattr(int smbw_fd,
801
if (strcmp(name, "system.posix_acl_access") == 0)
806
client_fd = smbw_fd_map[smbw_fd];
807
return smbc_fsetxattr(client_fd, name, value, size, flags);
810
int smbw_getxattr(const char *fname,
817
if (strcmp(name, "system.posix_acl_access") == 0)
822
smbw_fix_path(fname, path);
824
return smbc_getxattr(path, name, value, size);
827
int smbw_lgetxattr(const char *fname,
834
if (strcmp(name, "system.posix_acl_access") == 0)
839
smbw_fix_path(fname, path);
840
return smbc_lgetxattr(path, name, value, size);
843
int smbw_fgetxattr(int smbw_fd,
850
if (strcmp(name, "system.posix_acl_access") == 0)
855
client_fd = smbw_fd_map[smbw_fd];
856
return smbc_fgetxattr(client_fd, name, value, size);
859
int smbw_removexattr(const char *fname,
864
if (strcmp(name, "system.posix_acl_access") == 0)
869
smbw_fix_path(fname, path);
870
return smbc_removexattr(path, name);
873
int smbw_lremovexattr(const char *fname,
878
if (strcmp(name, "system.posix_acl_access") == 0)
883
smbw_fix_path(fname, path);
884
return smbc_lremovexattr(path, name);
887
int smbw_fremovexattr(int smbw_fd,
892
if (strcmp(name, "system.posix_acl_access") == 0)
897
client_fd = smbw_fd_map[smbw_fd];
898
return smbc_fremovexattr(client_fd, name);
901
int smbw_listxattr(const char *fname,
907
smbw_fix_path(fname, path);
908
return smbc_listxattr(path, list, size);
911
int smbw_llistxattr(const char *fname,
917
smbw_fix_path(fname, path);
918
return smbc_llistxattr(path, list, size);
921
int smbw_flistxattr(int smbw_fd,
927
client_fd = smbw_fd_map[smbw_fd];
928
return smbc_flistxattr(client_fd, list, size);