vfs.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 1,032 行 · 第 1/2 页
C
1,032 行
/* Unix SMB/Netbios implementation. Version 1.9. VFS initialisation and support functions Copyright (C) Tim Potter 1999 Copyright (C) Alexander Bokovoy 2002 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 work was sponsored by Optifacio Software Services, Inc.*/#include "includes.h"#undef DBGC_CLASS#define DBGC_CLASS DBGC_VFSstruct vfs_init_function_entry { char *name; vfs_op_tuple *vfs_op_tuples; struct vfs_init_function_entry *prev, *next;};static struct vfs_init_function_entry *backends = NULL;/* Some structures to help us initialise the vfs operations table */struct vfs_syminfo { char *name; void *fptr;};/* Default vfs hooks. WARNING: The order of these initialisers is very important. They must be in the same order as defined in vfs.h. Change at your own peril. */static struct vfs_ops default_vfs = { { /* Disk operations */ vfswrap_dummy_connect, vfswrap_dummy_disconnect, vfswrap_disk_free, vfswrap_get_quota, vfswrap_set_quota, vfswrap_get_shadow_copy_data, vfswrap_statvfs, /* Directory operations */ vfswrap_opendir, vfswrap_readdir, vfswrap_seekdir, vfswrap_telldir, vfswrap_rewinddir, vfswrap_mkdir, vfswrap_rmdir, vfswrap_closedir, /* File operations */ vfswrap_open, vfswrap_close, vfswrap_read, vfswrap_pread, vfswrap_write, vfswrap_pwrite, vfswrap_lseek, vfswrap_sendfile, vfswrap_rename, vfswrap_fsync, vfswrap_stat, vfswrap_fstat, vfswrap_lstat, vfswrap_unlink, vfswrap_chmod, vfswrap_fchmod, vfswrap_chown, vfswrap_fchown, vfswrap_chdir, vfswrap_getwd, vfswrap_utime, vfswrap_ftruncate, vfswrap_lock, vfswrap_symlink, vfswrap_readlink, vfswrap_link, vfswrap_mknod, vfswrap_realpath, /* Windows ACL operations. */ vfswrap_fget_nt_acl, vfswrap_get_nt_acl, vfswrap_fset_nt_acl, vfswrap_set_nt_acl, /* POSIX ACL operations. */ vfswrap_chmod_acl, vfswrap_fchmod_acl, vfswrap_sys_acl_get_entry, vfswrap_sys_acl_get_tag_type, vfswrap_sys_acl_get_permset, vfswrap_sys_acl_get_qualifier, vfswrap_sys_acl_get_file, vfswrap_sys_acl_get_fd, vfswrap_sys_acl_clear_perms, vfswrap_sys_acl_add_perm, vfswrap_sys_acl_to_text, vfswrap_sys_acl_init, vfswrap_sys_acl_create_entry, vfswrap_sys_acl_set_tag_type, vfswrap_sys_acl_set_qualifier, vfswrap_sys_acl_set_permset, vfswrap_sys_acl_valid, vfswrap_sys_acl_set_file, vfswrap_sys_acl_set_fd, vfswrap_sys_acl_delete_def_file, vfswrap_sys_acl_get_perm, vfswrap_sys_acl_free_text, vfswrap_sys_acl_free_acl, vfswrap_sys_acl_free_qualifier, /* EA operations. */ vfswrap_getxattr, vfswrap_lgetxattr, vfswrap_fgetxattr, vfswrap_listxattr, vfswrap_llistxattr, vfswrap_flistxattr, vfswrap_removexattr, vfswrap_lremovexattr, vfswrap_fremovexattr, vfswrap_setxattr, vfswrap_lsetxattr, vfswrap_fsetxattr, /* AIO operations. */ vfswrap_aio_read, vfswrap_aio_write, vfswrap_aio_return, vfswrap_aio_cancel, vfswrap_aio_error, vfswrap_aio_fsync, vfswrap_aio_suspend }};/**************************************************************************** maintain the list of available backends****************************************************************************/static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name){ struct vfs_init_function_entry *entry = backends; while(entry) { if (strcmp(entry->name, name)==0) return entry; entry = entry->next; } return NULL;}NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tuples){ struct vfs_init_function_entry *entry = backends; if ((version != SMB_VFS_INTERFACE_VERSION)) { DEBUG(0, ("Failed to register vfs module.\n" "The module was compiled against SMB_VFS_INTERFACE_VERSION %d,\n" "current SMB_VFS_INTERFACE_VERSION is %d.\n" "Please recompile against the current Samba Version!\n", version, SMB_VFS_INTERFACE_VERSION)); return NT_STATUS_OBJECT_TYPE_MISMATCH; } if (!name || !name[0] || !vfs_op_tuples) { DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n")); return NT_STATUS_INVALID_PARAMETER; } if (vfs_find_backend_entry(name)) { DEBUG(0,("VFS module %s already loaded!\n", name)); return NT_STATUS_OBJECT_NAME_COLLISION; } entry = SMB_XMALLOC_P(struct vfs_init_function_entry); entry->name = smb_xstrdup(name); entry->vfs_op_tuples = vfs_op_tuples; DLIST_ADD(backends, entry); DEBUG(5, ("Successfully added vfs backend '%s'\n", name)); return NT_STATUS_OK;}/**************************************************************************** initialise default vfs hooks****************************************************************************/static void vfs_init_default(connection_struct *conn){ DEBUG(3, ("Initialising default vfs hooks\n")); memcpy(&conn->vfs.ops, &default_vfs.ops, sizeof(default_vfs.ops)); memcpy(&conn->vfs_opaque.ops, &default_vfs.ops, sizeof(default_vfs.ops));}/**************************************************************************** initialise custom vfs hooks ****************************************************************************/BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object){ vfs_op_tuple *ops; char *module_name = NULL; char *module_param = NULL, *p; int i; vfs_handle_struct *handle; struct vfs_init_function_entry *entry; if (!conn||!vfs_object||!vfs_object[0]) { DEBUG(0,("vfs_init_custon() called with NULL pointer or emtpy vfs_object!\n")); return False; } if(!backends) { static_init_vfs; } DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object)); module_name = smb_xstrdup(vfs_object); p = strchr_m(module_name, ':'); if (p) { *p = 0; module_param = p+1; trim_char(module_param, ' ', ' '); } trim_char(module_name, ' ', ' '); /* First, try to load the module with the new module system */ if((entry = vfs_find_backend_entry(module_name)) || (NT_STATUS_IS_OK(smb_probe_module("vfs", module_name)) && (entry = vfs_find_backend_entry(module_name)))) { DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object)); if ((ops = entry->vfs_op_tuples) == NULL) { DEBUG(0, ("entry->vfs_op_tuples==NULL for [%s] failed\n", vfs_object)); SAFE_FREE(module_name); return False; } } else { DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object)); SAFE_FREE(module_name); return False; } handle = TALLOC_ZERO_P(conn->mem_ctx,vfs_handle_struct); if (!handle) { DEBUG(0,("talloc_zero() failed!\n")); SAFE_FREE(module_name); return False; } memcpy(&handle->vfs_next, &conn->vfs, sizeof(struct vfs_ops)); handle->conn = conn; if (module_param) { handle->param = talloc_strdup(conn->mem_ctx, module_param); } DLIST_ADD(conn->vfs_handles, handle); for(i=0; ops[i].op != NULL; i++) { DEBUG(5, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer)); if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) { /* Check whether this operation was already made opaque by different module */ if(((void**)&conn->vfs_opaque.ops)[ops[i].type] == ((void**)&default_vfs.ops)[ops[i].type]) { /* No, it isn't overloaded yet. Overload. */ DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object)); ((void**)&conn->vfs_opaque.ops)[ops[i].type] = ops[i].op; ((vfs_handle_struct **)&conn->vfs_opaque.handles)[ops[i].type] = handle; } } /* Change current VFS disposition*/ DEBUGADD(5, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object)); ((void**)&conn->vfs.ops)[ops[i].type] = ops[i].op; ((vfs_handle_struct **)&conn->vfs.handles)[ops[i].type] = handle; } SAFE_FREE(module_name); return True;}/***************************************************************** Generic VFS init.******************************************************************/BOOL smbd_vfs_init(connection_struct *conn){ const char **vfs_objects; unsigned int i = 0; int j = 0; /* Normal share - initialise with disk access functions */ vfs_init_default(conn); vfs_objects = lp_vfs_objects(SNUM(conn)); /* Override VFS functions if 'vfs object' was not specified*/ if (!vfs_objects || !vfs_objects[0]) return True; for (i=0; vfs_objects[i] ;) { i++; } for (j=i-1; j >= 0; j--) { if (!vfs_init_custom(conn, vfs_objects[j])) { DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j])); return False; } } return True;}/******************************************************************* Check if directory exists.********************************************************************/BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *st){ SMB_STRUCT_STAT st2; BOOL ret; if (!st) st = &st2; if (SMB_VFS_STAT(conn,dname,st) != 0) return(False); ret = S_ISDIR(st->st_mode); if(!ret) errno = ENOTDIR; return ret;}/******************************************************************* vfs mkdir wrapper ********************************************************************/int vfs_MkDir(connection_struct *conn, const char *name, mode_t mode){ int ret; SMB_STRUCT_STAT sbuf; if(!(ret=SMB_VFS_MKDIR(conn, name, mode))) { inherit_access_acl(conn, name, mode); /* * Check if high bits should have been set, * then (if bits are missing): add them. * Consider bits automagically set by UNIX, i.e. SGID bit from parent dir. */ if(mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && !SMB_VFS_STAT(conn,name,&sbuf) && (mode & ~sbuf.st_mode)) SMB_VFS_CHMOD(conn,name,sbuf.st_mode | (mode & ~sbuf.st_mode)); } return ret;}/******************************************************************* Check if an object exists in the vfs.********************************************************************/BOOL vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT *sbuf){ SMB_STRUCT_STAT st; if (!sbuf) sbuf = &st; ZERO_STRUCTP(sbuf); if (SMB_VFS_STAT(conn,fname,sbuf) == -1) return(False); return True;}/******************************************************************* Check if a file exists in the vfs.********************************************************************/BOOL vfs_file_exist(connection_struct *conn, const char *fname,SMB_STRUCT_STAT *sbuf){ SMB_STRUCT_STAT st; if (!sbuf) sbuf = &st; ZERO_STRUCTP(sbuf); if (SMB_VFS_STAT(conn,fname,sbuf) == -1) return False; return(S_ISREG(sbuf->st_mode));}/**************************************************************************** Read data from fsp on the vfs. (note: EINTR re-read differs from vfs_write_data)****************************************************************************/ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count){ size_t total=0; while (total < byte_count) { ssize_t ret = SMB_VFS_READ(fsp, fsp->fh->fd, buf + total, byte_count - total); if (ret == 0) return total; if (ret == -1) { if (errno == EINTR) continue; else return -1; } total += ret; } return (ssize_t)total;}ssize_t vfs_pread_data(files_struct *fsp, char *buf, size_t byte_count, SMB_OFF_T offset){ size_t total=0; while (total < byte_count) { ssize_t ret = SMB_VFS_PREAD(fsp, fsp->fh->fd, buf + total, byte_count - total, offset + total); if (ret == 0) return total; if (ret == -1) { if (errno == EINTR) continue; else return -1; } total += ret; } return (ssize_t)total;}/**************************************************************************** Write data to a fd on the vfs.****************************************************************************/ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N){ size_t total=0; ssize_t ret; while (total < N) { ret = SMB_VFS_WRITE(fsp,fsp->fh->fd,buffer + total,N - total); if (ret == -1) return -1; if (ret == 0) return total; total += ret; } return (ssize_t)total;}ssize_t vfs_pwrite_data(files_struct *fsp,const char *buffer, size_t N, SMB_OFF_T offset){ size_t total=0; ssize_t ret; while (total < N) { ret = SMB_VFS_PWRITE(fsp, fsp->fh->fd, buffer + total, N - total, offset + total); if (ret == -1) return -1; if (ret == 0) return total; total += ret; } return (ssize_t)total;}/**************************************************************************** An allocate file space call using the vfs interface. Allocates space for a file from a filedescriptor. Returns 0 on success, -1 on failure.****************************************************************************/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?