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

📄 vfs_simple.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Unix SMB/CIFS implementation.   simple NTVFS filesystem backend   Copyright (C) Andrew Tridgell 2003   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/>.*//*  this implements a very simple NTVFS filesystem backend.     this backend largely ignores the POSIX -> CIFS mappings, just doing absolutely  minimal work to give a working backend.*/#include "includes.h"#include "system/dir.h"#include "system/filesys.h"#include "svfs.h"#include "system/time.h"#include "lib/util/dlinklist.h"#include "ntvfs/ntvfs.h"#include "ntvfs/simple/proto.h"#ifndef O_DIRECTORY#define O_DIRECTORY 0#endif#define CHECK_READ_ONLY(req) do { if (share_bool_option(ntvfs->ctx->config, SHARE_READONLY, true)) return NT_STATUS_ACCESS_DENIED; } while (0)/*  connect to a share - used when a tree_connect operation comes  in. For a disk based backend we needs to ensure that the base  directory exists (tho it doesn't need to be accessible by the user,  that comes later)*/static NTSTATUS svfs_connect(struct ntvfs_module_context *ntvfs,			     struct ntvfs_request *req, const char *sharename){	struct stat st;	struct svfs_private *private;	struct share_config *scfg = ntvfs->ctx->config;	private = talloc(ntvfs, struct svfs_private);	NT_STATUS_HAVE_NO_MEMORY(private);	private->ntvfs = ntvfs;	private->next_search_handle = 0;	private->connectpath = talloc_strdup(private, share_string_option(scfg, SHARE_PATH, ""));	private->open_files = NULL;	private->search = NULL;	/* the directory must exist */	if (stat(private->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {		DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", 			 private->connectpath, sharename));		return NT_STATUS_BAD_NETWORK_NAME;	}	ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);	ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);	ntvfs->private_data = private;	return NT_STATUS_OK;}/*  disconnect from a share*/static NTSTATUS svfs_disconnect(struct ntvfs_module_context *ntvfs){	return NT_STATUS_OK;}/*  find open file handle given fd*/static struct svfs_file *find_fd(struct svfs_private *private, struct ntvfs_handle *handle){	struct svfs_file *f;	void *p;	p = ntvfs_handle_get_backend_data(handle, private->ntvfs);	if (!p) return NULL;	f = talloc_get_type(p, struct svfs_file);	if (!f) return NULL;	return f;}/*  delete a file - the dirtype specifies the file types to include in the search.   The name can contain CIFS wildcards, but rarely does (except with OS/2 clients)*/static NTSTATUS svfs_unlink(struct ntvfs_module_context *ntvfs,			    struct ntvfs_request *req,			    union smb_unlink *unl){	char *unix_path;	CHECK_READ_ONLY(req);	unix_path = svfs_unix_path(ntvfs, req, unl->unlink.in.pattern);	/* ignoring wildcards ... */	if (unlink(unix_path) == -1) {		return map_nt_error_from_unix(errno);	}	return NT_STATUS_OK;}/*  ioctl interface - we don't do any*/static NTSTATUS svfs_ioctl(struct ntvfs_module_context *ntvfs,			   struct ntvfs_request *req, union smb_ioctl *io){	return NT_STATUS_INVALID_PARAMETER;}/*  check if a directory exists*/static NTSTATUS svfs_chkpath(struct ntvfs_module_context *ntvfs,			     struct ntvfs_request *req,			     union smb_chkpath *cp){	char *unix_path;	struct stat st;	unix_path = svfs_unix_path(ntvfs, req, cp->chkpath.in.path);	if (stat(unix_path, &st) == -1) {		return map_nt_error_from_unix(errno);	}	if (!S_ISDIR(st.st_mode)) {		return NT_STATUS_NOT_A_DIRECTORY;	}	return NT_STATUS_OK;}/*  build a file_id from a stat struct*/static uint64_t svfs_file_id(struct stat *st){	uint64_t ret = st->st_ino;	ret <<= 32;	ret |= st->st_dev;	return ret;}/*  approximately map a struct stat to a generic fileinfo struct*/static NTSTATUS svfs_map_fileinfo(struct ntvfs_module_context *ntvfs,				  struct ntvfs_request *req, union smb_fileinfo *info, 				  struct stat *st, const char *unix_path){	struct svfs_dir *dir = NULL;	char *pattern = NULL;	int i;	const char *s, *short_name;	s = strrchr(unix_path, '/');	if (s) {		short_name = s+1;	} else {		short_name = "";	}	asprintf(&pattern, "%s:*", unix_path);		if (pattern) {		dir = svfs_list_unix(req, req, pattern);	}	unix_to_nt_time(&info->generic.out.create_time, st->st_ctime);	unix_to_nt_time(&info->generic.out.access_time, st->st_atime);	unix_to_nt_time(&info->generic.out.write_time,  st->st_mtime);	unix_to_nt_time(&info->generic.out.change_time, st->st_mtime);	info->generic.out.alloc_size = st->st_size;	info->generic.out.size = st->st_size;	info->generic.out.attrib = svfs_unix_to_dos_attrib(st->st_mode);	info->generic.out.alloc_size = st->st_blksize * st->st_blocks;	info->generic.out.nlink = st->st_nlink;	info->generic.out.directory = S_ISDIR(st->st_mode) ? 1 : 0;	info->generic.out.file_id = svfs_file_id(st);	/* REWRITE: TODO stuff in here */	info->generic.out.delete_pending = 0;	info->generic.out.ea_size = 0;	info->generic.out.num_eas = 0;	info->generic.out.fname.s = talloc_strdup(req, short_name);	info->generic.out.alt_fname.s = talloc_strdup(req, short_name);	info->generic.out.compressed_size = 0;	info->generic.out.format = 0;	info->generic.out.unit_shift = 0;	info->generic.out.chunk_shift = 0;	info->generic.out.cluster_shift = 0;		info->generic.out.access_flags = 0;	info->generic.out.position = 0;	info->generic.out.mode = 0;	info->generic.out.alignment_requirement = 0;	info->generic.out.reparse_tag = 0;	info->generic.out.num_streams = 0;	/* setup a single data stream */	info->generic.out.num_streams = 1 + (dir?dir->count:0);	info->generic.out.streams = talloc_array(req, 						   struct stream_struct,						   info->generic.out.num_streams);	if (!info->generic.out.streams) {		return NT_STATUS_NO_MEMORY;	}	info->generic.out.streams[0].size = st->st_size;	info->generic.out.streams[0].alloc_size = st->st_size;	info->generic.out.streams[0].stream_name.s = talloc_strdup(req,"::$DATA");	for (i=0;dir && i<dir->count;i++) {		s = strchr(dir->files[i].name, ':');		info->generic.out.streams[1+i].size = dir->files[i].st.st_size;		info->generic.out.streams[1+i].alloc_size = dir->files[i].st.st_size;		info->generic.out.streams[1+i].stream_name.s = s?s:dir->files[i].name;	}	return NT_STATUS_OK;}/*  return info on a pathname*/static NTSTATUS svfs_qpathinfo(struct ntvfs_module_context *ntvfs,			       struct ntvfs_request *req, union smb_fileinfo *info){	char *unix_path;	struct stat st;	DEBUG(19,("svfs_qpathinfo: file %s level 0x%x\n", info->generic.in.file.path, info->generic.level));	if (info->generic.level != RAW_FILEINFO_GENERIC) {		return ntvfs_map_qpathinfo(ntvfs, req, info);	}		unix_path = svfs_unix_path(ntvfs, req, info->generic.in.file.path);	DEBUG(19,("svfs_qpathinfo: file %s\n", unix_path));	if (stat(unix_path, &st) == -1) {		DEBUG(19,("svfs_qpathinfo: file %s errno=%d\n", unix_path, errno));		return map_nt_error_from_unix(errno);	}	DEBUG(19,("svfs_qpathinfo: file %s, stat done\n", unix_path));	return svfs_map_fileinfo(ntvfs, req, info, &st, unix_path);}/*  query info on a open file*/static NTSTATUS svfs_qfileinfo(struct ntvfs_module_context *ntvfs,			       struct ntvfs_request *req, union smb_fileinfo *info){	struct svfs_private *private = ntvfs->private_data;	struct svfs_file *f;	struct stat st;	if (info->generic.level != RAW_FILEINFO_GENERIC) {		return ntvfs_map_qfileinfo(ntvfs, req, info);	}	f = find_fd(private, info->generic.in.file.ntvfs);	if (!f) {		return NT_STATUS_INVALID_HANDLE;	}		if (fstat(f->fd, &st) == -1) {		return map_nt_error_from_unix(errno);	}	return svfs_map_fileinfo(ntvfs, req,info, &st, f->name);}/*  open a file*/static NTSTATUS svfs_open(struct ntvfs_module_context *ntvfs,			  struct ntvfs_request *req, union smb_open *io){	struct svfs_private *private = ntvfs->private_data;	char *unix_path;	struct stat st;	int fd, flags;	struct svfs_file *f;	int create_flags, rdwr_flags;	bool readonly;	NTSTATUS status;	struct ntvfs_handle *handle;		if (io->generic.level != RAW_OPEN_GENERIC) {		return ntvfs_map_open(ntvfs, req, io);	}	readonly = share_bool_option(ntvfs->ctx->config, SHARE_READONLY, SHARE_READONLY_DEFAULT);	if (readonly) {		create_flags = 0;		rdwr_flags = O_RDONLY;	} else {		create_flags = O_CREAT;		rdwr_flags = O_RDWR;	}	unix_path = svfs_unix_path(ntvfs, req, io->ntcreatex.in.fname);	switch (io->generic.in.open_disposition) {	case NTCREATEX_DISP_SUPERSEDE:	case NTCREATEX_DISP_OVERWRITE_IF:		flags = create_flags | O_TRUNC;		break;	case NTCREATEX_DISP_OPEN:	case NTCREATEX_DISP_OVERWRITE:		flags = 0;		break;	case NTCREATEX_DISP_CREATE:		flags = create_flags | O_EXCL;		break;	case NTCREATEX_DISP_OPEN_IF:		flags = create_flags;		break;	default:		flags = 0;		break;	}		flags |= rdwr_flags;	if (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) {		flags = O_RDONLY | O_DIRECTORY;		if (readonly) {			goto do_open;		}		switch (io->generic.in.open_disposition) {		case NTCREATEX_DISP_CREATE:			if (mkdir(unix_path, 0755) == -1) {				DEBUG(9,("svfs_open: mkdir %s errno=%d\n", unix_path, errno));				return map_nt_error_from_unix(errno);			}			break;		case NTCREATEX_DISP_OPEN_IF:			if (mkdir(unix_path, 0755) == -1 && errno != EEXIST) {				DEBUG(9,("svfs_open: mkdir %s errno=%d\n", unix_path, errno));				return map_nt_error_from_unix(errno);			}			break;		}	}do_open:	fd = open(unix_path, flags, 0644);	if (fd == -1) {		return map_nt_error_from_unix(errno);	}	if (fstat(fd, &st) == -1) {		DEBUG(9,("svfs_open: fstat errno=%d\n", errno));		close(fd);		return map_nt_error_from_unix(errno);	}	status = ntvfs_handle_new(ntvfs, req, &handle);	NT_STATUS_NOT_OK_RETURN(status);	f = talloc(handle, struct svfs_file);	NT_STATUS_HAVE_NO_MEMORY(f);	f->fd = fd;	f->name = talloc_strdup(f, unix_path);	NT_STATUS_HAVE_NO_MEMORY(f->name);	DLIST_ADD(private->open_files, f);	status = ntvfs_handle_set_backend_data(handle, ntvfs, f);	NT_STATUS_NOT_OK_RETURN(status);	ZERO_STRUCT(io->generic.out);		unix_to_nt_time(&io->generic.out.create_time, st.st_ctime);	unix_to_nt_time(&io->generic.out.access_time, st.st_atime);	unix_to_nt_time(&io->generic.out.write_time,  st.st_mtime);	unix_to_nt_time(&io->generic.out.change_time, st.st_mtime);	io->generic.out.file.ntvfs = handle;	io->generic.out.alloc_size = st.st_size;	io->generic.out.size = st.st_size;	io->generic.out.attrib = svfs_unix_to_dos_attrib(st.st_mode);	io->generic.out.is_directory = S_ISDIR(st.st_mode) ? 1 : 0;	return NT_STATUS_OK;}/*  create a directory*/static NTSTATUS svfs_mkdir(struct ntvfs_module_context *ntvfs,			   struct ntvfs_request *req, union smb_mkdir *md){	char *unix_path;	CHECK_READ_ONLY(req);	if (md->generic.level != RAW_MKDIR_MKDIR) {		return NT_STATUS_INVALID_LEVEL;	}	unix_path = svfs_unix_path(ntvfs, req, md->mkdir.in.path);	if (mkdir(unix_path, 0777) == -1) {		return map_nt_error_from_unix(errno);	}	return NT_STATUS_OK;}/*  remove a directory*/static NTSTATUS svfs_rmdir(struct ntvfs_module_context *ntvfs,			   struct ntvfs_request *req, struct smb_rmdir *rd){	char *unix_path;	CHECK_READ_ONLY(req);	unix_path = svfs_unix_path(ntvfs, req, rd->in.path);	if (rmdir(unix_path) == -1) {		return map_nt_error_from_unix(errno);	}	return NT_STATUS_OK;}/*  rename a set of files*/static NTSTATUS svfs_rename(struct ntvfs_module_context *ntvfs,			    struct ntvfs_request *req, union smb_rename *ren){	char *unix_path1, *unix_path2;	CHECK_READ_ONLY(req);	if (ren->generic.level != RAW_RENAME_RENAME) {		return NT_STATUS_INVALID_LEVEL;	}	unix_path1 = svfs_unix_path(ntvfs, req, ren->rename.in.pattern1);	unix_path2 = svfs_unix_path(ntvfs, req, ren->rename.in.pattern2);	if (rename(unix_path1, unix_path2) == -1) {		return map_nt_error_from_unix(errno);	}		return NT_STATUS_OK;}/*  copy a set of files*/static NTSTATUS svfs_copy(struct ntvfs_module_context *ntvfs,			  struct ntvfs_request *req, struct smb_copy *cp){	return NT_STATUS_NOT_SUPPORTED;}/*  read from a file*/static NTSTATUS svfs_read(struct ntvfs_module_context *ntvfs,			  struct ntvfs_request *req, union smb_read *rd){	struct svfs_private *private = ntvfs->private_data;	struct svfs_file *f;	ssize_t ret;	if (rd->generic.level != RAW_READ_READX) {		return NT_STATUS_NOT_SUPPORTED;	}	f = find_fd(private, rd->readx.in.file.ntvfs);	if (!f) {		return NT_STATUS_INVALID_HANDLE;	}	ret = pread(f->fd, 		    rd->readx.out.data, 		    rd->readx.in.maxcnt,		    rd->readx.in.offset);	if (ret == -1) {		return map_nt_error_from_unix(errno);	}	rd->readx.out.nread = ret;	rd->readx.out.remaining = 0; /* should fill this in? */	rd->readx.out.compaction_mode = 0; 	return NT_STATUS_OK;}/*  write to a file*/static NTSTATUS svfs_write(struct ntvfs_module_context *ntvfs,			   struct ntvfs_request *req, union smb_write *wr){	struct svfs_private *private = ntvfs->private_data;	struct svfs_file *f;	ssize_t ret;	if (wr->generic.level != RAW_WRITE_WRITEX) {		return ntvfs_map_write(ntvfs, req, wr);	}	CHECK_READ_ONLY(req);	f = find_fd(private, wr->writex.in.file.ntvfs);	if (!f) {

⌨️ 快捷键说明

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