diff options
-rw-r--r-- | source3/smbwrapper/README | 26 | ||||
-rw-r--r-- | source3/smbwrapper/access.c | 32 | ||||
-rw-r--r-- | source3/smbwrapper/chdir.c | 28 | ||||
-rw-r--r-- | source3/smbwrapper/close.c | 35 | ||||
-rw-r--r-- | source3/smbwrapper/fcntl.c | 35 | ||||
-rw-r--r-- | source3/smbwrapper/fstat.c | 84 | ||||
-rw-r--r-- | source3/smbwrapper/getdents.c | 36 | ||||
-rw-r--r-- | source3/smbwrapper/init.c | 22 | ||||
-rw-r--r-- | source3/smbwrapper/kernel_stat.h | 31 | ||||
-rw-r--r-- | source3/smbwrapper/lstat.c | 85 | ||||
-rw-r--r-- | source3/smbwrapper/open.c | 36 | ||||
-rw-r--r-- | source3/smbwrapper/read.c | 35 | ||||
-rw-r--r-- | source3/smbwrapper/realcalls.h | 44 | ||||
-rwxr-xr-x | source3/smbwrapper/smbsh | 6 | ||||
-rw-r--r-- | source3/smbwrapper/smbw.c | 1005 | ||||
-rw-r--r-- | source3/smbwrapper/smbw.h | 28 | ||||
-rw-r--r-- | source3/smbwrapper/stat.c | 89 | ||||
-rw-r--r-- | source3/smbwrapper/wrapper.h | 8 | ||||
-rw-r--r-- | source3/smbwrapper/write.c | 35 |
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); +} |