?? wrapper.c
字號(hào):
/* Unix SMB/Netbios implementation. Version 2.0 SMB wrapper functions Copyright (C) Andrew Tridgell 1998 Copyright (C) Derrell Lipman 2002-2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*//* * This is a rewrite of the original wrapped.c file, using libdl to obtain * pointers into the C library rather than attempting to find undocumented * functions in the C library to call for native file access. The problem * with the original implementation's paradigm is that samba manipulates * defines such that it gets the sizes of structures that it wants * (e.g. mapping 32-bit functions to 64-bit functions with their associated * 64-bit structure fields), but programs run under smbsh or using * smbwrapper.so were not necessarily compiled with the same flags. As an * example of the problem, a program calling stat() passes a pointer to a * "struct stat" but the fields in that structure are different in samba than * they are in the calling program if the calling program was not compiled to * force stat() to be mapped to stat64(). * * In this version, we provide an interface to each of the native functions, * not just the ones that samba is compiled to map to. We obtain the function * pointers from the C library using dlsym(), and for native file operations, * directly call the same function that the calling application was * requesting. Since the size of the calling application's structures vary * depending on what function was called, we use our own internal structures * for passing information to/from the SMB equivalent functions, and map them * back to the native structures before returning the result to the caller. * * This implementation was completed 25 December 2002. * Derrell Lipman *//* We do not want auto munging of 32->64 bit names in this file (only) */#undef _FILE_OFFSET_BITS#undef _GNU_SOURCE#include <sys/types.h>#include <sys/stat.h>#include <sys/time.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>#include <utime.h>#include <stdio.h>#include <dirent.h>#include <signal.h>#include <stdarg.h>#ifdef __USE_GNU# define SMBW_USE_GNU#endif#define __USE_GNU /* need this to have RTLD_NEXT defined */#include <dlfcn.h>#ifndef SMBW_USE_GNU# undef __USE_GNU#endif#include <errno.h>#include "libsmbclient.h"#include "bsd-strlfunc.h"#include "wrapper.h"/* * Debug bits: * 0x0 = none * 0x1 = display symbol definitions not found in C library * 0x2 = show wrapper functions being called * 0x4 = log to file SMBW_DEBUG_FILE instead of stderr */#define SMBW_DEBUG 0x0#define SMBW_DEBUG_FILE "/tmp/smbw.log"int smbw_debug = 0;#if SMBW_DEBUG & 0x2static int debugFd = 2;#endif#ifndef ENOTSUP#define ENOTSUP EOPNOTSUPP#endif/* * None of the methods of having the initialization function called * automatically upon shared library startup are effective in all situations. * We provide the "-init" parameter to the linker which is effective most of * the time, but fails for applications that provide their own shared * libraries with _init() functions (e.g. ps). We can't use "-z initfirst" * because the environment isn't yet set up at that point, so we can't find * our shared memory identifier (see shared.c). We therefore must resort to * this tried-and-true method of keeping an "initialized" flag. We check it * prior to calling the initialize() function to save a function call (a slow * operation on x86). */#if SMBW_DEBUG & 0x2# define check_init(buf) \ do { \ int saved_errno = errno; \ if (! initialized) initialize(); \ (* smbw_libc.write)(debugFd, "["buf"]", sizeof(buf)+1); \ errno = saved_errno; \ } while (0)#else# define check_init(buf) \ do { \ if (! initialized) smbw_initialize(); \ } while (0)#endifstatic void initialize(void);static int initialized = 0;SMBW_libc_pointers smbw_libc;/* * A public entry point used by the "-init" option to the linker. */void smbw_initialize(void){ initialize();}static void initialize(void){ int saved_errno;#if SMBW_DEBUG & 0x1 char *error;#endif saved_errno = errno; if (initialized) { return; } initialized = 1; #if SMBW_DEBUG & 0x1# define GETSYM(symname, symstring) \ if ((smbw_libc.symname = dlsym(RTLD_NEXT, symstring)) == NULL) { \ if (smbw_libc.write != NULL && \ (error = dlerror()) != NULL) { \ (* smbw_libc.write)(1, error, strlen(error)); \ (* smbw_libc.write)(1, "\n", 1); \ } \ }#else# define GETSYM(symname, symstring) \ smbw_libc.symname = dlsym(RTLD_NEXT, symstring);#endif /* * Get pointers to each of the symbols we'll need, from the C library * * Some of these symbols may not be found in the C library. That's * fine. We declare all of them here, and if the C library supports * them, they may be called so we have the wrappers for them. If the * C library doesn't support them, then the wrapper function will * never be called, and the null pointer will never be dereferenced. */ GETSYM(write, "write"); /* first, to allow debugging */ GETSYM(open, "open"); GETSYM(_open, "_open"); GETSYM(__open, "__open"); GETSYM(open64, "open64"); GETSYM(_open64, "_open64"); GETSYM(__open64, "__open64"); GETSYM(pread, "pread"); GETSYM(pread64, "pread64"); GETSYM(pwrite, "pwrite"); GETSYM(pwrite64, "pwrite64"); GETSYM(close, "close"); GETSYM(__close, "__close"); GETSYM(_close, "_close"); GETSYM(fcntl, "fcntl"); GETSYM(__fcntl, "__fcntl"); GETSYM(_fcntl, "_fcntl"); GETSYM(getdents, "getdents"); GETSYM(__getdents, "__getdents"); GETSYM(_getdents, "_getdents"); GETSYM(getdents64, "getdents64"); GETSYM(lseek, "lseek"); GETSYM(__lseek, "__lseek"); GETSYM(_lseek, "_lseek"); GETSYM(lseek64, "lseek64"); GETSYM(__lseek64, "__lseek64"); GETSYM(_lseek64, "_lseek64"); GETSYM(read, "read"); GETSYM(__read, "__read"); GETSYM(_read, "_read"); GETSYM(__write, "__write"); GETSYM(_write, "_write"); GETSYM(access, "access"); GETSYM(chmod, "chmod"); GETSYM(fchmod, "fchmod"); GETSYM(chown, "chown"); GETSYM(fchown, "fchown"); GETSYM(__xstat, "__xstat"); GETSYM(getcwd, "getcwd"); GETSYM(mkdir, "mkdir"); GETSYM(__fxstat, "__fxstat"); GETSYM(__lxstat, "__lxstat"); GETSYM(stat, "stat"); GETSYM(lstat, "lstat"); GETSYM(fstat, "fstat"); GETSYM(unlink, "unlink"); GETSYM(utime, "utime"); GETSYM(utimes, "utimes"); GETSYM(readlink, "readlink"); GETSYM(rename, "rename"); GETSYM(rmdir, "rmdir"); GETSYM(symlink, "symlink"); GETSYM(dup, "dup"); GETSYM(dup2, "dup2"); GETSYM(opendir, "opendir"); GETSYM(readdir, "readdir"); GETSYM(closedir, "closedir"); GETSYM(telldir, "telldir"); GETSYM(seekdir, "seekdir"); GETSYM(creat, "creat"); GETSYM(creat64, "creat64"); GETSYM(__xstat64, "__xstat64"); GETSYM(stat64, "stat64"); GETSYM(__fxstat64, "__fxstat64"); GETSYM(fstat64, "fstat64"); GETSYM(__lxstat64, "__lxstat64"); GETSYM(lstat64, "lstat64"); GETSYM(_llseek, "_llseek"); GETSYM(readdir64, "readdir64"); GETSYM(readdir_r, "readdir_r"); GETSYM(readdir64_r, "readdir64_r"); GETSYM(setxattr, "setxattr"); GETSYM(lsetxattr, "lsetxattr"); GETSYM(fsetxattr, "fsetxattr"); GETSYM(getxattr, "getxattr"); GETSYM(lgetxattr, "lgetxattr"); GETSYM(fgetxattr, "fgetxattr"); GETSYM(removexattr, "removexattr"); GETSYM(lremovexattr, "lremovexattr"); GETSYM(fremovexattr, "fremovexattr"); GETSYM(listxattr, "listxattr"); GETSYM(llistxattr, "llistxattr"); GETSYM(flistxattr, "flistxattr"); GETSYM(chdir, "chdir"); GETSYM(fchdir, "fchdir"); GETSYM(fork, "fork"); GETSYM(select, "select"); GETSYM(_select, "_select"); GETSYM(__select, "__select"); #if SMBW_DEBUG & 4 { if ((debugFd = open(SMBW_DEBUG_FILE, O_WRONLY | O_CREAT | O_APPEND)) < 0) {# define SMBW_MESSAGE "Could not create " SMBW_DEBUG_FILE "\n" (* smbw_libc.write)(1, SMBW_MESSAGE, sizeof(SMBW_MESSAGE));# undef SMBW_MESSAGE exit(1); } }#endif errno = saved_errno;}/** ** Static Functions **/static void stat_convert(struct SMBW_stat *src, struct stat *dest){ memset(dest, '\0', sizeof(*dest)); dest->st_size = src->s_size; dest->st_mode = src->s_mode; dest->st_ino = src->s_ino; dest->st_dev = src->s_dev; dest->st_rdev = src->s_rdev; dest->st_nlink = src->s_nlink; dest->st_uid = src->s_uid; dest->st_gid = src->s_gid; dest->st_atime = src->s_atime; dest->st_mtime = src->s_mtime; dest->st_ctime = src->s_ctime; dest->st_blksize = src->s_blksize; dest->st_blocks = src->s_blocks;}static void stat64_convert(struct SMBW_stat *src, struct stat64 *dest){ memset(dest, '\0', sizeof(*dest)); dest->st_size = src->s_size; dest->st_mode = src->s_mode; dest->st_ino = src->s_ino; dest->st_dev = src->s_dev; dest->st_rdev = src->s_rdev; dest->st_nlink = src->s_nlink; dest->st_uid = src->s_uid; dest->st_gid = src->s_gid; dest->st_atime = src->s_atime; dest->st_mtime = src->s_mtime; dest->st_ctime = src->s_ctime; dest->st_blksize = src->s_blksize; dest->st_blocks = src->s_blocks;}static void dirent_convert(struct SMBW_dirent *src, struct dirent *dest){ char *p; memset(dest, '\0', sizeof(*dest)); dest->d_ino = src->d_ino; dest->d_off = src->d_off; switch(src->d_type) { case SMBC_WORKGROUP: case SMBC_SERVER: case SMBC_FILE_SHARE: case SMBC_DIR: dest->d_type = DT_DIR; break; case SMBC_FILE: dest->d_type = DT_REG; break; case SMBC_PRINTER_SHARE: dest->d_type = DT_CHR; break; case SMBC_COMMS_SHARE: dest->d_type = DT_SOCK; break; case SMBC_IPC_SHARE: dest->d_type = DT_FIFO; break; case SMBC_LINK: dest->d_type = DT_LNK; break; } dest->d_reclen = src->d_reclen; smbw_strlcpy(dest->d_name, src->d_name, sizeof(dest->d_name)); p = dest->d_name + strlen(dest->d_name) + 1; smbw_strlcpy(p, src->d_comment, sizeof(dest->d_name) - (p - dest->d_name));}static void dirent64_convert(struct SMBW_dirent *src, struct dirent64 *dest){ char *p; memset(dest, '\0', sizeof(*dest)); dest->d_ino = src->d_ino; dest->d_off = src->d_off; switch(src->d_type) { case SMBC_WORKGROUP: case SMBC_SERVER: case SMBC_FILE_SHARE: case SMBC_DIR: dest->d_type = DT_DIR; break; case SMBC_FILE: dest->d_type = DT_REG; break; case SMBC_PRINTER_SHARE: dest->d_type = DT_CHR; break; case SMBC_COMMS_SHARE: dest->d_type = DT_SOCK; break; case SMBC_IPC_SHARE: dest->d_type = DT_FIFO; break; case SMBC_LINK: dest->d_type = DT_LNK; break; } dest->d_reclen = src->d_reclen; smbw_strlcpy(dest->d_name, src->d_name, sizeof(dest->d_name)); p = dest->d_name + strlen(dest->d_name) + 1; smbw_strlcpy(p, src->d_comment, sizeof(dest->d_name) - (p - dest->d_name));}static int openx(char *name, int flags, mode_t mode, int (* f)(char *, int, mode_t)){ if (smbw_path(name)) { return smbw_open(name, flags, mode); } return (* f)(name, flags, mode);}static int closex(int fd, int (* f)(int fd)){ if (smbw_fd(fd)) { return smbw_close(fd); } return (* f)(fd);}static int fcntlx(int fd, int cmd, long arg, int (* f)(int, int, long)){ if (smbw_fd(fd)) { return smbw_fcntl(fd, cmd, arg); } return (* f)(fd, cmd, arg);}static int getdentsx(int fd, struct dirent *external, unsigned int count, int (* f)(int, struct dirent *, unsigned int)){ if (smbw_fd(fd)) { int i; int internal_count; struct SMBW_dirent *internal; int ret; int n; /* * LIMITATION: If they pass a count which is not a multiple of * the size of struct dirent, they will not get a partial * structure; we ignore the excess count. */ n = (count / sizeof(struct dirent)); internal_count = sizeof(struct SMBW_dirent) * n; internal = malloc(internal_count); if (internal == NULL) { errno = ENOMEM; return -1; } ret = smbw_getdents(fd, internal, internal_count); if (ret <= 0) return ret; ret = sizeof(struct dirent) * n; for (i = 0; i < n; i++) dirent_convert(&internal[i], &external[i]); return ret; } return (* f)(fd, external, count);}static off_t lseekx(int fd, off_t offset, int whence, off_t (* f)(int, off_t, int)){ off_t ret; /* * We have left the definitions of the smbw_ functions undefined, * because types such as off_t can differ in meaning betweent his * function and smbw.c et al. Functions that return other than an * integer value, however, MUST have their return value defined. */ off64_t smbw_lseek(); if (smbw_fd(fd)) { return (off_t) smbw_lseek(fd, offset, whence); } ret = (* f)(fd, offset, whence); if (smbw_debug) { printf("lseekx(%d, 0x%llx) returned 0x%llx\n", fd, (unsigned long long) offset, (unsigned long long) ret); } return ret;}static off64_t lseek64x(int fd, off64_t offset, int whence, off64_t (* f)(int, off64_t, int)){ off64_t ret; /* * We have left the definitions of the smbw_ functions undefined, * because types such as off_t can differ in meaning betweent his * function and smbw.c et al. Functions that return other than an * integer value, however, MUST have their return value defined. */ off64_t smbw_lseek(); if (smbw_fd(fd)) ret = smbw_lseek(fd, offset, whence); else ret = (* f)(fd, offset, whence); if (smbw_debug) { printf("lseek64x(%d, 0x%llx) returned 0x%llx\n", fd, (unsigned long long) offset, (unsigned long long) ret); } return ret;}static ssize_t readx(int fd, void *buf, size_t count, ssize_t (* f)(int, void *, size_t)){ if (smbw_fd(fd)) { return smbw_read(fd, buf, count); } return (* f)(fd, buf, count);}static ssize_t writex(int fd, void *buf, size_t count, ssize_t (* f)(int, void *, size_t)){ if (smbw_fd(fd)) { return smbw_write(fd, buf, count); } return (* f)(fd, buf, count);}/** ** Wrapper Functions **/int open(__const char *name, int flags, ...){ va_list ap; mode_t mode; va_start(ap, flags); mode = va_arg(ap, mode_t); va_end(ap); check_init("open"); return openx((char *) name, flags, mode, smbw_libc.open);}int _open(char *name, int flags, mode_t mode){ check_init("open");
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -