1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

r6108: Added smbsh/smbwrapper for Linux to example/libsmbclient tree; provided more complete libsmbclient testbrowse utility

This commit is contained in:
Derrell Lipman 2005-03-29 00:42:51 +00:00 committed by Gerald (Jerry) Carter
parent 8c64cd368f
commit 15736b97c8
15 changed files with 4095 additions and 62 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}
/*****************************************************
a wrapper for fcntl()
*******************************************************/
int smbw_fcntl(int smbw_fd, int cmd, long arg)
{
return 0;
}
/*****************************************************
a wrapper for access()
*******************************************************/
int smbw_access(const char *name, int mode)
{
struct SMBW_stat st;
SMBW_INIT();
if (smbw_stat(name, &st)) return -1;
if (((mode & R_OK) && !(st.s_mode & S_IRUSR)) ||
((mode & W_OK) && !(st.s_mode & S_IWUSR)) ||
((mode & X_OK) && !(st.s_mode & S_IXUSR))) {
errno = EACCES;
return -1;
}
return 0;
}
/*****************************************************
a wrapper for readlink() - needed for correct errno setting
*******************************************************/
int smbw_readlink(const char *fname, char *buf, size_t bufsize)
{
struct SMBW_stat st;
int ret;
SMBW_INIT();
ret = smbw_stat(fname, &st);
if (ret != 0) {
return -1;
}
/* it exists - say it isn't a link */
errno = EINVAL;
return -1;
}
/*****************************************************
a wrapper for unlink()
*******************************************************/
int smbw_unlink(const char *fname)
{
char path[PATH_MAX];
SMBW_INIT();
smbw_fix_path(fname, path);
return smbc_unlink(path);
}
/*****************************************************
a wrapper for rename()
*******************************************************/
int smbw_rename(const char *oldname, const char *newname)
{
char path_old[PATH_MAX];
char path_new[PATH_MAX];
SMBW_INIT();
smbw_fix_path(oldname, path_old);
smbw_fix_path(newname, path_new);
return smbc_rename(path_old, path_new);
}
/*****************************************************
a wrapper for utimes
*******************************************************/
int smbw_utimes(const char *fname, void *buf)
{
char path[PATH_MAX];
smbw_fix_path(fname, path);
return smbc_utimes(path, buf);
}
/*****************************************************
a wrapper for utime
*******************************************************/
int smbw_utime(const char *fname, void *buf)
{
char path[PATH_MAX];
smbw_fix_path(fname, path);
return smbc_utime(path, buf);
}
/*****************************************************
a wrapper for chown()
*******************************************************/
int smbw_chown(const char *fname, uid_t owner, gid_t group)
{
/* always indiciate that this is not supported. */
errno = ENOTSUP;
return -1;
}
/*****************************************************
a wrapper for chmod()
*******************************************************/
int smbw_chmod(const char *fname, mode_t newmode)
{
char path[PATH_MAX];
smbw_fix_path(fname, path);
return smbc_chmod(path, newmode);
}
/*****************************************************
a wrapper for lseek()
*******************************************************/
SMBW_OFF_T smbw_lseek(int smbw_fd,
SMBW_OFF_T offset,
int whence)
{
int client_fd;
SMBW_OFF_T ret;
client_fd = smbw_fd_map[smbw_fd];
ret = smbc_lseek(client_fd, offset, whence);
if (smbw_debug)
{
printf("smbw_lseek(%d/%d, 0x%llx) returned 0x%llx\n",
smbw_fd, client_fd,
(unsigned long long) offset,
(unsigned long long) ret);
}
return ret;
}
/*****************************************************
a wrapper for dup()
*******************************************************/
int smbw_dup(int smbw_fd)
{
int fd2;
fd2 = (smbw_libc.dup)(smbw_fd);
if (fd2 == -1) {
return -1;
}
smbw_fd_map[fd2] = smbw_fd_map[smbw_fd];
smbw_ref(smbw_fd_map[smbw_fd], SMBW_RCT_Increment);
return fd2;
}
/*****************************************************
a wrapper for dup2()
*******************************************************/
int smbw_dup2(int smbw_fd, int fd2)
{
if ((* smbw_libc.dup2)(smbw_fd, fd2) != fd2) {
return -1;
}
smbw_fd_map[fd2] = smbw_fd_map[smbw_fd];
smbw_ref(smbw_fd_map[smbw_fd], SMBW_RCT_Increment);
return fd2;
}
/*****************************************************
when we fork we have to close all connections and files
in the child
*******************************************************/
int smbw_fork(void)
{
int i;
pid_t child_pid;
int p[2];
char c = 0;
SMBW_INIT();
if (pipe(p)) return (* smbw_libc.fork)();
child_pid = (* smbw_libc.fork)();
if (child_pid) {
/* block the parent for a moment until the sockets are
closed */
(* smbw_libc.close)(p[1]);
(* smbw_libc.read)(p[0], &c, 1);
(* smbw_libc.close)(p[0]);
return child_pid;
}
(* smbw_libc.close)(p[0]);
/* close all server connections and locally-opened files */
for (i = 0; i < __FD_SETSIZE; i++) {
if (smbw_fd_map[i] > 0 &&
smbw_ref(smbw_fd_map[i], SMBW_RCT_Get) > 0) {
smbc_close(smbw_fd_map[i]);
smbw_ref(smbw_fd_map[i], SMBW_RCT_Set, 0);
(* smbw_libc.close)(i);
}
smbw_fd_map[i] = -1;
}
/* unblock the parent */
write(p[1], &c, 1);
(* smbw_libc.close)(p[1]);
/* specify directory to start in, if it's simulated smb */
if (*smbw_cwd != '\0') {
setenv("SMBW_DIR", smbw_cwd, 1);
} else {
unsetenv("SMBW_DIR");
}
/* Re-initialize this library for the child */
do_init(0);
/* and continue in the child */
return 0;
}
int smbw_setxattr(const char *fname,
const char *name,
const void *value,
size_t size,
int flags)
{
char path[PATH_MAX];
if (strcmp(name, "system.posix_acl_access") == 0)
{
name = "system.*";
}
smbw_fix_path(fname, path);
return smbc_setxattr(path, name, value, size, flags);
}
int smbw_lsetxattr(const char *fname,
const char *name,
const void *value,
size_t size,
int flags)
{
char path[PATH_MAX];
if (strcmp(name, "system.posix_acl_access") == 0)
{
name = "system.*";
}
smbw_fix_path(fname, path);
return smbc_lsetxattr(path, name, value, size, flags);
}
int smbw_fsetxattr(int smbw_fd,
const char *name,
const void *value,
size_t size,
int flags)
{
int client_fd;
if (strcmp(name, "system.posix_acl_access") == 0)
{
name = "system.*";
}
client_fd = smbw_fd_map[smbw_fd];
return smbc_fsetxattr(client_fd, name, value, size, flags);
}
int smbw_getxattr(const char *fname,
const char *name,
const void *value,
size_t size)
{
char path[PATH_MAX];
if (strcmp(name, "system.posix_acl_access") == 0)
{
name = "system.*";
}
smbw_fix_path(fname, path);
return smbc_getxattr(path, name, value, size);
}
int smbw_lgetxattr(const char *fname,
const char *name,
const void *value,
size_t size)
{
char path[PATH_MAX];
if (strcmp(name, "system.posix_acl_access") == 0)
{
name = "system.*";
}
smbw_fix_path(fname, path);
return smbc_lgetxattr(path, name, value, size);
}
int smbw_fgetxattr(int smbw_fd,
const char *name,
const void *value,
size_t size)
{
int client_fd;
if (strcmp(name, "system.posix_acl_access") == 0)
{
name = "system.*";
}
client_fd = smbw_fd_map[smbw_fd];
return smbc_fgetxattr(client_fd, name, value, size);
}
int smbw_removexattr(const char *fname,
const char *name)
{
char path[PATH_MAX];
if (strcmp(name, "system.posix_acl_access") == 0)
{
name = "system.*";
}
smbw_fix_path(fname, path);
return smbc_removexattr(path, name);
}
int smbw_lremovexattr(const char *fname,
const char *name)
{
char path[PATH_MAX];
if (strcmp(name, "system.posix_acl_access") == 0)
{
name = "system.*";
}
smbw_fix_path(fname, path);
return smbc_lremovexattr(path, name);
}
int smbw_fremovexattr(int smbw_fd,
const char *name)
{
int client_fd;
if (strcmp(name, "system.posix_acl_access") == 0)
{
name = "system.*";
}
client_fd = smbw_fd_map[smbw_fd];
return smbc_fremovexattr(client_fd, name);
}
int smbw_listxattr(const char *fname,
char *list,
size_t size)
{
char path[PATH_MAX];
smbw_fix_path(fname, path);
return smbc_listxattr(path, list, size);
}
int smbw_llistxattr(const char *fname,
char *list,
size_t size)
{
char path[PATH_MAX];
smbw_fix_path(fname, path);
return smbc_llistxattr(path, list, size);
}
int smbw_flistxattr(int smbw_fd,
char *list,
size_t size)
{
int client_fd;
client_fd = smbw_fd_map[smbw_fd];
return smbc_flistxattr(client_fd, list, size);
}

