summaryrefslogtreecommitdiff
path: root/source3/smbwrapper
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>1998-10-02 12:37:31 +0000
committerAndrew Tridgell <tridge@samba.org>1998-10-02 12:37:31 +0000
commit24bf006d5224e59d2d073ca4a7cb2df838c4c6c7 (patch)
tree67360075f9d28f60661056afb9b5a335c5b7b86b /source3/smbwrapper
parent019c8d2fdda74dc03d9089eacfbd2b77e1056169 (diff)
downloadsamba-24bf006d5224e59d2d073ca4a7cb2df838c4c6c7.tar.gz
samba-24bf006d5224e59d2d073ca4a7cb2df838c4c6c7.tar.bz2
samba-24bf006d5224e59d2d073ca4a7cb2df838c4c6c7.zip
the guts of the smbwrapper code. I may change the layout of this at
some stage. (This used to be commit 3f34a3cac817de19d227c36bc792db8b2c3798f9)
Diffstat (limited to 'source3/smbwrapper')
-rw-r--r--source3/smbwrapper/README26
-rw-r--r--source3/smbwrapper/access.c32
-rw-r--r--source3/smbwrapper/chdir.c28
-rw-r--r--source3/smbwrapper/close.c35
-rw-r--r--source3/smbwrapper/fcntl.c35
-rw-r--r--source3/smbwrapper/fstat.c84
-rw-r--r--source3/smbwrapper/getdents.c36
-rw-r--r--source3/smbwrapper/init.c22
-rw-r--r--source3/smbwrapper/kernel_stat.h31
-rw-r--r--source3/smbwrapper/lstat.c85
-rw-r--r--source3/smbwrapper/open.c36
-rw-r--r--source3/smbwrapper/read.c35
-rw-r--r--source3/smbwrapper/realcalls.h44
-rwxr-xr-xsource3/smbwrapper/smbsh6
-rw-r--r--source3/smbwrapper/smbw.c1005
-rw-r--r--source3/smbwrapper/smbw.h28
-rw-r--r--source3/smbwrapper/stat.c89
-rw-r--r--source3/smbwrapper/wrapper.h8
-rw-r--r--source3/smbwrapper/write.c35
19 files changed, 1700 insertions, 0 deletions
diff --git a/source3/smbwrapper/README b/source3/smbwrapper/README
new file mode 100644
index 0000000000..be345b5566
--- /dev/null
+++ b/source3/smbwrapper/README
@@ -0,0 +1,26 @@
+This is a prelodable shared library that provides SMB client services
+for existing executables. Using this you can simulate a smb
+filesystem.
+
+Currently this code only works on Linux with glibc2. Eventually I hope
+to make it portable to lots of OSes but at the moment if you don't
+have Linux then don't even try to use it.
+
+To use it you need to do this:
+
+export SMBW_USER=username
+export SMBW_PASSWORD=username
+export LD_PRELOAD=full_path_to_smbwrapper.so
+
+then try to access /smb/SERVER/SHARE/ and see what happens.
+
+For debugging you can set SMBW_DEBUG to an integer debug level.
+
+This is code under development. Lots of things don't work yet. Quite a
+few things do though, for example I've successfully run tar, less, ls,
+bash, cmp, cat, du and a bunch of other utilities on files accessed
+via this library.
+
+If you want to help with the development of this code then join the
+samba-technical mailing list.
+
diff --git a/source3/smbwrapper/access.c b/source3/smbwrapper/access.c
new file mode 100644
index 0000000000..4e77113108
--- /dev/null
+++ b/source3/smbwrapper/access.c
@@ -0,0 +1,32 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+ SMB wrapper functions
+ Copyright (C) Andrew Tridgell 1998
+
+ 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 "wrapper.h"
+
+ int access(__const char *name, int mode)
+{
+ if (smbw_path(name)) {
+ return smbw_access(name, mode);
+ }
+
+ return real_access(name, mode);
+}
+
diff --git a/source3/smbwrapper/chdir.c b/source3/smbwrapper/chdir.c
new file mode 100644
index 0000000000..13e9e0fa55
--- /dev/null
+++ b/source3/smbwrapper/chdir.c
@@ -0,0 +1,28 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+ SMB wrapper functions
+ Copyright (C) Andrew Tridgell 1998
+
+ 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 "wrapper.h"
+
+ int chdir(__const char *name)
+{
+ return smbw_chdir(name);
+}
+
diff --git a/source3/smbwrapper/close.c b/source3/smbwrapper/close.c
new file mode 100644
index 0000000000..a0491fca56
--- /dev/null
+++ b/source3/smbwrapper/close.c
@@ -0,0 +1,35 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+ SMB wrapper functions
+ Copyright (C) Andrew Tridgell 1998
+
+ 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 "wrapper.h"
+
+#ifdef linux
+__asm__(".globl __close; __close = close");
+#endif
+
+ ssize_t close(int fd)
+{
+ if (smbw_fd(fd)) {
+ return smbw_close(fd);
+ }
+
+ return real_close(fd);
+}
diff --git a/source3/smbwrapper/fcntl.c b/source3/smbwrapper/fcntl.c
new file mode 100644
index 0000000000..fab18fbdf4
--- /dev/null
+++ b/source3/smbwrapper/fcntl.c
@@ -0,0 +1,35 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+ SMB wrapper functions
+ Copyright (C) Andrew Tridgell 1998
+
+ 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 "wrapper.h"
+
+#ifdef linux
+__asm__(".globl __fcntl; __fcntl = fcntl");
+#endif
+
+ int fcntl(int fd, int cmd, long arg)
+{
+ if (smbw_fd(fd)) {
+ return smbw_fcntl(fd);
+ }
+
+ return real_fcntl(fd, cmd, arg);
+}
diff --git a/source3/smbwrapper/fstat.c b/source3/smbwrapper/fstat.c
new file mode 100644
index 0000000000..dc83f4a3ca
--- /dev/null
+++ b/source3/smbwrapper/fstat.c
@@ -0,0 +1,84 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+ SMB wrapper functions
+ Copyright (C) Andrew Tridgell 1998
+
+ 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 "wrapper.h"
+
+ int __fxstat(int vers, int fd, struct stat *st)
+{
+ struct kernel_stat kbuf;
+ int ret;
+
+ if (smbw_fd(fd)) {
+ return smbw_fstat(fd, st);
+ }
+
+ switch (vers) {
+ case _STAT_VER_LINUX_OLD:
+ /* Nothing to do. The struct is in the form the kernel expects
+ it to be. */
+ return real_fstat(fd, (struct kernel_stat *)st);
+ break;
+
+ case _STAT_VER_LINUX:
+ /* Do the system call. */
+ ret = real_fstat(fd, &kbuf);
+
+ st->st_dev = kbuf.st_dev;
+#ifdef _HAVE___PAD1
+ st->__pad1 = 0;
+#endif
+ st->st_ino = kbuf.st_ino;
+ st->st_mode = kbuf.st_mode;
+ st->st_nlink = kbuf.st_nlink;
+ st->st_uid = kbuf.st_uid;
+ st->st_gid = kbuf.st_gid;
+ st->st_rdev = kbuf.st_rdev;
+#ifdef _HAVE___PAD2
+ st->__pad2 = 0;
+#endif
+ st->st_size = kbuf.st_size;
+ st->st_blksize = kbuf.st_blksize;
+ st->st_blocks = kbuf.st_blocks;
+ st->st_atime = kbuf.st_atime;
+#ifdef _HAVE___UNUSED1
+ st->__unused1 = 0;
+#endif
+ st->st_mtime = kbuf.st_mtime;
+#ifdef _HAVE___UNUSED2
+ st->__unused2 = 0;
+#endif
+ st->st_ctime = kbuf.st_ctime;
+#ifdef _HAVE___UNUSED3
+ st->__unused3 = 0;
+#endif
+#ifdef _HAVE___UNUSED4
+ st->__unused4 = 0;
+#endif
+#ifdef _HAVE___UNUSED5
+ st->__unused5 = 0;
+#endif
+ return ret;
+
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}
diff --git a/source3/smbwrapper/getdents.c b/source3/smbwrapper/getdents.c
new file mode 100644
index 0000000000..1ff1b6376a
--- /dev/null
+++ b/source3/smbwrapper/getdents.c
@@ -0,0 +1,36 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+ SMB wrapper functions
+ Copyright (C) Andrew Tridgell 1998
+
+ 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 "wrapper.h"
+
+#ifdef linux
+__asm__(".globl __getdents; __getdents = getdents");
+#endif
+
+ int getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
+{
+ if (smbw_fd(fd)) {
+ return smbw_getdents(fd, dirp, count);
+ }
+
+ return real_getdents(fd, dirp, count);
+}
diff --git a/source3/smbwrapper/init.c b/source3/smbwrapper/init.c
new file mode 100644
index 0000000000..23d85eb4cf
--- /dev/null
+++ b/source3/smbwrapper/init.c
@@ -0,0 +1,22 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+ initialise connections in smbwrapper
+ Copyright (C) Andrew Tridgell 1998
+
+ 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 "includes.h"
diff --git a/source3/smbwrapper/kernel_stat.h b/source3/smbwrapper/kernel_stat.h
new file mode 100644
index 0000000000..bd7ddcc9bc
--- /dev/null
+++ b/source3/smbwrapper/kernel_stat.h
@@ -0,0 +1,31 @@
+/* Definition of `struct stat' used in the kernel.. */
+struct kernel_stat
+ {
+ unsigned short int st_dev;
+ unsigned short int __pad1;
+#define _HAVE___PAD1
+ unsigned long int st_ino;
+ unsigned short int st_mode;
+ unsigned short int st_nlink;
+ unsigned short int st_uid;
+ unsigned short int st_gid;
+ unsigned short int st_rdev;
+ unsigned short int __pad2;
+#define _HAVE___PAD2
+ unsigned long int st_size;
+ unsigned long int st_blksize;
+ unsigned long int st_blocks;
+ unsigned long int st_atime;
+ unsigned long int __unused1;
+#define _HAVE___UNUSED1
+ unsigned long int st_mtime;
+ unsigned long int __unused2;
+#define _HAVE___UNUSED2
+ unsigned long int st_ctime;
+ unsigned long int __unused3;
+#define _HAVE___UNUSED3
+ unsigned long int __unused4;
+#define _HAVE___UNUSED4
+ unsigned long int __unused5;
+#define _HAVE___UNUSED5
+ };
diff --git a/source3/smbwrapper/lstat.c b/source3/smbwrapper/lstat.c
new file mode 100644
index 0000000000..f6298f6e0b
--- /dev/null
+++ b/source3/smbwrapper/lstat.c
@@ -0,0 +1,85 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+ SMB wrapper functions
+ Copyright (C) Andrew Tridgell 1998
+
+ 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 "wrapper.h"
+
+ int __lxstat(int vers, __const char *name, struct stat *st)
+{
+ struct kernel_stat kbuf;
+ int ret;
+
+ if (smbw_path(name)) {
+ return smbw_stat(name, st);
+ }
+
+ switch (vers) {
+ case _STAT_VER_LINUX_OLD:
+ /* Nothing to do. The struct is in the form the kernel expects
+ it to be. */
+ return real_lstat(name, (struct kernel_stat *)st);
+ break;
+
+ case _STAT_VER_LINUX:
+ /* Do the system call. */
+ ret = real_lstat(name, &kbuf);
+
+ st->st_dev = kbuf.st_dev;
+#ifdef _HAVE___PAD1
+ st->__pad1 = 0;
+#endif
+ st->st_ino = kbuf.st_ino;
+ st->st_mode = kbuf.st_mode;
+ st->st_nlink = kbuf.st_nlink;
+ st->st_uid = kbuf.st_uid;
+ st->st_gid = kbuf.st_gid;
+ st->st_rdev = kbuf.st_rdev;
+#ifdef _HAVE___PAD2
+ st->__pad2 = 0;
+#endif
+ st->st_size = kbuf.st_size;
+ st->st_blksize = kbuf.st_blksize;
+ st->st_blocks = kbuf.st_blocks;
+ st->st_atime = kbuf.st_atime;
+#ifdef _HAVE___UNUSED1
+ st->__unused1 = 0;
+#endif
+ st->st_mtime = kbuf.st_mtime;
+#ifdef _HAVE___UNUSED2
+ st->__unused2 = 0;
+#endif
+ st->st_ctime = kbuf.st_ctime;
+#ifdef _HAVE___UNUSED3
+ st->__unused3 = 0;
+#endif
+#ifdef _HAVE___UNUSED4
+ st->__unused4 = 0;
+#endif
+#ifdef _HAVE___UNUSED5
+ st->__unused5 = 0;
+#endif
+ return ret;
+
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}
+
diff --git a/source3/smbwrapper/open.c b/source3/smbwrapper/open.c
new file mode 100644
index 0000000000..8a088eeb19
--- /dev/null
+++ b/source3/smbwrapper/open.c
@@ -0,0 +1,36 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+ SMB wrapper functions
+ Copyright (C) Andrew Tridgell 1998
+
+ 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 "wrapper.h"
+
+#ifdef linux
+__asm__(".globl __open; __open = open");
+#endif
+
+ int open(__const char *name, int flags, mode_t mode)
+{
+ if (smbw_path(name)) {
+ return smbw_open(name, flags, mode);
+ }
+
+ return real_open(name, flags, mode);
+}
diff --git a/source3/smbwrapper/read.c b/source3/smbwrapper/read.c
new file mode 100644
index 0000000000..3ca49a6309
--- /dev/null
+++ b/source3/smbwrapper/read.c
@@ -0,0 +1,35 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+ SMB wrapper functions
+ Copyright (C) Andrew Tridgell 1998
+
+ 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 "wrapper.h"
+
+#ifdef linux
+__asm__(".globl __read; __read = read");
+#endif
+
+ ssize_t read(int fd, void *buf, size_t count)
+{
+ if (smbw_fd(fd)) {
+ return smbw_read(fd, buf, count);
+ }
+
+ return real_read(fd, buf, count);
+}
diff --git a/source3/smbwrapper/realcalls.h b/source3/smbwrapper/realcalls.h
new file mode 100644
index 0000000000..de9945f733
--- /dev/null
+++ b/source3/smbwrapper/realcalls.h
@@ -0,0 +1,44 @@
+#ifdef aix
+
+#include "aix-syscall.h"
+
+#else
+
+#define real_access(fn, mode) (syscall(SYS_access, (fn), (mode)))
+#define real_chdir(fn) (syscall(SYS_chdir, (fn)))
+#define real_chmod(fn, mode) (syscall(SYS_chmod,(fn), (mode)))
+#define real_chown(fn, owner, group) (syscall(SYS_chown,(fn),(owner),(group)))
+
+#define real_getdents(fd, dirp, count) (syscall(SYS_getdents, (fd), (dirp), (count)))
+/* if needed define SYS_getdents so that getdents gets compiled */
+
+#define real_link(fn1, fn2) (syscall(SYS_link, (fn1), (fn2)))
+
+#define real_lstat(fn, buf ) (syscall(SYS_lstat, (fn), (buf)))
+#define real_open(fn,flags,mode) (syscall(SYS_open, (fn), (flags), (mode)))
+#define real_prev_lstat(fn, buf ) (syscall(SYS_prev_lstat, (fn), (buf)))
+#define real_prev_stat(fn, buf ) (syscall(SYS_prev_stat, (fn), (buf)))
+
+#ifdef linux
+struct dirent *__libc_readdir(DIR * dir);
+#define real_readdir(dir) (__libc_readdir(dirp))
+#else
+#define real_readdir(dirp) ((struct dirent *)syscall(SYS_readdir,(dirp)))
+/* if needed define SYS_readdir so that readdir gets compiled */
+#endif
+
+#define real_readlink(fn,buf,len) (syscall(SYS_readlink, (fn), (buf), (len)))
+#define real_rename(fn1, fn2) (syscall(SYS_rename, (fn1), (fn2)))
+#define real_stat(fn, buf ) (syscall(SYS_stat, (fn), (buf)))
+#define real_fstat(fd, buf ) (syscall(SYS_fstat, (fd), (buf)))
+#define real_read(fd, buf, count ) (syscall(SYS_read, (fd), (buf), (count)))
+#define real_write(fd, buf, count ) (syscall(SYS_write, (fd), (buf), (count)))
+#define real_close(fd) (syscall(SYS_close, (fd)))
+#define real_fcntl(fd,cmd,arg) (syscall(SYS_fcntl, (fd), (cmd), (arg)))
+#define real_symlink(fn1, fn2) (syscall(SYS_symlink, (fn1), (fn2)))
+#define real_unlink(fn) (syscall(SYS_unlink, (fn)))
+#define real_utime(fn, buf) (syscall(SYS_utime, (fn), (buf)))
+#define real_utimes(fn, buf) (syscall(SYS_utimes, (fn), (buf)))
+
+#endif
+
diff --git a/source3/smbwrapper/smbsh b/source3/smbwrapper/smbsh
new file mode 100755
index 0000000000..f2cceb1ccb
--- /dev/null
+++ b/source3/smbwrapper/smbsh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# a simple launcher for the smbwrapper.so preloadde library
+
+export LD_PRELOAD=$PWD/smbwrapper/smbwrapper.so
+bash
diff --git a/source3/smbwrapper/smbw.c b/source3/smbwrapper/smbw.c
new file mode 100644
index 0000000000..c0c3ac86af
--- /dev/null
+++ b/source3/smbwrapper/smbw.c
@@ -0,0 +1,1005 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+ SMB wrapper functions
+ Copyright (C) Andrew Tridgell 1998
+
+ 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 "includes.h"
+#include "smbw.h"
+#include "wrapper.h"
+
+static pstring smb_cwd;
+
+struct smbw_server {
+ struct smbw_server *next, *prev;
+ struct cli_state cli;
+ char *server_name;
+ char *share_name;
+};
+
+struct smbw_file {
+ struct smbw_file *next, *prev;
+ int cli_fd, fd;
+ char *fname;
+ off_t offset;
+ struct smbw_server *srv;
+};
+
+struct smbw_dir {
+ struct smbw_dir *next, *prev;
+ int fd;
+ int offset, count, malloced;
+ struct smbw_server *srv;
+ struct file_info *list;
+};
+
+static struct smbw_file *smbw_files;
+static struct smbw_dir *smbw_dirs;
+static struct smbw_server *smbw_srvs;
+
+static struct bitmap *file_bmap;
+static pstring local_machine;
+extern int DEBUGLEVEL;
+
+/*****************************************************
+initialise structures
+*******************************************************/
+void smbw_init(void)
+{
+ extern BOOL in_client;
+ static int initialised;
+ static pstring servicesf = CONFIGFILE;
+ extern FILE *dbf;
+ char *p;
+
+ if (initialised) return;
+ initialised = 1;
+
+ DEBUGLEVEL = 0;
+ setup_logging("smbw",True);
+
+ dbf = stderr;
+
+ file_bmap = bitmap_allocate(SMBW_MAX_OPEN);
+ if (!file_bmap) {
+ exit(1);
+ }
+
+ charset_initialise();
+
+ in_client = True;
+
+ if (!lp_load(servicesf,True,False,False)) {
+ exit(1);
+ }
+
+ get_myname(local_machine,NULL);
+
+ if ((p=getenv("SMBW_DEBUG"))) {
+ DEBUGLEVEL = atoi(p);
+ }
+
+ if ((p=getenv("SMBW_CWD"))) {
+ pstrcpy(smb_cwd, p);
+ } else {
+ sys_getwd(smb_cwd);
+ }
+}
+
+/*****************************************************
+determine if a file descriptor is a smb one
+*******************************************************/
+BOOL smbw_fd(int fd)
+{
+ return (fd >= SMBW_FD_OFFSET);
+}
+
+
+/*****************************************************
+remove redundent stuff from a filename
+*******************************************************/
+void clean_fname(char *name)
+{
+ char *p, *p2;
+ int l;
+ int modified = 1;
+
+ if (!name) return;
+
+ while (modified) {
+ modified = 0;
+
+ DEBUG(4,("cleaning %s\n", name));
+
+ if ((p=strstr(name,"/./"))) {
+ modified = 1;
+ while (*p) {
+ p[0] = p[2];
+ p++;
+ }
+ }
+
+ if ((p=strstr(name,"//"))) {
+ modified = 1;
+ while (*p) {
+ p[0] = p[1];
+ p++;
+ }
+ }
+
+ if (strcmp(name,"/../")==0) {
+ modified = 1;
+ name[1] = 0;
+ }
+
+ if ((p=strstr(name,"/../"))) {
+ modified = 1;
+ for (p2=(p>name?p-1:p);p2>name;p2--) {
+ if (p2[0] == '/') break;
+ }
+ while (*p2) {
+ p2[0] = p2[3];
+ p2++;
+ }
+ }
+
+ if (strcmp(name,"/..")==0) {
+ modified = 1;
+ name[1] = 0;
+ }
+
+ 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;
+ }
+ }
+
+ l = strlen(name);
+ p = l>=2?(name+l-2):name;
+ if (strcmp(p,"/.")==0) {
+ if (p == name) {
+ p[1] = 0;
+ } else {
+ p[0] = 0;
+ }
+ }
+
+ if (strncmp(p=name,"./",2) == 0) {
+ modified = 1;
+ do {
+ p[0] = p[2];
+ } while (*p++);
+ }
+
+ l = strlen(p=name);
+ if (l > 1 && p[l-1] == '/') {
+ modified = 1;
+ p[l-1] = 0;
+ }
+ }
+}
+
+
+/*****************************************************
+parse a smb path into its components.
+*******************************************************/
+char *smbw_parse_path(char *fname, char **server, char **share, char **path)
+{
+ static fstring rshare, rserver;
+ static pstring rpath, s;
+ char *p, *p2;
+ int len;
+
+ (*server) = rserver;
+ (*share) = rshare;
+ (*path) = rpath;
+
+ if (fname[0] == '/') {
+ pstrcpy(s, fname);
+ } else {
+ slprintf(s,sizeof(s)-1, "%s/%s", smb_cwd, fname);
+ }
+ clean_fname(s);
+
+ DEBUG(4,("cleaned %s (fname=%s cwd=%s)\n",
+ s, fname, smb_cwd));
+
+ if (strncmp(s,SMBW_PREFIX,strlen(SMBW_PREFIX))) return s;
+
+ p = s + strlen(SMBW_PREFIX);
+ p2 = strchr(p,'/');
+
+ if (p2) {
+ len = (int)(p2-p);
+ } else {
+ len = strlen(p);
+ }
+
+ strncpy(rserver, p, len);
+ rserver[len] = 0;
+
+ p = p2;
+ if (!p) {
+ fstrcpy(rshare,"IPC$");
+ fstrcpy(rpath,"");
+ goto ok;
+ }
+
+ p++;
+ p2 = strchr(p,'/');
+
+ if (p2) {
+ len = (int)(p2-p);
+ } else {
+ len = strlen(p);
+ }
+
+ fstrcpy(rshare, p);
+ rshare[len] = 0;
+
+ p = p2;
+ if (!p) {
+ pstrcpy(rpath,"\\");
+ goto ok;
+ }
+
+ pstrcpy(rpath,p);
+
+ string_sub(rpath, "/", "\\");
+
+ ok:
+ DEBUG(4,("parsed path name=%s cwd=%s [%s] [%s] [%s]\n",
+ fname, smb_cwd,
+ *server, *share, *path));
+
+ return s;
+}
+
+/*****************************************************
+determine if a path name (possibly relative) is in the
+smb name space
+*******************************************************/
+BOOL smbw_path(char *path)
+{
+ char *server, *share, *s;
+ char *cwd;
+ cwd = smbw_parse_path(path, &server, &share, &s);
+ return strncmp(cwd,SMBW_PREFIX,strlen(SMBW_PREFIX)) == 0;
+}
+
+/*****************************************************
+return a unix errno from a SMB error pair
+*******************************************************/
+int smbw_errno(struct smbw_server *srv)
+{
+ int eclass=0, ecode=0;
+ cli_error(&srv->cli, &eclass, &ecode);
+ DEBUG(2,("eclass=%d ecode=%d\n", eclass, ecode));
+ if (eclass == ERRDOS) {
+ switch (ecode) {
+ case ERRbadfile: return ENOENT;
+ case ERRnoaccess: return EPERM;
+ }
+ }
+ return EINVAL;
+}
+
+/*****************************************************
+return a connection to a server (existing or new)
+*******************************************************/
+struct smbw_server *smbw_server(char *server, char *share)
+{
+ struct smbw_server *srv=NULL;
+ static struct cli_state c;
+ char *username;
+ char *password;
+ char *workgroup;
+ struct nmb_name called, calling;
+
+ username = getenv("SMBW_USER");
+ if (!username) username = getenv("USER");
+ if (!username) username = "guest";
+
+ workgroup = getenv("SMBW_WORKGROUP");
+ if (!workgroup) workgroup = lp_workgroup();
+
+ password = getenv("SMBW_PASSWORD");
+ if (!password) password = "";
+
+ /* try to use an existing connection */
+ for (srv=smbw_srvs;srv;srv=srv->next) {
+ if (strcmp(server,srv->server_name)==0 &&
+ strcmp(share,srv->share_name)==0) return srv;
+ }
+
+ /* have to open a new connection */
+ if (!cli_initialise(&c) || !cli_connect(&c, server, NULL)) {
+ errno = ENOENT;
+ return NULL;
+ }
+
+ make_nmb_name(&calling, local_machine, 0x0, "");
+ make_nmb_name(&called , server, 0x20, "");
+
+ if (!cli_session_request(&c, &calling, &called)) {
+ cli_shutdown(&c);
+ errno = ENOENT;
+ return NULL;
+ }
+
+ if (!cli_negprot(&c)) {
+ cli_shutdown(&c);
+ errno = ENOENT;
+ return NULL;
+ }
+
+ if (!cli_session_setup(&c, username,
+ password, strlen(password),
+ password, strlen(password),
+ workgroup)) {
+ cli_shutdown(&c);
+ errno = EPERM;
+ return NULL;
+ }
+
+ if (!cli_send_tconX(&c, share,
+ strstr(share,"IPC$")?"IPC":"A:",
+ password, strlen(password)+1)) {
+ cli_shutdown(&c);
+ errno = ENOENT;
+ return NULL;
+ }
+
+ srv = (struct smbw_server *)malloc(sizeof(*srv));
+ if (!srv) {
+ errno = ENOMEM;
+ goto failed;
+ }
+
+ ZERO_STRUCTP(srv);
+
+ srv->cli = c;
+
+ srv->server_name = strdup(server);
+ if (!srv->server_name) {
+ errno = ENOMEM;
+ goto failed;
+ }
+
+ srv->share_name = strdup(share);
+ if (!srv->share_name) {
+ errno = ENOMEM;
+ goto failed;
+ }
+
+ DLIST_ADD(smbw_srvs, srv);
+
+ return srv;
+
+ failed:
+ cli_shutdown(&c);
+ if (!srv) return NULL;
+
+ if (srv->server_name) free(srv->server_name);
+ if (srv->share_name) free(srv->share_name);
+ free(srv);
+ return NULL;
+}
+
+
+/*****************************************************
+map a fd to a smbw_file structure
+*******************************************************/
+struct smbw_file *smbw_file(int fd)
+{
+ struct smbw_file *file;
+
+ for (file=smbw_files;file;file=file->next) {
+ if (file->fd == fd) return file;
+ }
+ return NULL;
+}
+
+/*****************************************************
+map a fd to a smbw_dir structure
+*******************************************************/
+struct smbw_dir *smbw_dir(int fd)
+{
+ struct smbw_dir *dir;
+
+ for (dir=smbw_dirs;dir;dir=dir->next) {
+ if (dir->fd == fd) return dir;
+ }
+ return NULL;
+}
+
+/*****************************************************
+setup basic info in a stat structure
+*******************************************************/
+void smbw_setup_stat(struct stat *st, char *fname, size_t size, int mode)
+{
+ ZERO_STRUCTP(st);
+
+ if (IS_DOS_DIR(mode)) {
+ st->st_mode = SMBW_DIR_MODE;
+ } else {
+ st->st_mode = SMBW_FILE_MODE;
+ }
+
+ st->st_size = size;
+ st->st_blksize = 512;
+ st->st_blocks = (size+511)/512;
+ st->st_uid = getuid();
+ st->st_gid = getgid();
+}
+
+/*****************************************************
+free a smbw_dir structure and all entries
+*******************************************************/
+static void free_dir(struct smbw_dir *dir)
+{
+ if (dir->list) {
+ free(dir->list);
+ }
+ ZERO_STRUCTP(dir);
+ free(dir);
+}
+
+
+static struct smbw_dir *cur_dir;
+
+/*****************************************************
+add a entry to a directory listing
+*******************************************************/
+void smbw_dir_add(struct file_info *finfo)
+{
+ DEBUG(2,("%s\n", finfo->name));
+
+ if (cur_dir->malloced == cur_dir->count) {
+ cur_dir->list = (struct file_info *)Realloc(cur_dir->list,
+ sizeof(cur_dir->list[0])*
+ (cur_dir->count+100));
+ if (!cur_dir->list) {
+ /* oops */
+ return;
+ }
+ cur_dir->malloced += 100;
+ }
+
+ cur_dir->list[cur_dir->count] = *finfo;
+ cur_dir->count++;
+}
+
+/*****************************************************
+open a directory on the server
+*******************************************************/
+int smbw_dir_open(const char *fname1, int flags)
+{
+ char *fname = strdup(fname1);
+ char *server, *share, *path;
+ struct smbw_server *srv=NULL;
+ struct smbw_dir *dir=NULL;
+ pstring mask;
+ int fd;
+
+ DEBUG(4,("%s\n", __FUNCTION__));
+
+ if (!fname) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ smbw_init();
+
+ /* work out what server they are after */
+ smbw_parse_path(fname, &server, &share, &path);
+
+ /* get a connection to the server */
+ srv = smbw_server(server, share);
+ if (!srv) {
+ /* smbw_server sets errno */
+ goto failed;
+ }
+
+ dir = (struct smbw_dir *)malloc(sizeof(*dir));
+ if (!dir) {
+ errno = ENOMEM;
+ goto failed;
+ }
+
+ ZERO_STRUCTP(dir);
+
+ cur_dir = dir;
+
+ slprintf(mask, sizeof(mask)-1, "%s\\*", path);
+ string_sub(mask,"\\\\","\\");
+
+ if (cli_list(&srv->cli, mask, aHIDDEN|aSYSTEM|aDIR, smbw_dir_add) <= 0) {
+ errno = smbw_errno(srv);
+ goto failed;
+ }
+
+ cur_dir = NULL;
+
+ fd = bitmap_find(file_bmap, 0);
+ if (fd == -1) {
+ errno = EMFILE;
+ goto failed;
+ }
+
+ DLIST_ADD(smbw_dirs, dir);
+
+ bitmap_set(file_bmap, fd);
+
+ dir->fd = fd + SMBW_FD_OFFSET;
+
+ return dir->fd;
+
+ failed:
+ if (dir) {
+ free_dir(dir);
+ }
+ if (fname) free(fname);
+
+ return -1;
+}
+
+
+/*****************************************************
+a wrapper for open()
+*******************************************************/
+int smbw_open(const char *fname1, int flags, mode_t mode)
+{
+ char *fname = strdup(fname1);
+ char *server, *share, *path;
+ struct smbw_server *srv=NULL;
+ int eno, fd = -1;
+ struct smbw_file *file=NULL;
+
+ DEBUG(4,("%s\n", __FUNCTION__));
+
+ if (!fname) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ smbw_init();
+
+ /* work out what server they are after */
+ smbw_parse_path(fname, &server, &share, &path);
+
+ /* get a connection to the server */
+ srv = smbw_server(server, share);
+ if (!srv) {
+ /* smbw_server sets errno */
+ goto failed;
+ }
+
+ fd = cli_open(&srv->cli, path, flags, DENY_NONE);
+ if (fd == -1) {
+ if (fname) free(fname);
+ /* it might be a directory. Maybe we should use chkpath? */
+ return smbw_dir_open(fname1, flags);
+ }
+ if (fd == -1) {
+ errno = eno;
+ goto failed;
+ }
+
+ file = (struct smbw_file *)malloc(sizeof(*file));
+ if (!file) {
+ errno = ENOMEM;
+ goto failed;
+ }
+
+ ZERO_STRUCTP(file);
+
+ file->cli_fd = fd;
+ file->fname = strdup(path);
+ if (!file->fname) {
+ errno = ENOMEM;
+ goto failed;
+ }
+ file->srv = srv;
+ file->fd = bitmap_find(file_bmap, 0);
+
+ if (file->fd == -1) {
+ errno = EMFILE;
+ goto failed;
+ }
+
+ bitmap_set(file_bmap, file->fd);
+
+ file->fd += SMBW_FD_OFFSET;
+
+ DLIST_ADD(smbw_files, file);
+
+ DEBUG(2,("opened %s\n", fname1));
+
+ free(fname);
+
+ return file->fd;
+
+ failed:
+ if (fname) {
+ free(fname);
+ }
+ if (fd != -1) {
+ cli_close(&srv->cli, fd);
+ }
+ if (file) {
+ if (file->fname) {
+ free(file->fname);
+ }
+ free(file);
+ }
+ return -1;
+}
+
+
+/*****************************************************
+a wrapper for fstat() on a directory
+*******************************************************/
+int smbw_dir_fstat(int fd, struct stat *st)
+{
+ struct smbw_dir *dir;
+
+ DEBUG(4,("%s\n", __FUNCTION__));
+
+ dir = smbw_dir(fd);
+ if (!dir) {
+ errno = EBADF;
+ return -1;
+ }
+
+ ZERO_STRUCTP(st);
+
+ smbw_setup_stat(st, "", dir->count*sizeof(struct dirent), aDIR);
+
+ return 0;
+}
+
+/*****************************************************
+a wrapper for fstat()
+*******************************************************/
+int smbw_fstat(int fd, struct stat *st)
+{
+ struct smbw_file *file;
+ time_t c_time, a_time, m_time;
+ uint32 size;
+ int mode;
+
+ DEBUG(4,("%s\n", __FUNCTION__));
+
+ file = smbw_file(fd);
+ if (!file) {
+ return smbw_dir_fstat(fd, st);
+ }
+
+ DEBUG(4,("%s - qfileinfo\n", __FUNCTION__));
+
+ if (!cli_qfileinfo(&file->srv->cli, file->cli_fd,
+ &c_time, &a_time, &m_time, &size, &mode)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ smbw_setup_stat(st, file->fname, size, mode);
+
+ st->st_atime = a_time;
+ st->st_ctime = c_time;
+ st->st_mtime = m_time;
+
+ DEBUG(4,("%s - OK\n", __FUNCTION__));
+
+ return 0;
+}
+
+/*****************************************************
+a wrapper for stat()
+*******************************************************/
+int smbw_stat(char *fname1, struct stat *st)
+{
+ struct smbw_server *srv;
+ char *server, *share, *path;
+ char *fname = strdup(fname1);
+ time_t c_time, a_time, m_time;
+ uint32 size;
+ int mode;
+
+ DEBUG(4,("%s (%s)\n", __FUNCTION__, fname1));
+
+ if (!fname) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ smbw_init();
+
+ /* work out what server they are after */
+ smbw_parse_path(fname, &server, &share, &path);
+
+ /* get a connection to the server */
+ srv = smbw_server(server, share);
+ if (!srv) {
+ /* smbw_server sets errno */
+ goto failed;
+ }
+
+ if (!cli_qpathinfo(&srv->cli, path,
+ &c_time, &a_time, &m_time, &size, &mode)) {
+ errno = smbw_errno(srv);
+ goto failed;
+ }
+
+ smbw_setup_stat(st, path, size, mode);
+
+ st->st_atime = a_time;
+ st->st_ctime = c_time;
+ st->st_mtime = m_time;
+
+ return 0;
+
+ failed:
+ if (fname) free(fname);
+ return -1;
+}
+
+/*****************************************************
+a wrapper for read()
+*******************************************************/
+ssize_t smbw_read(int fd, void *buf, size_t count)
+{
+ struct smbw_file *file;
+ int ret;
+
+ DEBUG(4,("%s\n", __FUNCTION__));
+
+ file = smbw_file(fd);
+ if (!file) {
+ DEBUG(3,("bad fd in read\n"));
+ errno = EBADF;
+ return -1;
+ }
+
+ ret = cli_read(&file->srv->cli, file->cli_fd, buf, file->offset, count);
+
+ if (ret == -1) {
+ errno = smbw_errno(file->srv);
+ return -1;
+ }
+
+ file->offset += ret;
+
+ return ret;
+}
+
+/*****************************************************
+a wrapper for write()
+*******************************************************/
+ssize_t smbw_write(int fd, void *buf, size_t count)
+{
+ struct smbw_file *file;
+ int ret;
+
+ DEBUG(4,("%s\n", __FUNCTION__));
+
+ file = smbw_file(fd);
+ if (!file) {
+ DEBUG(3,("bad fd in read\n"));
+ errno = EBADF;
+ return -1;
+ }
+
+ ret = cli_write(&file->srv->cli, file->cli_fd, buf, file->offset, count);
+
+ if (ret == -1) {
+ errno = smbw_errno(file->srv);
+ return -1;
+ }
+
+ file->offset += ret;
+
+ return ret;
+}
+
+/*****************************************************
+close a directory handle
+*******************************************************/
+int smbw_dir_close(int fd)
+{
+ struct smbw_dir *dir;
+
+ DEBUG(4,("%s\n", __FUNCTION__));
+
+ dir = smbw_dir(fd);
+ if (!dir) {
+ DEBUG(4,("%s(%d)\n", __FUNCTION__, __LINE__));
+ errno = EBADF;
+ return -1;
+ }
+
+ bitmap_clear(file_bmap, dir->fd - SMBW_FD_OFFSET);
+
+ DLIST_REMOVE(smbw_dirs, dir);
+
+ free_dir(dir);
+
+ return 0;
+}
+
+/*****************************************************
+a wrapper for close()
+*******************************************************/
+int smbw_close(int fd)
+{
+ struct smbw_file *file;
+
+ DEBUG(4,("%s\n", __FUNCTION__));
+
+ file = smbw_file(fd);
+ if (!file) {
+ return smbw_dir_close(fd);
+ }
+
+ if (!cli_close(&file->srv->cli, file->cli_fd)) {
+ errno = smbw_errno(file->srv);
+ return -1;
+ }
+
+
+ bitmap_clear(file_bmap, file->fd - SMBW_FD_OFFSET);
+
+ DLIST_REMOVE(smbw_files, file);
+
+ free(file->fname);
+ ZERO_STRUCTP(file);
+ free(file);
+
+ return 0;
+}
+
+
+/*****************************************************
+a wrapper for fcntl()
+*******************************************************/
+int smbw_fcntl(int fd, int cmd, long arg)
+{
+ DEBUG(4,("%s\n", __FUNCTION__));
+ return 0;
+}
+
+
+/*****************************************************
+a wrapper for getdents()
+*******************************************************/
+int smbw_getdents(unsigned int fd, struct dirent *dirp, int count)
+{
+ struct smbw_dir *dir;
+ int n=0;
+
+ DEBUG(4,("%s\n", __FUNCTION__));
+
+ dir = smbw_dir(fd);
+ if (!dir) {
+ errno = EBADF;
+ return -1;
+ }
+
+ while (count>=sizeof(*dirp) && (dir->offset < dir->count)) {
+ dirp->d_ino = dir->offset + 0x10000;
+ dirp->d_off = (dir->offset+1)*sizeof(*dirp);
+ dirp->d_reclen = sizeof(*dirp);
+ /* what's going on with the -1 here? maybe d_type isn't really there? */
+ safe_strcpy(&dirp->d_name[-1], dir->list[dir->offset].name,
+ sizeof(dirp->d_name)-1);
+ dir->offset++;
+ count -= dirp->d_reclen;
+ dirp++;
+ n++;
+ }
+
+ return n*sizeof(*dirp);
+}
+
+
+/*****************************************************
+a wrapper for access()
+*******************************************************/
+int smbw_access(char *name, int mode)
+{
+ struct stat st;
+ /* how do we map this properly ?? */
+ return smbw_stat(name, &st) == 0;
+}
+
+
+/*****************************************************
+a wrapper for chdir()
+*******************************************************/
+int smbw_chdir(char *name)
+{
+ struct smbw_server *srv;
+ char *server, *share, *path;
+ int mode = aDIR;
+ char *cwd;
+
+ DEBUG(4,("%s (%s)\n", __FUNCTION__, name));
+
+ if (!name) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ smbw_init();
+
+ DEBUG(2,("parsing\n"));
+
+ /* work out what server they are after */
+ cwd = smbw_parse_path(name, &server, &share, &path);
+
+ DEBUG(2,("parsed\n"));
+
+ if (strncmp(cwd,SMBW_PREFIX,strlen(SMBW_PREFIX))) {
+ if (real_chdir(cwd) == 0) {
+ pstrcpy(smb_cwd, cwd);
+ setenv("SMB_CWD", smb_cwd, 1);
+ return 0;
+ }
+ errno = ENOENT;
+ return -1;
+ }
+
+ DEBUG(2,("doing server\n"));
+
+ /* get a connection to the server */
+ srv = smbw_server(server, share);
+ if (!srv) {
+ /* smbw_server sets errno */
+ return -1;
+ }
+
+ DEBUG(2,("doing qpathinfo share=%s\n", share));
+
+ if (strcmp(share,"IPC$") &&
+ !cli_qpathinfo(&srv->cli, path,
+ NULL, NULL, NULL, NULL, &mode)) {
+ errno = smbw_errno(srv);
+ return -1;
+ }
+
+ if (!(mode & aDIR)) {
+ errno = ENOTDIR;
+ return -1;
+ }
+
+ pstrcpy(smb_cwd, cwd);
+ setenv("SMB_CWD", smb_cwd, 1);
+
+ return 0;
+}
+
diff --git a/source3/smbwrapper/smbw.h b/source3/smbwrapper/smbw.h
new file mode 100644
index 0000000000..c723b6989b
--- /dev/null
+++ b/source3/smbwrapper/smbw.h
@@ -0,0 +1,28 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+ SMB wrapper functions - definitions
+ Copyright (C) Andrew Tridgell 1998
+
+ 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.
+*/
+
+#define SMBW_PREFIX "/smb/"
+
+#define SMBW_FD_OFFSET 1024
+#define SMBW_MAX_OPEN 2048
+
+#define SMBW_FILE_MODE (S_IFREG | 0644)
+#define SMBW_DIR_MODE (S_IFDIR | 0755)
diff --git a/source3/smbwrapper/stat.c b/source3/smbwrapper/stat.c
new file mode 100644
index 0000000000..8980f75f97
--- /dev/null
+++ b/source3/smbwrapper/stat.c
@@ -0,0 +1,89 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+ SMB wrapper functions
+ Copyright (C) Andrew Tridgell 1998
+
+ 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 "wrapper.h"
+
+ int __xstat(int vers, __const char *name, struct stat *st)
+{
+ struct kernel_stat kbuf;
+ int ret;
+
+ if (smbw_path(name)) {
+ return smbw_stat(name, st);
+ }
+
+ switch (vers) {
+ case _STAT_VER_LINUX_OLD:
+ /* Nothing to do. The struct is in the form the kernel expects
+ it to be. */
+ return real_stat(name, (struct kernel_stat *)st);
+ break;
+
+ case _STAT_VER_LINUX:
+ /* Do the system call. */
+ ret = real_stat(name, &kbuf);
+
+ st->st_dev = kbuf.st_dev;
+#ifdef _HAVE___PAD1
+ st->__pad1 = 0;
+#endif
+ st->st_ino = kbuf.st_ino;
+ st->st_mode = kbuf.st_mode;
+ st->st_nlink = kbuf.st_nlink;
+ st->st_uid = kbuf.st_uid;
+ st->st_gid = kbuf.st_gid;
+ st->st_rdev = kbuf.st_rdev;
+#ifdef _HAVE___PAD2
+ st->__pad2 = 0;
+#endif
+ st->st_size = kbuf.st_size;
+ st->st_blksize = kbuf.st_blksize;
+ st->st_blocks = kbuf.st_blocks;
+ st->st_atime = kbuf.st_atime;
+#ifdef _HAVE___UNUSED1
+ st->__unused1 = 0;
+#endif
+ st->st_mtime = kbuf.st_mtime;
+#ifdef _HAVE___UNUSED2
+ st->__unused2 = 0;
+#endif
+ st->st_ctime = kbuf.st_ctime;
+#ifdef _HAVE___UNUSED3
+ st->__unused3 = 0;
+#endif
+#ifdef _HAVE___UNUSED4
+ st->__unused4 = 0;
+#endif
+#ifdef _HAVE___UNUSED5
+ st->__unused5 = 0;
+#endif
+ return ret;
+
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+ int stat(__const char *name, struct stat *st)
+{
+ return __xstat(_STAT_VER, name, st);
+}
diff --git a/source3/smbwrapper/wrapper.h b/source3/smbwrapper/wrapper.h
new file mode 100644
index 0000000000..84a947a8b8
--- /dev/null
+++ b/source3/smbwrapper/wrapper.h
@@ -0,0 +1,8 @@
+#include <syscall.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "kernel_stat.h"
+#include "realcalls.h"
diff --git a/source3/smbwrapper/write.c b/source3/smbwrapper/write.c
new file mode 100644
index 0000000000..a05f55d9a4
--- /dev/null
+++ b/source3/smbwrapper/write.c
@@ -0,0 +1,35 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 2.0
+ SMB wrapper functions
+ Copyright (C) Andrew Tridgell 1998
+
+ 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 "wrapper.h"
+
+#ifdef linux
+__asm__(".globl __write; __write = write");
+#endif
+
+ ssize_t write(int fd, void *buf, size_t count)
+{
+ if (smbw_fd(fd)) {
+ return smbw_write(fd, buf, count);
+ }
+
+ return real_write(fd, buf, count);
+}