the guts of the smbwrapper code. I may change the layout of this at
authorAndrew Tridgell <tridge@samba.org>
Fri, 2 Oct 1998 12:37:31 +0000 (12:37 +0000)
committerAndrew Tridgell <tridge@samba.org>
Fri, 2 Oct 1998 12:37:31 +0000 (12:37 +0000)
some stage.

19 files changed:
source/smbwrapper/README [new file with mode: 0644]
source/smbwrapper/access.c [new file with mode: 0644]
source/smbwrapper/chdir.c [new file with mode: 0644]
source/smbwrapper/close.c [new file with mode: 0644]
source/smbwrapper/fcntl.c [new file with mode: 0644]
source/smbwrapper/fstat.c [new file with mode: 0644]
source/smbwrapper/getdents.c [new file with mode: 0644]
source/smbwrapper/init.c [new file with mode: 0644]
source/smbwrapper/kernel_stat.h [new file with mode: 0644]
source/smbwrapper/lstat.c [new file with mode: 0644]
source/smbwrapper/open.c [new file with mode: 0644]
source/smbwrapper/read.c [new file with mode: 0644]
source/smbwrapper/realcalls.h [new file with mode: 0644]
source/smbwrapper/smbsh [new file with mode: 0755]
source/smbwrapper/smbw.c [new file with mode: 0644]
source/smbwrapper/smbw.h [new file with mode: 0644]
source/smbwrapper/stat.c [new file with mode: 0644]
source/smbwrapper/wrapper.h [new file with mode: 0644]
source/smbwrapper/write.c [new file with mode: 0644]

diff --git a/source/smbwrapper/README b/source/smbwrapper/README
new file mode 100644 (file)
index 0000000..be345b5
--- /dev/null
@@ -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/source/smbwrapper/access.c b/source/smbwrapper/access.c
new file mode 100644 (file)
index 0000000..4e77113
--- /dev/null
@@ -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/source/smbwrapper/chdir.c b/source/smbwrapper/chdir.c
new file mode 100644 (file)
index 0000000..13e9e0f
--- /dev/null
@@ -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/source/smbwrapper/close.c b/source/smbwrapper/close.c
new file mode 100644 (file)
index 0000000..a0491fc
--- /dev/null
@@ -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/source/smbwrapper/fcntl.c b/source/smbwrapper/fcntl.c
new file mode 100644 (file)
index 0000000..fab18fb
--- /dev/null
@@ -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/source/smbwrapper/fstat.c b/source/smbwrapper/fstat.c
new file mode 100644 (file)
index 0000000..dc83f4a
--- /dev/null
@@ -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/source/smbwrapper/getdents.c b/source/smbwrapper/getdents.c
new file mode 100644 (file)
index 0000000..1ff1b63
--- /dev/null
@@ -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/source/smbwrapper/init.c b/source/smbwrapper/init.c
new file mode 100644 (file)
index 0000000..23d85eb
--- /dev/null
@@ -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/source/smbwrapper/kernel_stat.h b/source/smbwrapper/kernel_stat.h
new file mode 100644 (file)
index 0000000..bd7ddcc
--- /dev/null
@@ -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/source/smbwrapper/lstat.c b/source/smbwrapper/lstat.c
new file mode 100644 (file)
index 0000000..f6298f6
--- /dev/null
@@ -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/source/smbwrapper/open.c b/source/smbwrapper/open.c
new file mode 100644 (file)
index 0000000..8a088ee
--- /dev/null
@@ -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/source/smbwrapper/read.c b/source/smbwrapper/read.c
new file mode 100644 (file)
index 0000000..3ca49a6
--- /dev/null
@@ -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/source/smbwrapper/realcalls.h b/source/smbwrapper/realcalls.h
new file mode 100644 (file)
index 0000000..de9945f
--- /dev/null
@@ -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/source/smbwrapper/smbsh b/source/smbwrapper/smbsh
new file mode 100755 (executable)
index 0000000..f2cceb1
--- /dev/null
@@ -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/source/smbwrapper/smbw.c b/source/smbwrapper/smbw.c
new file mode 100644 (file)
index 0000000..c0c3ac8
--- /dev/null
@@ -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/source/smbwrapper/smbw.h b/source/smbwrapper/smbw.h
new file mode 100644 (file)
index 0000000..c723b69
--- /dev/null
@@ -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/source/smbwrapper/stat.c b/source/smbwrapper/stat.c
new file mode 100644 (file)
index 0000000..8980f75
--- /dev/null
@@ -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/source/smbwrapper/wrapper.h b/source/smbwrapper/wrapper.h
new file mode 100644 (file)
index 0000000..84a947a
--- /dev/null
@@ -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/source/smbwrapper/write.c b/source/smbwrapper/write.c
new file mode 100644 (file)
index 0000000..a05f55d
--- /dev/null
@@ -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);
+}