View File

@ -0,0 +1,163 @@
/*
Unix SMB/Netbios implementation.
Version 2.0
SMB wrapper functions - definitions
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.
*/
#ifndef _SMBW_H
#define _SMBW_H
#include <sys/types.h>
#include <errno.h>
#include <malloc.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "config.h" /* must come before libsmbclient.h */
#include "libsmbclient.h"
#include "wrapper.h"
#undef DEBUG
#define DEBUG(level, s) do { if (level <= debug_level) printf s; } while (0)
#define SMBW_PREFIX "/smb"
#define SMBW_DUMMY "/dev/null"
extern int smbw_initialized;
#define SMBW_INIT() do { if (! smbw_initialized) smbw_init(); } while (0)
#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T)
# define SMBW_OFF_T off64_t
#else
# define SMBW_OFF_T off_t
#endif
/* The following definitions come from smbwrapper/smbw.c */
typedef enum {
SMBW_RCT_Increment,
SMBW_RCT_Decrement,
SMBW_RCT_Get,
SMBW_RCT_Set
} Ref_Count_Type;
int smbw_ref(int client_fd, Ref_Count_Type type, ...);
void smbw_init(void);
int smbw_fd(int fd);
int smbw_path(const char *path);
void smbw_clean_fname(char *name);
void smbw_fix_path(const char *src, char *dest);
void smbw_set_auth_data_fn(smbc_get_auth_data_fn fn);
int smbw_open(const char *fname, int flags, mode_t mode);
ssize_t smbw_pread(int fd, void *buf, size_t count, SMBW_OFF_T ofs);
ssize_t smbw_read(int fd, void *buf, size_t count);
ssize_t smbw_write(int fd, void *buf, size_t count);
ssize_t smbw_pwrite(int fd, void *buf, size_t count, SMBW_OFF_T ofs);
int smbw_close(int fd);
int smbw_fcntl(int fd, int cmd, long arg);
int smbw_access(const char *name, int mode);
int smbw_readlink(const char *path, char *buf, size_t bufsize);
int smbw_unlink(const char *fname);
int smbw_rename(const char *oldname, const char *newname);
int smbw_utime(const char *fname, void *buf);
int smbw_utimes(const char *fname, void *buf);
int smbw_chown(const char *fname, uid_t owner, gid_t group);
int smbw_chmod(const char *fname, mode_t newmode);
SMBW_OFF_T smbw_lseek(int smbw_fd, SMBW_OFF_T offset, int whence);
int smbw_dup(int fd);
int smbw_dup2(int fd, int fd2);
int smbw_fork(void);
/* The following definitions come from smbwrapper/smbw_dir.c */
int smbw_dirp(DIR * dirp);
int smbw_dir_open(const char *fname);
int smbw_dir_fstat(int fd, SMBW_stat *st);
int smbw_dir_close(int fd);
int smbw_getdents(unsigned int fd, SMBW_dirent *dirp, int count);
int smbw_chdir(const char *name);
int smbw_mkdir(const char *fname, mode_t mode);
int smbw_rmdir(const char *fname);
char *smbw_getcwd(char *buf, size_t size);
int smbw_fchdir(int fd);
DIR *smbw_opendir(const char *fname);
SMBW_dirent *smbw_readdir(DIR *dirp);
int smbw_readdir_r(DIR *dirp,
struct SMBW_dirent *__restrict entry,
struct SMBW_dirent **__restrict result);
int smbw_closedir(DIR *dirp);
void smbw_seekdir(DIR *dirp, long long offset);
long long smbw_telldir(DIR *dirp);
int smbw_setxattr(const char *fname,
const char *name,
const void *value,
size_t size,
int flags);
int smbw_lsetxattr(const char *fname,
const char *name,
const void *value,
size_t size,
int flags);
int smbw_fsetxattr(int smbw_fd,
const char *name,
const void *value,
size_t size,
int flags);
int smbw_getxattr(const char *fname,
const char *name,
const void *value,
size_t size);
int smbw_lgetxattr(const char *fname,
const char *name,
const void *value,
size_t size);
int smbw_fgetxattr(int smbw_fd,
const char *name,
const void *value,
size_t size);
int smbw_removexattr(const char *fname,
const char *name);
int smbw_lremovexattr(const char *fname,
const char *name);
int smbw_fremovexattr(int smbw_fd,
const char *name);
int smbw_listxattr(const char *fname,
char *list,
size_t size);
int smbw_llistxattr(const char *fname,
char *list,
size_t size);
int smbw_flistxattr(int smbw_fd,
char *list,
size_t size);
/* The following definitions come from smbwrapper/smbw_stat.c */
int smbw_fstat(int fd, SMBW_stat *st);
int smbw_stat(const char *fname, SMBW_stat *st);
/* The following definitions come from smbwrapper/cache.c */
int
smbw_cache_functions(SMBCCTX * context);
#endif /* _SMBW_H */

