⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pvfs_open.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 4 页
字号:
/*    Unix SMB/CIFS implementation.   POSIX NTVFS backend - open and close   Copyright (C) Andrew Tridgell 2004   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 3 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, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "vfs_posix.h"#include "system/dir.h"#include "system/time.h"#include "lib/util/dlinklist.h"#include "messaging/messaging.h"#include "librpc/gen_ndr/xattr.h"/*  find open file handle given fnum*/struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs,			       struct ntvfs_request *req, struct ntvfs_handle *h){	void *p;	struct pvfs_file *f;	p = ntvfs_handle_get_backend_data(h, pvfs->ntvfs);	if (!p) return NULL;	f = talloc_get_type(p, struct pvfs_file);	if (!f) return NULL;	return f;}/*  cleanup a open directory handle*/static int pvfs_dir_handle_destructor(struct pvfs_file_handle *h){	if (h->have_opendb_entry) {		struct odb_lock *lck;		NTSTATUS status;		const char *delete_path = NULL;		lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key);		if (lck == NULL) {			DEBUG(0,("Unable to lock opendb for close\n"));			return 0;		}		status = odb_close_file(lck, h, &delete_path);		if (!NT_STATUS_IS_OK(status)) {			DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n",				 h->name->full_name, nt_errstr(status)));		}		if (h->name->stream_name == NULL && delete_path) {			status = pvfs_xattr_unlink_hook(h->pvfs, delete_path);			if (!NT_STATUS_IS_OK(status)) {				DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n",					 delete_path, nt_errstr(status)));			}			if (rmdir(delete_path) != 0) {				DEBUG(0,("pvfs_dir_handle_destructor: failed to rmdir '%s' - %s\n",					 delete_path, strerror(errno)));			}		}		talloc_free(lck);	}	return 0;}/*  cleanup a open directory fnum*/static int pvfs_dir_fnum_destructor(struct pvfs_file *f){	DLIST_REMOVE(f->pvfs->files.list, f);	ntvfs_handle_remove_backend_data(f->ntvfs, f->pvfs->ntvfs);	return 0;}/*  setup any EAs and the ACL on newly created files/directories*/static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs,					struct ntvfs_request *req,					struct pvfs_filename *name,					int fd,	struct pvfs_file *f,					union smb_open *io){	NTSTATUS status;	/* setup any EAs that were asked for */	if (io->ntcreatex.in.ea_list) {		status = pvfs_setfileinfo_ea_set(pvfs, name, fd, 						 io->ntcreatex.in.ea_list->num_eas,						 io->ntcreatex.in.ea_list->eas);		if (!NT_STATUS_IS_OK(status)) {			return status;		}	}	/* setup an initial sec_desc if requested */	if (io->ntcreatex.in.sec_desc) {		union smb_setfileinfo set;/*  * TODO: set the full ACL!  *       - vista denies the creation of the file with NT_STATUS_PRIVILEGE_NOT_HELD, *         when a SACL is present on the sd, *         but the user doesn't have SeSecurityPrivilege *       - w2k3 allows it */		set.set_secdesc.in.file.ntvfs = f->ntvfs;		set.set_secdesc.in.secinfo_flags = SECINFO_DACL;		set.set_secdesc.in.sd = io->ntcreatex.in.sec_desc;		status = pvfs_acl_set(pvfs, req, name, fd, SEC_STD_WRITE_DAC, &set);	} else {		/* otherwise setup an inherited acl from the parent */		status = pvfs_acl_inherit(pvfs, req, name, fd);	}	return status;}/*  form the lock context used for opendb locking. Note that we must  zero here to take account of possible padding on some architectures*/NTSTATUS pvfs_locking_key(struct pvfs_filename *name,			  TALLOC_CTX *mem_ctx, DATA_BLOB *key){	struct {		dev_t device;		ino_t inode;	} lock_context;	ZERO_STRUCT(lock_context);	lock_context.device = name->st.st_dev;	lock_context.inode = name->st.st_ino;	*key = data_blob_talloc(mem_ctx, &lock_context, sizeof(lock_context));	if (key->data == NULL) {		return NT_STATUS_NO_MEMORY;	}		return NT_STATUS_OK;}/*  open a directory*/static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, 				    struct ntvfs_request *req, 				    struct pvfs_filename *name, 				    union smb_open *io){	struct pvfs_file *f;	struct ntvfs_handle *h;	NTSTATUS status;	uint32_t create_action;	uint32_t access_mask = io->generic.in.access_mask;	struct odb_lock *lck;	bool del_on_close;	uint32_t create_options;	uint32_t share_access;	bool forced;	create_options = io->generic.in.create_options;	share_access   = io->generic.in.share_access;	forced = (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)?true:false;	if (name->stream_name) {		if (forced) {			return NT_STATUS_NOT_A_DIRECTORY;		} else {			return NT_STATUS_FILE_IS_A_DIRECTORY;		}	}	/* if the client says it must be a directory, and it isn't,	   then fail */	if (name->exists && !(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) {		return NT_STATUS_NOT_A_DIRECTORY;	}	/* found with gentest */	if (io->ntcreatex.in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED &&	    (io->ntcreatex.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) &&	    (io->ntcreatex.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {		return NT_STATUS_INVALID_PARAMETER;	}		switch (io->generic.in.open_disposition) {	case NTCREATEX_DISP_OPEN_IF:		break;	case NTCREATEX_DISP_OPEN:		if (!name->exists) {			return NT_STATUS_OBJECT_NAME_NOT_FOUND;		}		break;	case NTCREATEX_DISP_CREATE:		if (name->exists) {			return NT_STATUS_OBJECT_NAME_COLLISION;		}		break;	case NTCREATEX_DISP_OVERWRITE_IF:	case NTCREATEX_DISP_OVERWRITE:	case NTCREATEX_DISP_SUPERSEDE:	default:		return NT_STATUS_INVALID_PARAMETER;	}	status = ntvfs_handle_new(pvfs->ntvfs, req, &h);	NT_STATUS_NOT_OK_RETURN(status);	f = talloc(h, struct pvfs_file);	if (f == NULL) {		return NT_STATUS_NO_MEMORY;	}	f->handle = talloc(f, struct pvfs_file_handle);	if (f->handle == NULL) {		return NT_STATUS_NO_MEMORY;	}	if (name->exists) {		/* check the security descriptor */		status = pvfs_access_check(pvfs, req, name, &access_mask);	} else {		status = pvfs_access_check_create(pvfs, req, name, &access_mask);	}	NT_STATUS_NOT_OK_RETURN(status);	if (io->generic.in.query_maximal_access) {		status = pvfs_access_maximal_allowed(pvfs, req, name, 						     &io->generic.out.maximal_access);		NT_STATUS_NOT_OK_RETURN(status);	}	f->ntvfs         = h;	f->pvfs          = pvfs;	f->pending_list  = NULL;	f->lock_count    = 0;	f->share_access  = io->generic.in.share_access;	f->impersonation = io->generic.in.impersonation;	f->access_mask   = access_mask;	f->brl_handle	 = NULL;	f->notify_buffer = NULL;	f->search        = NULL;	f->handle->pvfs              = pvfs;	f->handle->name              = talloc_steal(f->handle, name);	f->handle->fd                = -1;	f->handle->odb_locking_key   = data_blob(NULL, 0);	f->handle->create_options    = io->generic.in.create_options;	f->handle->seek_offset       = 0;	f->handle->position          = 0;	f->handle->mode              = 0;	f->handle->oplock            = NULL;	f->handle->open_completed    = false;	if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&	    pvfs_directory_empty(pvfs, f->handle->name)) {		del_on_close = true;	} else {		del_on_close = false;	}	if (name->exists) {		/* form the lock context used for opendb locking */		status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key);		if (!NT_STATUS_IS_OK(status)) {			return status;		}		/* get a lock on this file before the actual open */		lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);		if (lck == NULL) {			DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n",				 name->full_name));			/* we were supposed to do a blocking lock, so something			   is badly wrong! */			return NT_STATUS_INTERNAL_DB_CORRUPTION;		}				/* see if we are allowed to open at the same time as existing opens */		status = odb_can_open(lck, name->stream_id,				      share_access, access_mask, del_on_close,				      io->generic.in.open_disposition, false);		if (!NT_STATUS_IS_OK(status)) {			talloc_free(lck);			return status;		}		/* now really mark the file as open */		status = odb_open_file(lck, f->handle, name->full_name,				       NULL, false, OPLOCK_NONE, NULL);		if (!NT_STATUS_IS_OK(status)) {			talloc_free(lck);			return status;		}		f->handle->have_opendb_entry = true;	}	DLIST_ADD(pvfs->files.list, f);	/* setup destructors to avoid leaks on abnormal termination */	talloc_set_destructor(f->handle, pvfs_dir_handle_destructor);	talloc_set_destructor(f, pvfs_dir_fnum_destructor);	if (!name->exists) {		uint32_t attrib = io->generic.in.file_attr | FILE_ATTRIBUTE_DIRECTORY;		mode_t mode = pvfs_fileperms(pvfs, attrib);		if (mkdir(name->full_name, mode) == -1) {			return pvfs_map_errno(pvfs,errno);		}		pvfs_xattr_unlink_hook(pvfs, name->full_name);		status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 0, &name);		if (!NT_STATUS_IS_OK(status)) {			goto cleanup_delete;		}		status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, f, io);		if (!NT_STATUS_IS_OK(status)) {			goto cleanup_delete;		}		/* form the lock context used for opendb locking */		status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key);		if (!NT_STATUS_IS_OK(status)) {			return status;		}		lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);		if (lck == NULL) {			DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n",				 name->full_name));			/* we were supposed to do a blocking lock, so something			   is badly wrong! */			return NT_STATUS_INTERNAL_DB_CORRUPTION;		}		status = odb_can_open(lck, name->stream_id,				      share_access, access_mask, del_on_close,				      io->generic.in.open_disposition, false);		if (!NT_STATUS_IS_OK(status)) {			goto cleanup_delete;		}		status = odb_open_file(lck, f->handle, name->full_name,				       NULL, false, OPLOCK_NONE, NULL);		if (!NT_STATUS_IS_OK(status)) {			goto cleanup_delete;		}		f->handle->have_opendb_entry = true;		create_action = NTCREATEX_ACTION_CREATED;		notify_trigger(pvfs->notify_context, 			       NOTIFY_ACTION_ADDED, 			       FILE_NOTIFY_CHANGE_DIR_NAME,			       name->full_name);	} else {		create_action = NTCREATEX_ACTION_EXISTED;	}	if (!name->exists) {		return NT_STATUS_OBJECT_NAME_NOT_FOUND;	}	/* the open succeeded, keep this handle permanently */	status = ntvfs_handle_set_backend_data(h, pvfs->ntvfs, f);	if (!NT_STATUS_IS_OK(status)) {		goto cleanup_delete;	}	f->handle->open_completed = true;	io->generic.out.oplock_level  = OPLOCK_NONE;	io->generic.out.file.ntvfs    = h;	io->generic.out.create_action = create_action;	io->generic.out.create_time   = name->dos.create_time;	io->generic.out.access_time   = name->dos.access_time;	io->generic.out.write_time    = name->dos.write_time;	io->generic.out.change_time   = name->dos.change_time;	io->generic.out.attrib        = name->dos.attrib;	io->generic.out.alloc_size    = name->dos.alloc_size;	io->generic.out.size          = name->st.st_size;	io->generic.out.file_type     = FILE_TYPE_DISK;	io->generic.out.ipc_state     = 0;	io->generic.out.is_directory  = 1;	return NT_STATUS_OK;cleanup_delete:	rmdir(name->full_name);	return status;}/*  destroy a struct pvfs_file_handle*/static int pvfs_handle_destructor(struct pvfs_file_handle *h){	if ((h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&	    h->name->stream_name) {		NTSTATUS status;		status = pvfs_stream_delete(h->pvfs, h->name, h->fd);		if (!NT_STATUS_IS_OK(status)) {			DEBUG(0,("Failed to delete stream '%s' on close of '%s'\n",				 h->name->stream_name, h->name->full_name));		}	}	if (h->fd != -1) {		if (close(h->fd) != 0) {			DEBUG(0,("pvfs_handle_destructor: close(%d) failed for %s - %s\n",				 h->fd, h->name->full_name, strerror(errno)));		}		h->fd = -1;	}	if (h->have_opendb_entry) {		struct odb_lock *lck;		NTSTATUS status;		const char *delete_path = NULL;		lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key);		if (lck == NULL) {			DEBUG(0,("Unable to lock opendb for close\n"));			return 0;		}		status = odb_close_file(lck, h, &delete_path);		if (!NT_STATUS_IS_OK(status)) {			DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n", 				 h->name->full_name, nt_errstr(status)));		}		if (h->name->stream_name == NULL &&		    h->open_completed && delete_path) {			status = pvfs_xattr_unlink_hook(h->pvfs, delete_path);			if (!NT_STATUS_IS_OK(status)) {				DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n",					 delete_path, nt_errstr(status)));			}			if (unlink(delete_path) != 0) {				DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n",					 delete_path, strerror(errno)));			} else {				notify_trigger(h->pvfs->notify_context,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -