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

📄 pvfs_xattr.c

📁 samba最新软件
💻 C
字号:
/*    Unix SMB/CIFS implementation.   POSIX NTVFS backend - xattr support   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 "lib/util/unix_privs.h"#include "librpc/gen_ndr/ndr_xattr.h"#include "param/param.h"/*  pull a xattr as a blob*/static NTSTATUS pull_xattr_blob(struct pvfs_state *pvfs,				TALLOC_CTX *mem_ctx,				const char *attr_name, 				const char *fname, 				int fd, 				size_t estimated_size,				DATA_BLOB *blob){	NTSTATUS status;	if (pvfs->ea_db) {		return pull_xattr_blob_tdb(pvfs, mem_ctx, attr_name, fname, 					   fd, estimated_size, blob);	}	status = pull_xattr_blob_system(pvfs, mem_ctx, attr_name, fname, 					fd, estimated_size, blob);	/* if the filesystem doesn't support them, then tell pvfs not to try again */	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)||	    NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)||	    NT_STATUS_EQUAL(status, NT_STATUS_INVALID_SYSTEM_SERVICE)) {		DEBUG(5,("pvfs_xattr: xattr not supported in filesystem: %s\n", nt_errstr(status)));		pvfs->flags &= ~PVFS_FLAG_XATTR_ENABLE;		status = NT_STATUS_NOT_FOUND;	}	return status;}/*  push a xattr as a blob*/static NTSTATUS push_xattr_blob(struct pvfs_state *pvfs,				const char *attr_name, 				const char *fname, 				int fd, 				const DATA_BLOB *blob){	if (pvfs->ea_db) {		return push_xattr_blob_tdb(pvfs, attr_name, fname, fd, blob);	}	return push_xattr_blob_system(pvfs, attr_name, fname, fd, blob);}/*  delete a xattr*/static NTSTATUS delete_xattr(struct pvfs_state *pvfs, const char *attr_name, 			     const char *fname, int fd){	if (pvfs->ea_db) {		return delete_xattr_tdb(pvfs, attr_name, fname, fd);	}	return delete_xattr_system(pvfs, attr_name, fname, fd);}/*  a hook called on unlink - allows the tdb xattr backend to cleanup*/NTSTATUS pvfs_xattr_unlink_hook(struct pvfs_state *pvfs, const char *fname){	if (pvfs->ea_db) {		return unlink_xattr_tdb(pvfs, fname);	}	return unlink_xattr_system(pvfs, fname);}/*  load a NDR structure from a xattr*/NTSTATUS pvfs_xattr_ndr_load(struct pvfs_state *pvfs,			     TALLOC_CTX *mem_ctx,			     const char *fname, int fd, const char *attr_name,			     void *p, void *pull_fn){	NTSTATUS status;	DATA_BLOB blob;	enum ndr_err_code ndr_err;	status = pull_xattr_blob(pvfs, mem_ctx, attr_name, fname, 				 fd, XATTR_DOSATTRIB_ESTIMATED_SIZE, &blob);	if (!NT_STATUS_IS_OK(status)) {		return status;	}	/* pull the blob */	ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, lp_iconv_convenience(pvfs->ntvfs->ctx->lp_ctx), 				       p, (ndr_pull_flags_fn_t)pull_fn);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		return ndr_map_error2ntstatus(ndr_err);	}	data_blob_free(&blob);	return NT_STATUS_OK;}/*  save a NDR structure into a xattr*/NTSTATUS pvfs_xattr_ndr_save(struct pvfs_state *pvfs,			     const char *fname, int fd, const char *attr_name, 			     void *p, void *push_fn){	TALLOC_CTX *mem_ctx = talloc_new(NULL);	DATA_BLOB blob;	NTSTATUS status;	enum ndr_err_code ndr_err;	ndr_err = ndr_push_struct_blob(&blob, mem_ctx, lp_iconv_convenience(pvfs->ntvfs->ctx->lp_ctx), p, (ndr_push_flags_fn_t)push_fn);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		talloc_free(mem_ctx);		return ndr_map_error2ntstatus(ndr_err);	}	status = push_xattr_blob(pvfs, attr_name, fname, fd, &blob);	talloc_free(mem_ctx);	return status;}/*  fill in file attributes from extended attributes*/NTSTATUS pvfs_dosattrib_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd){	NTSTATUS status;	struct xattr_DosAttrib attrib;	TALLOC_CTX *mem_ctx = talloc_new(name);	struct xattr_DosInfo1 *info1;	struct xattr_DosInfo2Old *info2;	if (name->stream_name != NULL) {		name->stream_exists = false;	} else {		name->stream_exists = true;	}	if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {		return NT_STATUS_OK;	}	status = pvfs_xattr_ndr_load(pvfs, mem_ctx, name->full_name, 				     fd, XATTR_DOSATTRIB_NAME,				     &attrib, 				     (ndr_pull_flags_fn_t)ndr_pull_xattr_DosAttrib);	/* not having a DosAttrib is not an error */	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {		talloc_free(mem_ctx);		return pvfs_stream_info(pvfs, name, fd);	}	if (!NT_STATUS_IS_OK(status)) {		talloc_free(mem_ctx);		return status;	}	switch (attrib.version) {	case 1:		info1 = &attrib.info.info1;		name->dos.attrib = pvfs_attrib_normalise(info1->attrib, 							 name->st.st_mode);		name->dos.ea_size = info1->ea_size;		if (name->st.st_size == info1->size) {			name->dos.alloc_size = 				pvfs_round_alloc_size(pvfs, info1->alloc_size);		}		if (!null_nttime(info1->create_time)) {			name->dos.create_time = info1->create_time;		}		if (!null_nttime(info1->change_time)) {			name->dos.change_time = info1->change_time;		}		name->dos.flags = 0;		break;	case 2:		/*		 * Note: This is only used to parse existing values from disk		 *       We use xattr_DosInfo1 again for storing new values		 */		info2 = &attrib.info.oldinfo2;		name->dos.attrib = pvfs_attrib_normalise(info2->attrib, 							 name->st.st_mode);		name->dos.ea_size = info2->ea_size;		if (name->st.st_size == info2->size) {			name->dos.alloc_size = 				pvfs_round_alloc_size(pvfs, info2->alloc_size);		}		if (!null_nttime(info2->create_time)) {			name->dos.create_time = info2->create_time;		}		if (!null_nttime(info2->change_time)) {			name->dos.change_time = info2->change_time;		}		name->dos.flags = info2->flags;		break;	default:		DEBUG(0,("ERROR: Unsupported xattr DosAttrib version %d on '%s'\n",			 attrib.version, name->full_name));		talloc_free(mem_ctx);		return NT_STATUS_INVALID_LEVEL;	}	talloc_free(mem_ctx);		status = pvfs_stream_info(pvfs, name, fd);	return status;}/*  save the file attribute into the xattr*/NTSTATUS pvfs_dosattrib_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd){	struct xattr_DosAttrib attrib;	struct xattr_DosInfo1 *info1;	if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {		return NT_STATUS_OK;	}	attrib.version = 1;	info1 = &attrib.info.info1;	name->dos.attrib = pvfs_attrib_normalise(name->dos.attrib, name->st.st_mode);	info1->attrib      = name->dos.attrib;	info1->ea_size     = name->dos.ea_size;	info1->size        = name->st.st_size;	info1->alloc_size  = name->dos.alloc_size;	info1->create_time = name->dos.create_time;	info1->change_time = name->dos.change_time;	return pvfs_xattr_ndr_save(pvfs, name->full_name, fd, 				   XATTR_DOSATTRIB_NAME, &attrib, 				   (ndr_push_flags_fn_t)ndr_push_xattr_DosAttrib);}/*  load the set of DOS EAs*/NTSTATUS pvfs_doseas_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,			  struct xattr_DosEAs *eas){	NTSTATUS status;	ZERO_STRUCTP(eas);	if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {		return NT_STATUS_OK;	}	status = pvfs_xattr_ndr_load(pvfs, eas, name->full_name, fd, XATTR_DOSEAS_NAME,				     eas, (ndr_pull_flags_fn_t)ndr_pull_xattr_DosEAs);	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {		return NT_STATUS_OK;	}	return status;}/*  save the set of DOS EAs*/NTSTATUS pvfs_doseas_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,			  struct xattr_DosEAs *eas){	if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {		return NT_STATUS_OK;	}	return pvfs_xattr_ndr_save(pvfs, name->full_name, fd, XATTR_DOSEAS_NAME, eas, 				   (ndr_push_flags_fn_t)ndr_push_xattr_DosEAs);}/*  load the set of streams from extended attributes*/NTSTATUS pvfs_streams_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,			   struct xattr_DosStreams *streams){	NTSTATUS status;	ZERO_STRUCTP(streams);	if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {		return NT_STATUS_OK;	}	status = pvfs_xattr_ndr_load(pvfs, streams, name->full_name, fd, 				     XATTR_DOSSTREAMS_NAME,				     streams, 				     (ndr_pull_flags_fn_t)ndr_pull_xattr_DosStreams);	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {		return NT_STATUS_OK;	}	return status;}/*  save the set of streams into filesystem xattr*/NTSTATUS pvfs_streams_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,			   struct xattr_DosStreams *streams){	if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {		return NT_STATUS_OK;	}	return pvfs_xattr_ndr_save(pvfs, name->full_name, fd, 				   XATTR_DOSSTREAMS_NAME, 				   streams, 				   (ndr_push_flags_fn_t)ndr_push_xattr_DosStreams);}/*  load the current ACL from extended attributes*/NTSTATUS pvfs_acl_load(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,		       struct xattr_NTACL *acl){	NTSTATUS status;	ZERO_STRUCTP(acl);	if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {		return NT_STATUS_NOT_FOUND;	}	status = pvfs_xattr_ndr_load(pvfs, acl, name->full_name, fd, 				     XATTR_NTACL_NAME,				     acl, 				     (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);	return status;}/*  save the acl for a file into filesystem xattr*/NTSTATUS pvfs_acl_save(struct pvfs_state *pvfs, struct pvfs_filename *name, int fd,		       struct xattr_NTACL *acl){	NTSTATUS status;	void *privs;	if (!(pvfs->flags & PVFS_FLAG_XATTR_ENABLE)) {		return NT_STATUS_OK;	}	/* this xattr is in the "system" namespace, so we need	   admin privileges to set it */	privs = root_privileges();	status = pvfs_xattr_ndr_save(pvfs, name->full_name, fd, 				     XATTR_NTACL_NAME, 				     acl, 				     (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);	talloc_free(privs);	return status;}/*  create a zero length xattr with the given name*/NTSTATUS pvfs_xattr_create(struct pvfs_state *pvfs, 			   const char *fname, int fd,			   const char *attr_prefix,			   const char *attr_name){	NTSTATUS status;	DATA_BLOB blob = data_blob(NULL, 0);	char *aname = talloc_asprintf(NULL, "%s%s", attr_prefix, attr_name);	if (aname == NULL) {		return NT_STATUS_NO_MEMORY;	}	status = push_xattr_blob(pvfs, aname, fname, fd, &blob);	talloc_free(aname);	return status;}/*  delete a xattr with the given name*/NTSTATUS pvfs_xattr_delete(struct pvfs_state *pvfs, 			   const char *fname, int fd,			   const char *attr_prefix,			   const char *attr_name){	NTSTATUS status;	char *aname = talloc_asprintf(NULL, "%s%s", attr_prefix, attr_name);	if (aname == NULL) {		return NT_STATUS_NO_MEMORY;	}	status = delete_xattr(pvfs, aname, fname, fd);	talloc_free(aname);	return status;}/*  load a xattr with the given name*/NTSTATUS pvfs_xattr_load(struct pvfs_state *pvfs, 			 TALLOC_CTX *mem_ctx,			 const char *fname, int fd,			 const char *attr_prefix,			 const char *attr_name,			 size_t estimated_size,			 DATA_BLOB *blob){	NTSTATUS status;	char *aname = talloc_asprintf(mem_ctx, "%s%s", attr_prefix, attr_name);	if (aname == NULL) {		return NT_STATUS_NO_MEMORY;	}	status = pull_xattr_blob(pvfs, mem_ctx, aname, fname, fd, estimated_size, blob);	talloc_free(aname);	return status;}/*  save a xattr with the given name*/NTSTATUS pvfs_xattr_save(struct pvfs_state *pvfs, 			 const char *fname, int fd,			 const char *attr_prefix,			 const char *attr_name,			 const DATA_BLOB *blob){	NTSTATUS status;	char *aname = talloc_asprintf(NULL, "%s%s", attr_prefix, attr_name);	if (aname == NULL) {		return NT_STATUS_NO_MEMORY;	}	status = push_xattr_blob(pvfs, aname, fname, fd, blob);	talloc_free(aname);	return status;}/*  probe for system support for xattrs*/void pvfs_xattr_probe(struct pvfs_state *pvfs){	TALLOC_CTX *tmp_ctx = talloc_new(pvfs);	DATA_BLOB blob;	pull_xattr_blob(pvfs, tmp_ctx, "user.XattrProbe", pvfs->base_directory, 			-1, 1, &blob);	pull_xattr_blob(pvfs, tmp_ctx, "security.XattrProbe", pvfs->base_directory, 			-1, 1, &blob);	talloc_free(tmp_ctx);}

⌨️ 快捷键说明

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