View File

@ -0,0 +1,355 @@
/*
Unix SMB/Netbios implementation.
Version 2.0
SMB wrapper directory 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 "smbw.h"
/*****************************************************
determine if a directory handle is a smb one
*******************************************************/
int smbw_dirp(DIR * dirp)
{
return ((char *) dirp >= (char *) smbw_fd_map &&
(char *) dirp < (char *) &smbw_fd_map[__FD_SETSIZE] &&
*(int *) dirp != -1);
}
/*****************************************************
a wrapper for getdents()
*******************************************************/
int smbw_getdents(unsigned int fd_smbw,
struct SMBW_dirent *dirent_external,
int count)
{
int remaining;
int fd_client = smbw_fd_map[fd_smbw];
struct smbc_dirent *dirent_internal;
for (remaining = count;
remaining > sizeof(struct SMBW_dirent);
dirent_external++) {
/*
* We do these one at a time because there's otherwise no way
* to limit how many smbc_getdents() will return for us, and
* if it returns too many, it also doesn't give us offsets to
* be able to seek back to where we need to be. In practice,
* this one-at-a-time retrieval isn't a problem because the
* time-consuming network transaction is all done at
* smbc_opendir() time.
*/
dirent_internal = smbc_readdir(fd_client);
if (dirent_internal == NULL) {
break;
}
remaining -= sizeof(struct SMBW_dirent);
dirent_external->d_ino = -1; /* not supported */
dirent_external->d_off = smbc_telldir(fd_client);
dirent_external->d_reclen = sizeof(struct SMBW_dirent);
dirent_external->d_type = dirent_internal->smbc_type;
strncpy(dirent_external->d_name,
dirent_internal->name,
sizeof(dirent_external->d_name) - 1);
strncpy(dirent_external->d_comment,
dirent_internal->comment,
sizeof(dirent_external->d_comment) - 1);
}
return(count - remaining);
}
/*****************************************************
a wrapper for chdir()
*******************************************************/
int smbw_chdir(const char *name)
{
int simulate;
struct stat statbuf;
char path[PATH_MAX];
char *p;
SMBW_INIT();
if (!name) {
errno = EINVAL;
return -1;
}
if (! smbw_path((char *) name)) {
if ((* smbw_libc.chdir)(name) == 0) {
*smbw_cwd = '\0';
return 0;
}
return -1;
}
smbw_fix_path(name, path);
/* ensure it exists */
p = path + 6; /* look just past smb:// */
simulate = (strchr(p, '/') == NULL);
/* special case for full-network scan, workgroups, and servers */
if (! simulate) {
if (smbc_stat(path, &statbuf) < 0) {
return -1;
}
/* ensure it's a directory */
if (! S_ISDIR(statbuf.st_mode)) {
errno = ENOTDIR;
return -1;
}
}
strncpy(smbw_cwd, path, PATH_MAX);
/* we don't want the old directory to be busy */
(* smbw_libc.chdir)("/");
return 0;
}
/*****************************************************
a wrapper for mkdir()
*******************************************************/
int smbw_mkdir(const char *fname, mode_t mode)
{
char path[PATH_MAX];
if (!fname) {
errno = EINVAL;
return -1;
}
SMBW_INIT();
smbw_fix_path(fname, path);
return smbc_mkdir(path, mode);
}
/*****************************************************
a wrapper for rmdir()
*******************************************************/
int smbw_rmdir(const char *fname)
{
char path[PATH_MAX];
if (!fname) {
errno = EINVAL;
return -1;
}
SMBW_INIT();
smbw_fix_path(fname, path);
return smbc_rmdir(path);
}
/*****************************************************
a wrapper for getcwd()
*******************************************************/
char *smbw_getcwd(char *buf, size_t size)
{
SMBW_INIT();
if (*smbw_cwd == '\0') {
return (* smbw_libc.getcwd)(buf, size);
}
if (buf == NULL) {
if (size == 0) {
size = strlen(smbw_cwd) + 1;
}
buf = malloc(size);
if (buf == NULL) {
errno = ENOMEM;
return NULL;
}
}
strncpy(buf, smbw_cwd, size);
buf[size-1] = '\0';
return buf;
}
/*****************************************************
a wrapper for fchdir()
*******************************************************/
int smbw_fchdir(int fd_smbw)
{
int ret;
SMBW_INIT();
if (! smbw_fd(fd_smbw)) {
ret = (* smbw_libc.fchdir)(fd_smbw);
(void) (* smbw_libc.getcwd)(smbw_cwd, PATH_MAX);
return ret;
}
errno = EACCES;
return -1;
}
/*****************************************************
open a directory on the server
*******************************************************/
DIR *smbw_opendir(const char *fname)
{
int fd_client;
int fd_smbw;
char path[PATH_MAX];
DIR * dirp;
SMBW_INIT();
if (!fname) {
errno = EINVAL;
return NULL;
}
fd_smbw = (smbw_libc.open)(SMBW_DUMMY, O_WRONLY, 0200);
if (fd_smbw == -1) {
errno = EMFILE;
return NULL;
}
smbw_fix_path(fname, path);
fd_client = smbc_opendir(path);
if (fd_client < 0) {
(* smbw_libc.close)(fd_smbw);
return NULL;
}
smbw_fd_map[fd_smbw] = fd_client;
smbw_ref(fd_client, SMBW_RCT_Increment);
dirp = (DIR *) &smbw_fd_map[fd_smbw];
return dirp;
}
/*****************************************************
read one entry from a directory
*******************************************************/
struct SMBW_dirent *smbw_readdir(DIR *dirp)
{
int fd_smbw;
int fd_client;
struct smbc_dirent *dirent_internal;
static struct SMBW_dirent dirent_external;
fd_smbw = (int *) dirp - smbw_fd_map;
fd_client = smbw_fd_map[fd_smbw];
if ((dirent_internal = smbc_readdir(fd_client)) == NULL) {
return NULL;
}
dirent_external.d_ino = -1; /* not supported */
dirent_external.d_off = smbc_telldir(fd_client);
dirent_external.d_reclen = sizeof(struct SMBW_dirent);
dirent_external.d_type = dirent_internal->smbc_type;
strncpy(dirent_external.d_name,
dirent_internal->name,
sizeof(dirent_external.d_name) - 1);
strncpy(dirent_external.d_comment,
dirent_internal->comment,
sizeof(dirent_external.d_comment) - 1);
return &dirent_external;
}
/*****************************************************
read one entry from a directory in a reentrant fashion
ha! samba is not re-entrant, and neither is the
libsmbclient library
*******************************************************/
int smbw_readdir_r(DIR *dirp,
struct SMBW_dirent *__restrict entry,
struct SMBW_dirent **__restrict result)
{
SMBW_dirent *dirent;
dirent = smbw_readdir(dirp);
if (dirent != NULL) {
*entry = *dirent;
if (result != NULL) {
*result = entry;
}
return 0;
}
if (result != NULL) {
*result = NULL;
}
return EBADF;
}
/*****************************************************
close a DIR*
*******************************************************/
int smbw_closedir(DIR *dirp)
{
int fd_smbw = (int *) dirp - smbw_fd_map;
int fd_client = smbw_fd_map[fd_smbw];
(* smbw_libc.close)(fd_smbw);
if (smbw_ref(fd_client, SMBW_RCT_Decrement) > 0) {
return 0;
}
smbw_fd_map[fd_smbw] = -1;
return smbc_closedir(fd_client);
}
/*****************************************************
seek in a directory
*******************************************************/
void smbw_seekdir(DIR *dirp, long long offset)
{
int fd_smbw = (int *) dirp - smbw_fd_map;
int fd_client = smbw_fd_map[fd_smbw];
smbc_lseekdir(fd_client, offset);
}
/*****************************************************
current loc in a directory
*******************************************************/
long long smbw_telldir(DIR *dirp)
{
int fd_smbw = (int *) dirp - smbw_fd_map;
int fd_client = smbw_fd_map[fd_smbw];
return (long long) smbc_telldir(fd_client);
}

