diff options
| author | Derrell Lipman <derrell@samba.org> | 2005-03-29 00:42:51 +0000 |
|---|---|---|
| committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 10:56:22 -0500 |
| commit | fbc611f431db443c23486f768ca5e2bc4db95c24 (patch) | |
| tree | eda7acba80812fe7fce924e9bbdbfa9dc971942d /examples | |
| parent | fa787af52093e14de4a472d2ccb50b9ec66b10d1 (diff) | |
| download | samba-fbc611f431db443c23486f768ca5e2bc4db95c24.tar.gz samba-fbc611f431db443c23486f768ca5e2bc4db95c24.tar.bz2 samba-fbc611f431db443c23486f768ca5e2bc4db95c24.zip | |
r6108: Added smbsh/smbwrapper for Linux to example/libsmbclient tree; provided more complete libsmbclient testbrowse utility
(This used to be commit 15736b97c837a16d9c009b8bff18b31429ccbe83)
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/libsmbclient/Makefile | 8 | ||||
| -rw-r--r-- | examples/libsmbclient/smbwrapper/Makefile | 35 | ||||
| -rw-r--r-- | examples/libsmbclient/smbwrapper/README | 40 | ||||
| -rw-r--r-- | examples/libsmbclient/smbwrapper/opendir_smbsh.c | 47 | ||||
| -rw-r--r-- | examples/libsmbclient/smbwrapper/select.c | 124 | ||||
| -rw-r--r-- | examples/libsmbclient/smbwrapper/smbsh.c | 160 | ||||
| -rw-r--r-- | examples/libsmbclient/smbwrapper/smbw.c | 910 | ||||
| -rw-r--r-- | examples/libsmbclient/smbwrapper/smbw.h | 163 | ||||
| -rw-r--r-- | examples/libsmbclient/smbwrapper/smbw_dir.c | 355 | ||||
| -rw-r--r-- | examples/libsmbclient/smbwrapper/smbw_stat.c | 146 | ||||
| -rw-r--r-- | examples/libsmbclient/smbwrapper/wrapper.c | 1729 | ||||
| -rw-r--r-- | examples/libsmbclient/smbwrapper/wrapper.h | 209 | ||||
| -rw-r--r-- | examples/libsmbclient/testbrowse.c | 219 | ||||
| -rw-r--r-- | examples/libsmbclient/testsmbc.c | 2 | ||||
| -rw-r--r-- | examples/libsmbclient/tree.c | 8 |
15 files changed, 4094 insertions, 61 deletions
diff --git a/examples/libsmbclient/Makefile b/examples/libsmbclient/Makefile index fcd5ef29003..6c89fd431ec 100644 --- a/examples/libsmbclient/Makefile +++ b/examples/libsmbclient/Makefile @@ -10,7 +10,7 @@ CFLAGS = -I$(SAMBA_INCL) $(EXTLIB_INCL) LDFLAGS = -L/usr/lib -all: testsmbc tree testacl testbrowse +all: testsmbc tree testacl testbrowse smbsh testsmbc: testsmbc.o @echo Linking testsmbc @@ -32,5 +32,9 @@ testbrowse: testbrowse.o @echo Linking testbrowse @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ -lsmbclient -lpopt $< +smbsh: + make -C smbwrapper + clean: - @rm -f *.o *~ + @rm -f *.o *~ testsmbc tree testacl testbrowse + @make -C smbwrapper clean diff --git a/examples/libsmbclient/smbwrapper/Makefile b/examples/libsmbclient/smbwrapper/Makefile new file mode 100644 index 00000000000..099c2049866 --- /dev/null +++ b/examples/libsmbclient/smbwrapper/Makefile @@ -0,0 +1,35 @@ +LIBS = -lsmbclient -ldl +DEFS = -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE + +CFLAGS = -I$(SAMBA_INCL) $(EXTLIB_INCL) + +LDFLAGS = -L/usr/lib + +SMBINCLUDE = -I../../../source/include +CFLAGS= -fpic -g -O0 $(DEFS) $(SMBINCLUDE) + +BIN = . + +SMBWRAPPER_OBJS = smbw.o smbw_dir.o smbw_stat.o wrapper.o select.o +SMBSH_OBJS = smbsh.o + +all: $(BIN)/smbwrapper.so $(BIN)/smbsh + +$(BIN)/smbwrapper.so: $(SMBWRAPPER_OBJS) + $(CC) -g \ + -Wl,-init=smbw_initialize \ + -shared \ + --export-all-symbols \ + -o $(BIN)/smbwrapper.so \ + $(SMBWRAPPER_OBJS) \ + $(LIBS) \ + -Wl,-soname=`basename $@` + +$(BIN)/smbsh: $(SMBSH_OBJS) + $(CC) -g -o $(BIN)/smbsh $(SMBSH_OBJS) $(LIBS) + +opendir_smbsh: opendir_smbsh.o + $(CC) -g -o opendir_smbsh opendir_smbsh.o $(LIBS) $(DMALLOC) + +clean: + rm -f *.o *~ opendir_smbsh smbsh smbwrapper.so diff --git a/examples/libsmbclient/smbwrapper/README b/examples/libsmbclient/smbwrapper/README new file mode 100644 index 00000000000..7b71ec06ba0 --- /dev/null +++ b/examples/libsmbclient/smbwrapper/README @@ -0,0 +1,40 @@ +To create "smbsh" on Linux, just type "make". + +If you execute "smbsh" in *this* directory (so that it can find the required +shared library), you'll find yourself in a new shell. You can then issue +commands referencing the "/smb" pseudo-filesystem: + + ls /smb + ls /smb/WORKGROUP_OR_DOMAIN + ls /smb/SERVER + ls /smb/SERVER/SHARE + ls /smb/SERVER/SHARE/PATH + +Note that WORKGROUP_OR_DOMAIN is *not* used other than at that level. This is +consistent with the smb:// URI definition. + +Usage: + smbsh [-L <path to find smbwrapper.so>] + [-p <library to load before smbwrapper.so>] + [-a <library to load after smbwrapper.so>] + [-d <debug value for libsmbclient>] + [-n] (do not ask for username/password) + [-W <workgroup>] + [-U <username%password] + [command] + +So to list the contents of \\MYDESK\C$ where a username (adventure) and password +(xyzzy) are required, and with smbwrapper.so installed in /usr/share/samba, you +could try: + + smbsh -L /usr/share/samba -U adventure%xyzzy ls '/smb/MYDESK/C$' + +(It's a good idea to get in the habit of surrounding windows paths in single +quotes, since they often contain spaces and other characters that'll give you +headaches when not escaped.) + +This smbsh seems to work quite well on Linux 2.4 and 2.6. The biggest problem it +has is in tracking your current working directory. I haven't had the time to +track that down and fix it. + +Derrell Lipman diff --git a/examples/libsmbclient/smbwrapper/opendir_smbsh.c b/examples/libsmbclient/smbwrapper/opendir_smbsh.c new file mode 100644 index 00000000000..275b95f8ea1 --- /dev/null +++ b/examples/libsmbclient/smbwrapper/opendir_smbsh.c @@ -0,0 +1,47 @@ +#include <sys/types.h> +#include <dirent.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <libsmbclient.h> + +int +main(int argc, char * argv[]) +{ + char * p; + char buf[1024]; + DIR * dir; + struct dirent * dirent; + + setbuf(stdout, NULL); + + for (fputs("path: ", stdout), p = fgets(buf, sizeof(buf), stdin); + p != NULL && *p != '\n' && *p != '\0'; + fputs("path: ", stdout), p = fgets(buf, sizeof(buf), stdin)) + { + if ((p = strchr(buf, '\n')) != NULL) + { + *p = '\0'; + } + + printf("Opening (%s)...\n", buf); + + if ((dir = opendir(buf)) == NULL) + { + printf("Could not open directory [%s]: \n", + buf, strerror(errno)); + continue; + } + + while ((dirent = readdir(dir)) != NULL) + { + printf("%-30s", dirent->d_name); + printf("%-30s", dirent->d_name + strlen(dirent->d_name) + 1); + printf("\n"); + } + + closedir(dir); + } + + exit(0); +} diff --git a/examples/libsmbclient/smbwrapper/select.c b/examples/libsmbclient/smbwrapper/select.c new file mode 100644 index 00000000000..aa90169ee71 --- /dev/null +++ b/examples/libsmbclient/smbwrapper/select.c @@ -0,0 +1,124 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + Samba select/poll implementation + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Derrell Lipman 2003-2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + * WHY THIS FILE? + * + * This file implements the two functions in the select() family, as required + * by samba. The samba native functions, though, implement a pipe to help + * alleviate a deadlock problem, but which creates problems of its own (the + * timeout stops working correctly). Those functions also require that all + * signal handlers call a function which writes to the pipe -- a task which is + * difficult to do in the smbwrapper environment. + */ + + +#include <sys/select.h> +#include <errno.h> +#include <stdio.h> + +int sys_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *tval) +{ + int ret; + fd_set *readfds2, readfds_buf; + + /* If readfds is NULL we need to provide our own set. */ + if (readfds) { + readfds2 = readfds; + } else { + readfds2 = &readfds_buf; + FD_ZERO(readfds2); + } + + errno = 0; + ret = select(maxfd,readfds2,writefds,errorfds,tval); + + if (ret <= 0) { + FD_ZERO(readfds2); + if (writefds) + FD_ZERO(writefds); + if (errorfds) + FD_ZERO(errorfds); + } + + return ret; +} + +/******************************************************************* + Similar to sys_select() but catch EINTR and continue. + This is what sys_select() used to do in Samba. +********************************************************************/ + +int sys_select_intr(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *tval) +{ + int ret; + fd_set *readfds2, readfds_buf, *writefds2, writefds_buf, *errorfds2, errorfds_buf; + struct timeval tval2, *ptval, end_time, now_time; + extern void GetTimeOfDay(struct timeval *tval); + + readfds2 = (readfds ? &readfds_buf : NULL); + writefds2 = (writefds ? &writefds_buf : NULL); + errorfds2 = (errorfds ? &errorfds_buf : NULL); + if (tval) { + GetTimeOfDay(&end_time); + end_time.tv_sec += tval->tv_sec; + end_time.tv_usec += tval->tv_usec; + end_time.tv_sec += end_time.tv_usec / 1000000; + end_time.tv_usec %= 1000000; + ptval = &tval2; + } else { + ptval = NULL; + } + + do { + if (readfds) + readfds_buf = *readfds; + if (writefds) + writefds_buf = *writefds; + if (errorfds) + errorfds_buf = *errorfds; + if (tval) { + GetTimeOfDay(&now_time); + tval2.tv_sec = end_time.tv_sec - now_time.tv_sec; + tval2.tv_usec = end_time.tv_usec - now_time.tv_usec; + if ((signed long) tval2.tv_usec < 0) { + tval2.tv_usec += 1000000; + tval2.tv_sec--; + } + if ((signed long) tval2.tv_sec < 0) { + ret = 0; + break; /* time has already elapsed */ + } + } + + ret = sys_select(maxfd, readfds2, writefds2, errorfds2, ptval); + } while (ret == -1 && errno == EINTR); + + if (readfds) + *readfds = readfds_buf; + if (writefds) + *writefds = writefds_buf; + if (errorfds) + *errorfds = errorfds_buf; + + return ret; +} diff --git a/examples/libsmbclient/smbwrapper/smbsh.c b/examples/libsmbclient/smbwrapper/smbsh.c new file mode 100644 index 00000000000..7b33de766fd --- /dev/null +++ b/examples/libsmbclient/smbwrapper/smbsh.c @@ -0,0 +1,160 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0 + SMB wrapper functions - frontend + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Derrell Lipman 2003-2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <limits.h> +#include <string.h> +#include <libsmbclient.h> + +#ifndef FALSE +# define FALSE (0) +# define TRUE (! FALSE) +#endif + +static void smbsh_usage(void) +{ + printf("smbsh [options] [command [args] ...]\n\n"); + printf(" -p prepend library name\n"); + printf(" -a append library name\n"); + printf(" -n"); + printf(" -W workgroup\n"); + printf(" -U username\n"); + printf(" -P prefix\n"); + printf(" -R resolve order\n"); + printf(" -d debug level\n"); + printf(" -l logfile\n"); + printf(" -L libdir\n"); + exit(0); +} + +int main(int argc, char *argv[]) +{ + char *p, *u; + char *libd = "."; + char line[PATH_MAX], pre[PATH_MAX], post[PATH_MAX]; + int opt; + int no_ask = 0; + struct stat statbuf; + extern char *optarg; + extern int optind; + + *pre = *post = '\0'; + + while ((opt = getopt(argc, argv, "p:a:d:nL:W:U:h")) != -1) { + switch (opt) { + case 'p': /* prepend library before smbwrapper.so */ + if (*pre != '\0') + strncat(pre, " ", PATH_MAX - strlen(pre)); + strncat(pre, optarg, PATH_MAX - strlen(pre)); + break; + + case 'a': /* append library after smbwrapper.so */ + strncat(post, " ", PATH_MAX - strlen(post)); + strncat(post, optarg, PATH_MAX - strlen(post)); + break; + + case 'd': + setenv("DEBUG", optarg, TRUE); + break; + + case 'n': /* don't ask for username/password */ + no_ask++; + break; + + case 'L': + libd = optarg; + break; + + case 'W': + setenv("WORKGROUP", optarg, TRUE); + break; + + case 'U': + p = strchr(optarg,'%'); + if (p) { + *p=0; + setenv("PASSWORD", p+1, TRUE); + } + setenv("USER", optarg, TRUE); + break; + + case 'h': + default: + smbsh_usage(); + } + } + + + if (! no_ask) { + if (!getenv("USER")) { + printf("Username: "); + u = fgets(line, sizeof(line)-1, stdin); + setenv("USER", u, TRUE); + } + + if (!getenv("PASSWORD")) { + p = getpass("Password: "); + setenv("PASSWORD", p, TRUE); + } + } + + strncpy(line, pre, PATH_MAX - strlen(line)); + strncat(line, " ", PATH_MAX - strlen(line)); + strncat(line, libd, PATH_MAX - strlen(line)); + strncat(line, "/smbwrapper.so", PATH_MAX - strlen(line)); + strncat(line, post, PATH_MAX - strlen(line)); + setenv("LD_PRELOAD", line, TRUE); + setenv("LD_BIND_NOW", "true", TRUE); + + snprintf(line,sizeof(line)-1,"%s/smbwrapper.32.so", libd); + + if (stat(line, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { + snprintf(line,sizeof(line)-1,"%s/smbwrapper.32.so:DEFAULT", libd); + setenv("_RLD_LIST", line, TRUE); + snprintf(line,sizeof(line)-1,"%s/smbwrapper.so:DEFAULT", libd); + setenv("_RLDN32_LIST", line, TRUE); + } else { + snprintf(line,sizeof(line)-1,"%s/smbwrapper.so:DEFAULT", libd); + setenv("_RLD_LIST", line, TRUE); + } + + if (optind < argc) { + execvp(argv[optind], &argv[optind]); + } else { + char *shellpath = getenv("SHELL"); + + setenv("PS1", "smbsh$ ", TRUE); + + if(shellpath) { + execl(shellpath,"smbsh", NULL); + } else { + setenv("SHELL", "/bin/sh", TRUE); + execl("/bin/sh", "smbsh", NULL); + } + } + printf("launch failed!\n"); + return 1; +} diff --git a/examples/libsmbclient/smbwrapper/smbw.c b/examples/libsmbclient/smbwrapper/smbw.c new file mode 100644 index 00000000000..d2f1c18695d --- /dev/null +++ b/examples/libsmbclient/smbwrapper/smbw.c @@ -0,0 +1,910 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0 + SMB wrapper functions + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Derrell Lipman 2003-2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdarg.h> +#include <assert.h> +#include "smbw.h" + +int smbw_fd_map[__FD_SETSIZE]; +int smbw_ref_count[__FD_SETSIZE]; +char smbw_cwd[PATH_MAX]; +char smbw_prefix[] = SMBW_PREFIX; + +/* needs to be here because of dumb include files on some systems */ +int creat_bits = O_WRONLY|O_CREAT|O_TRUNC; + +int smbw_initialized = 0; + +static int debug_level = 0; + +static SMBCCTX *smbw_ctx; + +extern int smbw_debug; + + +int smbw_ref(int client_fd, Ref_Count_Type type, ...) +{ + va_list ap; + + /* client id values begin at SMBC_BASE_FC. */ + client_fd -= SMBC_BASE_FD; + + va_start(ap, type); + switch(type) + { + case SMBW_RCT_Increment: + return ++smbw_ref_count[client_fd]; + + case SMBW_RCT_Decrement: + return --smbw_ref_count[client_fd]; + + case SMBW_RCT_Get: + return smbw_ref_count[client_fd]; + + case SMBW_RCT_Set: + return (smbw_ref_count[client_fd] = va_arg(ap, int)); + } + va_end(ap); + + /* never gets here */ + return -1; +} + + +/* + * Return a username and password given a server and share name + * + * Returns 0 upon success; + * non-zero otherwise, and errno is set to indicate the error. + */ +static void get_envvar_auth_data(const char *srv, + const char *shr, + char *wg, int wglen, + char *un, int unlen, + char *pw, int pwlen) +{ + char *u; + char *p; + char *w; + + /* Fall back to environment variables */ + + w = getenv("WORKGROUP"); + if (w == NULL) w = ""; + + u = getenv("USER"); + if (u == NULL) u = ""; + + p = getenv("PASSWORD"); + if (p == NULL) p = ""; + + strncpy(wg, w, wglen); + strncpy(un, u, unlen); + strncpy(pw, p, pwlen); +} + +static smbc_get_auth_data_fn get_auth_data_fn = get_envvar_auth_data; + +/***************************************************** +set the get auth data function +******************************************************/ +void smbw_set_auth_data_fn(smbc_get_auth_data_fn fn) +{ + get_auth_data_fn = fn; +} + + +/***************************************************** +ensure that all connections are terminated upon exit +******************************************************/ +static void do_shutdown(void) +{ + if (smbw_ctx != NULL) { + smbc_free_context(smbw_ctx, 1); + } +} + + +/***************************************************** +initialise structures +*******************************************************/ +static void do_init(int is_real_startup) +{ + int i; + char *p; + + smbw_initialized = 1; /* this must be first to avoid recursion! */ + + smbw_ctx = NULL; /* don't free context until it's established */ + + /* initially, no file descriptors are mapped */ + for (i = 0; i < __FD_SETSIZE; i++) { + smbw_fd_map[i] = -1; + smbw_ref_count[i] = 0; + } + + /* See if we've been told to start in a particular directory */ + if ((p=getenv("SMBW_DIR")) != NULL) { + strncpy(smbw_cwd, p, PATH_MAX); + + /* we don't want the old directory to be busy */ + (* smbw_libc.chdir)("/"); + + } else { + *smbw_cwd = '\0'; + } + + if ((p=getenv("DEBUG"))) { + debug_level = atoi(p); + } + + if ((smbw_ctx = smbc_new_context()) == NULL) { + exit(1); + } + + smbw_ctx->debug = debug_level; + smbw_ctx->callbacks.auth_fn = get_auth_data_fn; + smbw_ctx->options.browse_max_lmb_count = 0; + smbw_ctx->options.urlencode_readdir_entries = 1; + smbw_ctx->options.one_share_per_server = 1; +// smbw_cache_functions(smbw_ctx); + + if (smbc_init_context(smbw_ctx) == NULL) { + exit(1); + } + + smbc_set_context(smbw_ctx); + + /* if not real startup, exit handler has already been established */ + if (is_real_startup) { + atexit(do_shutdown); + } +} + +/***************************************************** +initialise structures, real start up vs a fork() +*******************************************************/ +void smbw_init(void) +{ + do_init(1); +} + + +/***************************************************** +determine if a file descriptor is a smb one +*******************************************************/ +int smbw_fd(int smbw_fd) +{ + SMBW_INIT(); + + return (smbw_fd >= 0 && + smbw_fd < __FD_SETSIZE && + smbw_fd_map[smbw_fd] >= SMBC_BASE_FD); /* minimum smbc_ fd */ +} + + +/***************************************************** +determine if a path is a smb one +*******************************************************/ +int smbw_path(const char *name) +{ + int len; + int ret; + int saved_errno; + + saved_errno = errno; + + SMBW_INIT(); + + len = strlen(smbw_prefix); + + ret = ((strncmp(name, smbw_prefix, len) == 0 && + (name[len] == '\0' || name[len] == '/')) || + (*name != '/' && *smbw_cwd != '\0')); + + errno = saved_errno; + return ret; +} + + +/***************************************************** +remove redundent stuff from a filename +*******************************************************/ +void smbw_clean_fname(char *name) +{ + char *p, *p2; + int l; + int modified = 1; + + if (!name) return; + + DEBUG(10, ("Clean [%s]...\n", name)); + + while (modified) { + modified = 0; + + if ((p=strstr(name,"/./"))) { + modified = 1; + while (*p) { + p[0] = p[2]; + p++; + } + DEBUG(10, ("\tclean 1 (/./) produced [%s]\n", name)); + } + + if ((p=strstr(name,"//"))) { + modified = 1; + while (*p) { + p[0] = p[1]; + p++; + } + DEBUG(10, ("\tclean 2 (//) produced [%s]\n", name)); + } + + if (strcmp(name,"/../")==0) { + modified = 1; + name[1] = 0; + DEBUG(10,("\tclean 3 (^/../$) produced [%s]\n", name)); + } + + if ((p=strstr(name,"/../"))) { + modified = 1; + for (p2 = (p > name ? p-1 : p); p2 > name; p2--) { + if (p2[0] == '/') break; + } + if (p2 > name) p2++; + while (*p2) { + p2[0] = p[3]; + p2++; + p++; + } + DEBUG(10, ("\tclean 4 (/../) produced [%s]\n", name)); + } + + if (strcmp(name,"/..")==0) { + modified = 1; + name[1] = 0; + DEBUG(10, ("\tclean 5 (^/..$) produced [%s]\n", name)); + } + + l = strlen(name); + p = l>=3?(name+l-3):name; + if (strcmp(p,"/..")==0) { + modified = 1; + for (p2=p-1;p2>name;p2--) { + if (p2[0] == '/') break; + } + if (p2==name) { + p[0] = '/'; + p[1] = 0; + } else { + p2[0] = 0; + } + DEBUG(10, ("\tclean 6 (/..) produced [%s]\n", name)); + } + + l = strlen(name); + p = l>=2?(name+l-2):name; + if (strcmp(p,"/.")==0) { + modified = 1; + if (p == name) { + p[1] = 0; + } else { + p[0] = 0; + } + DEBUG(10, ("\tclean 7 (/.) produced [%s]\n", name)); + } + + if (strncmp(p=name,"./",2) == 0) { + modified = 1; + do { + p[0] = p[2]; + } while (*p++); + DEBUG(10, ("\tclean 8 (^./) produced [%s]\n", name)); + } + + l = strlen(p=name); + if (l > 1 && p[l-1] == '/') { + modified = 1; + p[l-1] = 0; + DEBUG(10, ("\tclean 9 (/) produced [%s]\n", name)); + } + } +} + +void smbw_fix_path(const char *src, char *dest) +{ + const char *p; + int len = strlen(smbw_prefix); + + if (*src == '/') { + for (p = src + len; *p == '/'; p++) + ; + snprintf(dest, PATH_MAX, "smb://%s", p); + } else { + snprintf(dest, PATH_MAX, "%s/%s", smbw_cwd, src); + } + + smbw_clean_fname(dest + 5); + + DEBUG(10, ("smbw_fix_path(%s) returning [%s]\n", src, dest)); +} + + + +/***************************************************** +a wrapper for open() +*******************************************************/ +int smbw_open(const char *fname, int flags, mode_t mode) +{ + int client_fd; + int smbw_fd; + char path[PATH_MAX]; + + SMBW_INIT(); + + if (!fname) { + errno = EINVAL; + return -1; + } + + smbw_fd = (smbw_libc.open)(SMBW_DUMMY, O_WRONLY, 0200); + if (smbw_fd == -1) { + errno = EMFILE; + return -1; + } + + smbw_fix_path(fname, path); + if (flags == creat_bits) { + client_fd = smbc_creat(path, mode); + } else { + client_fd = smbc_open(path, flags, mode); + } + + if (client_fd < 0) { + (* smbw_libc.close)(smbw_fd); + return -1; + } + + smbw_fd_map[smbw_fd] = client_fd; + smbw_ref(client_fd, SMBW_RCT_Increment); + return smbw_fd; +} + + +/***************************************************** +a wrapper for pread() + +there should really be an smbc_pread() to avoid the two +lseek()s required in this kludge. +*******************************************************/ +ssize_t smbw_pread(int smbw_fd, void *buf, size_t count, SMBW_OFF_T ofs) +{ + int client_fd; + ssize_t ret; + int saved_errno; + SMBW_OFF_T old_ofs; + + client_fd = smbw_fd_map[smbw_fd]; + + if ((old_ofs = smbc_lseek(client_fd, 0, SEEK_CUR)) < 0 || + smbc_lseek(client_fd, ofs, SEEK_SET) < 0) { + return -1; + } + + if ((ret = smbc_read(client_fd, buf, count)) < 0) { + saved_errno = errno; + (void) smbc_lseek(client_fd, old_ofs, SEEK_SET); + errno = saved_errno; + return -1; + } + + return ret; +} + +/***************************************************** +a wrapper for read() +*******************************************************/ +ssize_t smbw_read(int smbw_fd, void *buf, size_t count) +{ + int client_fd; + + client_fd = smbw_fd_map[smbw_fd]; + + return smbc_read(client_fd, buf, count); +} + + + +/***************************************************** +a wrapper for write() +*******************************************************/ +ssize_t smbw_write(int smbw_fd, void *buf, size_t count) +{ + int client_fd; + + client_fd = smbw_fd_map[smbw_fd]; + + return smbc_write(client_fd, buf, count); +} + +/***************************************************** +a wrapper for pwrite() +*******************************************************/ +ssize_t smbw_pwrite(int smbw_fd, void *buf, size_t count, SMBW_OFF_T ofs) +{ + int saved_errno; + int client_fd; + ssize_t ret; + SMBW_OFF_T old_ofs; + + client_fd = smbw_fd_map[smbw_fd]; + + if ((old_ofs = smbc_lseek(client_fd, 0, SEEK_CUR)) < 0 || + smbc_lseek(client_fd, ofs, SEEK_SET) < 0) { + return -1; + } + + if ((ret = smbc_write(client_fd, buf, count)) < 0) { + saved_errno = errno; + (void) smbc_lseek(client_fd, old_ofs, SEEK_SET); + errno = saved_errno; + return -1; + } + + return ret; +} + +/***************************************************** +a wrapper for close() +*******************************************************/ +int smbw_close(int smbw_fd) +{ + int client_fd; + + client_fd = smbw_fd_map[smbw_fd]; + + if (smbw_ref(client_fd, SMBW_RCT_Decrement) > 0) { + return 0; + } + + (* smbw_libc.close)(smbw_fd); + smbw_fd_map[smbw_fd] = -1; + return smbc_close(client_fd); +} + + +/********************************************* |
