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 + -
显示快捷键?