View File

@ -0,0 +1,146 @@
/*
Unix SMB/Netbios implementation.
Version 2.0
SMB wrapper stat 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 "smbw.h"
static int timezone_diff = -1;
#define TM_YEAR_BASE 1900
/*******************************************************************
yield the difference between *A and *B, in seconds, ignoring leap seconds
********************************************************************/
static int tm_diff(struct tm *a, struct tm *b)
{
int ay = a->tm_year + (TM_YEAR_BASE - 1);
int by = b->tm_year + (TM_YEAR_BASE - 1);
int intervening_leap_days =
(ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
int years = ay - by;
int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
int hours = 24*days + (a->tm_hour - b->tm_hour);
int minutes = 60*hours + (a->tm_min - b->tm_min);
int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
return seconds;
}
/*******************************************************************
return the UTC offset in seconds west of UTC, or 0 if it cannot be determined
******************************************************************/
static int TimeZone(time_t t)
{
struct tm *tm = gmtime(&t);
struct tm tm_utc;
if (!tm)
return 0;
tm_utc = *tm;
tm = localtime(&t);
if (!tm)
return 0;
return tm_diff(&tm_utc,tm);
}
static void copy_stat(struct SMBW_stat *external, struct stat *internal)
{
if (timezone_diff < 0)
{
timezone_diff = TimeZone(time(NULL));
}
external->s_dev = internal->st_dev;
external->s_ino = internal->st_ino;
external->s_mode = internal->st_mode;
external->s_nlink = internal->st_nlink;
external->s_uid = internal->st_uid;
external->s_gid = internal->st_gid;
external->s_rdev = internal->st_rdev;
external->s_size = internal->st_size;
external->s_blksize = internal->st_blksize;
external->s_blocks = internal->st_blocks;
external->s_atime = internal->st_atime + timezone_diff;
external->s_mtime = internal->st_mtime + timezone_diff;
external->s_ctime = internal->st_ctime + timezone_diff;
}
/*****************************************************
a wrapper for fstat()
*******************************************************/
int smbw_fstat(int fd_smbw, struct SMBW_stat *st)
{
int fd_client = smbw_fd_map[fd_smbw];
struct stat statbuf;
if (smbc_fstat(fd_client, &statbuf) < 0) {
return -1;
}
copy_stat(st, &statbuf);
return 0;
}
/*****************************************************
a wrapper for stat()
*******************************************************/
int smbw_stat(const char *fname, struct SMBW_stat *st)
{
int simulate;
char *p;
char path[PATH_MAX];
struct stat statbuf;
SMBW_INIT();
smbw_fix_path(fname, path);
p = path + 6; /* look just past smb:// */
simulate = (strchr(p, '/') == NULL);
/* special case for full-network scan, workgroups, and servers */
if (simulate) {
statbuf.st_dev = 0;
statbuf.st_ino = 0;
statbuf.st_mode = 0040777;
statbuf.st_nlink = 1;
statbuf.st_uid = 0;
statbuf.st_gid = 0;
statbuf.st_rdev = 0;
statbuf.st_size = 0;
statbuf.st_blksize = 1024;
statbuf.st_blocks = 1;
statbuf.st_atime = 0; /* beginning of epoch */
statbuf.st_mtime = 0; /* beginning of epoch */
statbuf.st_ctime = 0; /* beginning of epoch */
} else if (smbc_stat(path, &statbuf) < 0) {
return -1;
}
copy_stat(st, &statbuf);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,209 @@
/*
Unix SMB/Netbios implementation.
Version 2.0
SMB wrapper functions
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.
*/
#ifndef __WRAPPER_H__
#define __WRAPPER_H__
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#include <utime.h>
#include <signal.h>
#include <stdio.h>
extern int smbw_fd_map[__FD_SETSIZE];
extern int smbw_ref_count[__FD_SETSIZE];
extern char smbw_cwd[PATH_MAX];
extern char smbw_prefix[];
typedef struct SMBW_stat {
unsigned long s_dev; /* device */
unsigned long s_ino; /* inode */
unsigned long s_mode; /* protection */
unsigned long s_nlink; /* number of hard links */
unsigned long s_uid; /* user ID of owner */
unsigned long s_gid; /* group ID of owner */
unsigned long s_rdev; /* device type (if inode device) */
unsigned long long s_size; /* total size, in bytes */
unsigned long s_blksize; /* blocksize for filesystem I/O */
unsigned long s_blocks; /* number of blocks allocated */
unsigned long s_atime; /* time of last access */
unsigned long s_mtime; /* time of last modification */
unsigned long s_ctime; /* time of last change */
} SMBW_stat;
typedef struct SMBW_dirent {
unsigned long d_ino; /* inode number */
unsigned long long d_off; /* offset to the next dirent */
unsigned long d_reclen; /* length of this record */
unsigned long d_type; /* type of file */
char d_name[256]; /* filename */
char d_comment[256]; /* comment */
} SMBW_dirent;
struct kernel_sigaction {
__sighandler_t k_sa_handler;
unsigned long sa_flags;
sigset_t sa_mask;
};
typedef struct SMBW_libc
{
/* write() is first, to allow debugging */
ssize_t (* write)(int fd, void *buf, size_t count);
int (* open)(char *name, int flags, mode_t mode);
int (* _open)(char *name, int flags, mode_t mode) ;
int (* __open)(char *name, int flags, mode_t mode) ;
int (* open64)(char *name, int flags, mode_t mode);
int (* _open64)(char *name, int flags, mode_t mode) ;
int (* __open64)(char *name, int flags, mode_t mode) ;
ssize_t (* pread)(int fd, void *buf, size_t size, off_t ofs);
ssize_t (* pread64)(int fd, void *buf, size_t size, off64_t ofs);
ssize_t (* pwrite)(int fd, void *buf, size_t size, off_t ofs);
ssize_t (* pwrite64)(int fd, void *buf, size_t size, off64_t ofs);
int (* close)(int fd);
int (* __close)(int fd);
int (* _close)(int fd);
int (* fcntl)(int fd, int cmd, long arg);
int (* __fcntl)(int fd, int cmd, long arg);
int (* _fcntl)(int fd, int cmd, long arg);
int (* getdents)(int fd, struct dirent *dirp, unsigned int count);
int (* __getdents)(int fd, struct dirent *dirp, unsigned int count);
int (* _getdents)(int fd, struct dirent *dirp, unsigned int count);
int (* getdents64)(int fd, struct dirent64 *dirp, unsigned int count);
off_t (* lseek)(int fd, off_t offset, int whence);
off_t (* __lseek)(int fd, off_t offset, int whence);
off_t (* _lseek)(int fd, off_t offset, int whence);
off64_t (* lseek64)(int fd, off64_t offset, int whence);
off64_t (* __lseek64)(int fd, off64_t offset, int whence);
off64_t (* _lseek64)(int fd, off64_t offset, int whence);
ssize_t (* read)(int fd, void *buf, size_t count);
ssize_t (* __read)(int fd, void *buf, size_t count);
ssize_t (* _read)(int fd, void *buf, size_t count);
ssize_t (* __write)(int fd, void *buf, size_t count);
ssize_t (* _write)(int fd, void *buf, size_t count);
int (* access)(char *name, int mode);
int (* chmod)(char *name, mode_t mode);
int (* fchmod)(int fd, mode_t mode);
int (* chown)(char *name, uid_t owner, gid_t group);
int (* fchown)(int fd, uid_t owner, gid_t group);
int (* __xstat)(int vers, char *name, struct stat *st);
char * ( *getcwd)(char *buf, size_t size);
int (* mkdir)(char *name, mode_t mode);
int (* __fxstat)(int vers, int fd, struct stat *st);
int (* __lxstat)(int vers, char *name, struct stat *st);
int (* stat)(char *name, struct stat *st);
int (* lstat)(char *name, struct stat *st);
int (* fstat)(int fd, struct stat *st);
int (* unlink)(char *name);
int (* utime)(char *name, struct utimbuf *tvp);
int (* utimes)(char *name, struct timeval *tvp);
int (* readlink)(char *path, char *buf, size_t bufsize);
int (* rename)(char *oldname, char *newname);
int (* rmdir)(char *name);
int (* symlink)(char *topath, char *frompath);
int (* dup)(int fd);
int (* dup2)(int oldfd, int newfd);
DIR * (* opendir)(char *name);
struct dirent * (* readdir)(DIR *dir);
int (* closedir)(DIR *dir);
off_t (* telldir)(DIR *dir);
void (* seekdir)(DIR *dir, off_t offset);
int (* creat)(char *path, mode_t mode);
int (* creat64)(char *path, mode_t mode);
int (* __xstat64)(int ver, char *name, struct stat64 *st64);
int (* stat64)(char *name, struct stat64 *st64);
int (* __fxstat64)(int ver, int fd, struct stat64 *st64);
int (* fstat64)(int fd, struct stat64 *st64);
int (* __lxstat64)(int ver, char *name, struct stat64 *st64);
int (* lstat64)(char *name, struct stat64 *st64);
int (* _llseek)(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t *result, unsigned int whence);
struct dirent64 * (* readdir64)(DIR *dir);
int (* readdir_r)(DIR *dir, struct dirent *entry, struct dirent **result);
int (* readdir64_r)(DIR *dir, struct dirent64 *entry, struct dirent64 **result);
int (* setxattr)(const char *fname,
const char *name,
const void *value,
size_t size,
int flags);
int (* lsetxattr)(const char *fname,
const char *name,
const void *value,
size_t size,
int flags);
int (* fsetxattr)(int smbw_fd,
const char *name,
const void *value,
size_t size,
int flags);
int (* getxattr)(const char *fname,
const char *name,
const void *value,
size_t size);
int (* lgetxattr)(const char *fname,
const char *name,
const void *value,
size_t size);
int (* fgetxattr)(int smbw_fd,
const char *name,
const void *value,
size_t size);
int (* removexattr)(const char *fname,
const char *name);
int (* lremovexattr)(const char *fname,
const char *name);
int (* fremovexattr)(int smbw_fd,
const char *name);
int (* listxattr)(const char *fname,
char *list,
size_t size);
int (* llistxattr)(const char *fname,
char *list,
size_t size);
int (* flistxattr)(int smbw_fd,
char *list,
size_t size);
int (* chdir)(const char *path);
int (* fchdir)(int fd);
pid_t (* fork)(void);
int (* select)(int n,
fd_set *readfds,
fd_set *writefds,
fd_set *exceptfds,
struct timeval *timeout);
int (* _select)(int n,
fd_set *readfds,
fd_set *writefds,
fd_set *exceptfds,
struct timeval *timeout);
int (* __select)(int n,
fd_set *readfds,
fd_set *writefds,
fd_set *exceptfds,
struct timeval *timeout);
} SMBW_libc_pointers;
extern SMBW_libc_pointers smbw_libc;
#endif /* __WRAPPER_H__ */

View File

@ -1,91 +1,202 @@
/*
Unix SMB/CIFS implementation.
SMB client library test program for browsing with different master browsers
Copyright (C) Derrell Lipman 2004
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 <errno.h>
#include <sys/time.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <popt.h>
#include <libsmbclient.h>
#include <stdlib.h>
void error_message(char * pMessage)
{
printf("ERROR: %s\n", pMessage);
}
static void
auth_fn(const char * pServer,
const char * pShare,
char * pWorkgroup,
int workgroup_len,
char * pUsername,
int username_len,
char * pPassword,
int password_len)
get_auth_data_fn(const char * pServer,
const char * pShare,
char * pWorkgroup,
int maxLenWorkgroup,
char * pUsername,
int maxLenUsername,
char * pPassword,
int maxLenPassword)
{
strncpy(pUsername, "anonymous", username_len); /* doesn't matter what */
strncpy(pPassword, "password", password_len); /* ditto */
char temp[128];
printf("Entered get_auth_data_fn\n");
fprintf(stdout, "Need password for //%s/%s\n", pServer, pShare);
fprintf(stdout, "Username: [%s] ", pUsername);
fgets(temp, sizeof(temp), stdin);
if (temp[strlen(temp) - 1] == '\n') /* A new line? */
{
temp[strlen(temp) - 1] = '\0';
}
if (temp[0] != '\0')
{
strncpy(pUsername, temp, maxLenUsername - 1);
}
strcpy(temp, getpass("Password: "));
if (temp[strlen(temp) - 1] == '\n') /* A new line? */
{
temp[strlen(temp) - 1] = '\0';
}
if (temp[0] != '\0')
{
strncpy(pPassword, temp, maxLenPassword - 1);
}
fprintf(stdout, "Workgroup: ");
fgets(temp, sizeof(temp), stdin);
if (temp[strlen(temp) - 1] == '\n') /* A new line? */
{
temp[strlen(temp) - 1] = '\0';
}
if (temp[0] != '\0')
{
strncpy(pWorkgroup, temp, maxLenWorkgroup - 1);
}
putchar('\n');
}
int
main(int argc, char * argv[])
{
int debug = 4;
int debug = 0;
int opt;
char * p;
char * q;
char buf[1024];
int dir;
struct stat stat;
struct smbc_dirent * dirent;
char ** ppUrl;
char * urlList[] =
poptContext pc;
struct poptOption long_options[] =
{
"smb://",
"smb://?mb=.any",
"smb://?mb=.all",
"smb://?mb=xx", /* this one is suupposed to fail */
NULL
POPT_AUTOHELP
{
"debug", 'd', POPT_ARG_INT, &debug,
0, "Set debug level", "integer"
},
{
NULL
}
};
if (smbc_init(auth_fn, debug) != 0)
setbuf(stdout, NULL);
pc = poptGetContext("opendir", argc, (const char **)argv, long_options, 0);
poptSetOtherOptionHelp(pc, "");
while ((opt = poptGetNextOpt(pc)) != -1) {
printf("Got option %d = %c\n", opt, opt);
switch (opt) {
}
}
if (smbc_init(get_auth_data_fn, debug) != 0)
{
printf("Could not initialize smbc_ library\n");
return 1;
}
for (ppUrl = urlList; *ppUrl != NULL; ppUrl++)
for (fputs("url: ", stdout), p = fgets(buf, sizeof(buf), stdin);
p != NULL && *p != '\n' && *p != '\0';
fputs("url: ", stdout), p = fgets(buf, sizeof(buf), stdin))
{
printf("Opening (%s)...\n", *ppUrl);
if ((dir = smbc_opendir(*ppUrl)) < 0)
if ((p = strchr(buf, '\n')) != NULL)
{
printf("Could not open [%s] (%d:%s)\n",
*ppUrl, errno, strerror(errno));
*p = '\0';
}
printf("Opening (%s)...\n", buf);
if ((dir = smbc_opendir(buf)) < 0)
{
printf("Could not open directory [%s] (%d:%s)\n",
buf, errno, strerror(errno));
continue;
}
while ((dirent = smbc_readdir(dir)) != NULL)
{
printf("%s\n", dirent->name);
printf("%-30s", dirent->name);
printf("%-30s", dirent->comment);
switch(dirent->smbc_type)
{
case SMBC_WORKGROUP:
printf("WORKGROUP");
break;
case SMBC_SERVER:
printf("SERVER");
break;
case SMBC_FILE_SHARE:
printf("FILE_SHARE");
break;
case SMBC_PRINTER_SHARE:
printf("PRINTER_SHARE");
break;
case SMBC_COMMS_SHARE:
printf("COMMS_SHARE");
break;
case SMBC_IPC_SHARE:
printf("IPC_SHARE");
break;
case SMBC_DIR:
printf("DIR");
break;
case SMBC_FILE:
printf("FILE");
q = buf + strlen(buf);
strcat(q, "/");
strcat(q+1, dirent->name);
if (smbc_stat(buf, &stat) < 0)
{
printf(" unknown size (reason %d: %s)",
errno, strerror(errno));
}
else
{
printf(" size %lu", (unsigned long) stat.st_size);
}
*p = '\0';
break;
case SMBC_LINK:
printf("LINK");
break;
}
printf("\n");
}
smbc_closedir(dir);
}
exit(0);
}

View File

@ -132,7 +132,7 @@ int main(int argc, char *argv[])
((struct smbc_dirent *)dirp)->comment);
dirp += dsize;
(char *)dirc -= dsize;
dirc -= dsize;
}

View File

@ -294,7 +294,7 @@ static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
gtk_clist_append(GTK_CLIST(clist), rowdata);
(char *)dirp += dirlen;
dirp = (struct smbc_dirent *) ((char *) dirp + dirlen);
err -= dirlen;
}
@ -429,7 +429,7 @@ static void cb_itemsignal( GtkWidget *item,
}
(char *)dirp += dirlen;
dirp = (struct smbc_dirent *) ((char *) dirp + dirlen);
err -= dirlen;
}
@ -564,7 +564,7 @@ static void cb_wholenet(GtkWidget *item, gchar *signame)
gtk_signal_connect(GTK_OBJECT(subtree), "unselect_child",
GTK_SIGNAL_FUNC(cb_unselect_child), real_tree);
(char *)dirp += dirlen;
dirp = (struct smbc_dirent *) ((char *) dirp + dirlen);
err -= dirlen;
}
@ -797,7 +797,7 @@ int main( int argc,
gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
GTK_SIGNAL_FUNC(cb_unselect_child), tree);
(char *)dirp += dirlen;
dirp = (struct smbc_dirent *) ((char *) dirp + dirlen);
err -= dirlen;
}