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

📄 ntfs-3g.c

📁 LINUX下读写NTFS分区的工具。 已经集成了通过LIBCONV库支持中文的代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
/** * ntfs-3g - Third Generation NTFS Driver * * Copyright (c) 2005-2007 Yura Pakhuchiy * Copyright (c) 2005 Yuval Fledel * Copyright (c) 2006-2008 Szabolcs Szakacsits * * This file is originated from the Linux-NTFS project. * * 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 (in the main directory of the NTFS-3G * distribution in the file COPYING); if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "config.h"#include <fuse.h>#if !defined(FUSE_VERSION) || (FUSE_VERSION < 26)#error "***********************************************************"#error "*                                                         *"#error "*     Compilation requires at least FUSE version 2.6.0!   *"#error "*                                                         *"#error "***********************************************************"#endif#ifdef FUSE_INTERNAL#define FUSE_TYPE	"integrated FUSE"#else#define FUSE_TYPE	"external FUSE"#endif#ifdef HAVE_STDIO_H#include <stdio.h>#endif#ifdef HAVE_STRING_H#include <string.h>#endif#ifdef HAVE_ERRNO_H#include <errno.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_LOCALE_H#include <locale.h>#endif#include <signal.h>#ifdef HAVE_LIMITS_H#include <limits.h>#endif#include <getopt.h>#include <syslog.h>#include <sys/wait.h>#ifdef HAVE_SETXATTR#include <sys/xattr.h>#endif#include "attrib.h"#include "inode.h"#include "volume.h"#include "dir.h"#include "unistr.h"#include "layout.h"#include "index.h"#include "utils.h"#include "version.h"#include "ntfstime.h"#include "misc.h"#ifndef PATH_MAX#define PATH_MAX 4096#endiftypedef enum {	FSTYPE_NONE,	FSTYPE_UNKNOWN,	FSTYPE_FUSE,	FSTYPE_FUSEBLK} fuse_fstype;typedef enum {	ATIME_ENABLED,	ATIME_DISABLED,	ATIME_RELATIVE} ntfs_atime_t;typedef struct {	fuse_fill_dir_t filler;	void *buf;} ntfs_fuse_fill_context_t;typedef enum {	NF_STREAMS_INTERFACE_NONE,	/* No access to named data streams. */	NF_STREAMS_INTERFACE_XATTR,	/* Map named data streams to xattrs. */	NF_STREAMS_INTERFACE_WINDOWS,	/* "file:stream" interface. */} ntfs_fuse_streams_interface;typedef struct {	ntfs_volume *vol;	unsigned int uid;	unsigned int gid;	unsigned int fmask;	unsigned int dmask;	ntfs_fuse_streams_interface streams;	ntfs_atime_t atime;	BOOL ro;	BOOL show_sys_files;	BOOL silent;	BOOL force;	BOOL hiberfile;	BOOL debug;	BOOL no_detach;	BOOL blkdev;	BOOL mounted;	struct fuse_chan *fc;} ntfs_fuse_context_t;static struct options {	char	*mnt_point;	/* Mount point */	char	*options;	/* Mount options */	char	*device;	/* Device to mount */} opts;static const char *EXEC_NAME = "ntfs-3g";static char def_opts[] = "silent,allow_other,nonempty,";static ntfs_fuse_context_t *ctx;static u32 ntfs_sequence;static const char *locale_msg ="WARNING: Couldn't set locale to '%s' thus some file names may not\n""         be correct or visible. Please see the potential solution at\n""         http://ntfs-3g.org/support.html#locale\n";static const char *usage_msg = "\n""%s %s %s %d - Third Generation NTFS Driver\n""\n""Copyright (C) 2006-2008 Szabolcs Szakacsits\n""Copyright (C) 2005-2007 Yura Pakhuchiy\n""\n""Usage:    %s <device|image_file> <mount_point> [-o option[,...]]\n""\n""Options:  ro (read-only mount), force, remove_hiberfile, locale=,\n" "          uid=, gid=, umask=, fmask=, dmask=, streams_interface=.\n""          Please see the details in the manual.\n""\n""Example:  ntfs-3g /dev/sda1 /mnt/win -o force\n""\n""%s";#ifdef FUSE_INTERNALint drop_privs(void);int restore_privs(void);#else/* * setuid and setgid root ntfs-3g denies to start with external FUSE,  * therefore the below functions are no-op in such case. */static int drop_privs(void)    { return 0; }static int restore_privs(void) { return 0; }static const char *setuid_msg ="Mount is denied because setuid and setgid root ntfs-3g is insecure with the\n""external FUSE library. Either remove the setuid/setgid bit from the binary\n""or rebuild NTFS-3G with integrated FUSE support and make it setuid root.\n""Please see more information at http://ntfs-3g.org/support.html#unprivileged\n";static const char *unpriv_fuseblk_msg ="Unprivileged user can not mount NTFS block devices using the external FUSE\n""library. Either mount the volume as root, or rebuild NTFS-3G with integrated\n""FUSE support and make it setuid root. Please see more information at\n""http://ntfs-3g.org/support.html#unprivileged\n";#endif	/** * ntfs_fuse_is_named_data_stream - check path to be to named data stream * @path:	path to check * * Returns 1 if path is to named data stream or 0 otherwise. */static int ntfs_fuse_is_named_data_stream(const char *path){	if (strchr(path, ':') && ctx->streams == NF_STREAMS_INTERFACE_WINDOWS)		return 1;	return 0;}static void ntfs_fuse_update_times(ntfs_inode *ni, ntfs_time_update_flags mask){	if (ctx->atime == ATIME_DISABLED)		mask &= ~NTFS_UPDATE_ATIME;	else if (ctx->atime == ATIME_RELATIVE && mask == NTFS_UPDATE_ATIME &&			ni->last_access_time >= ni->last_data_change_time &&			ni->last_access_time >= ni->last_mft_change_time)		return;	ntfs_inode_update_times(ni, mask);}static s64 ntfs_get_nr_free_mft_records(ntfs_volume *vol){	ntfs_attr *na = vol->mftbmp_na;	s64 nr_free = ntfs_attr_get_free_bits(na);	if (nr_free >= 0)		nr_free += (na->allocated_size - na->data_size) << 3;	return nr_free;}/** * ntfs_fuse_statfs - return information about mounted NTFS volume * @path:	ignored (but fuse requires it) * @sfs:	statfs structure in which to return the information * * Return information about the mounted NTFS volume @sb in the statfs structure * pointed to by @sfs (this is initialized with zeros before ntfs_statfs is * called). We interpret the values to be correct of the moment in time at * which we are called. Most values are variable otherwise and this isn't just * the free values but the totals as well. For example we can increase the * total number of file nodes if we run out and we can keep doing this until * there is no more space on the volume left at all. * * This code based on ntfs_statfs from ntfs kernel driver. * * Returns 0 on success or -errno on error. */static int ntfs_fuse_statfs(const char *path __attribute__((unused)),			    struct statvfs *sfs){	s64 size;	int delta_bits;	ntfs_volume *vol;	vol = ctx->vol;	if (!vol)		return -ENODEV;		/* File system block size, used for optimal transfer block size. */	sfs->f_bsize = vol->cluster_size;		/* Fundamental file system block size, used as the unit. */	sfs->f_frsize = vol->cluster_size;		/*	 * Total number of blocks on file system in units of f_frsize.	 * Since inodes are also stored in blocks ($MFT is a file) hence	 * this is the number of clusters on the volume.	 */	sfs->f_blocks = vol->nr_clusters;		/* Free blocks available for all and for non-privileged processes. */	size = vol->free_clusters;	if (size < 0)		size = 0;	sfs->f_bavail = sfs->f_bfree = size;		/* Free inodes on the free space */	delta_bits = vol->cluster_size_bits - vol->mft_record_size_bits;	if (delta_bits >= 0)		size <<= delta_bits;	else		size >>= -delta_bits;		/* Number of inodes at this point in time. */	sfs->f_files = (vol->mftbmp_na->allocated_size << 3) + size;		/* Free inodes available for all and for non-privileged processes. */	size += vol->free_mft_records;	if (size < 0)		size = 0;	sfs->f_ffree = sfs->f_favail = size;		/* Maximum length of filenames. */	sfs->f_namemax = NTFS_MAX_NAME_LEN;	return 0;}/** * ntfs_fuse_parse_path - split path to path and stream name. * @org_path:		path to split * @path:		pointer to buffer in which parsed path saved * @stream_name:	pointer to buffer where stream name in unicode saved * * This function allocates buffers for @*path and @*stream, user must free them * after use. * * Return values: *	<0	Error occurred, return -errno; *	 0	No stream name, @*stream is not allocated and set to AT_UNNAMED. *	>0	Stream name length in unicode characters. */static int ntfs_fuse_parse_path(const char *org_path, char **path,		ntfschar **stream_name){	char *stream_name_mbs;	int res;	stream_name_mbs = strdup(org_path);	if (!stream_name_mbs)		return -errno;	if (ctx->streams == NF_STREAMS_INTERFACE_WINDOWS) {		*path = strsep(&stream_name_mbs, ":");		if (stream_name_mbs) {			*stream_name = NULL;			res = ntfs_mbstoucs(stream_name_mbs, stream_name);			if (res < 0)				return -errno;			return res;		}	} else		*path = stream_name_mbs;	*stream_name = AT_UNNAMED;	return 0;}static void set_fuse_error(int *err){	if (!*err)		*err = -errno;}static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf){	int res = 0;	ntfs_inode *ni;	ntfs_attr *na;	ntfs_volume *vol;	char *path = NULL;	ntfschar *stream_name;	int stream_name_len;	vol = ctx->vol;	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);	if (stream_name_len < 0)		return stream_name_len;	memset(stbuf, 0, sizeof(struct stat));	ni = ntfs_pathname_to_inode(vol, NULL, path);	if (!ni) {		res = -errno;		goto exit;	}	if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY && !stream_name_len) {		/* Directory. */		stbuf->st_mode = S_IFDIR | (0777 & ~ctx->dmask);		na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4);		if (na) {			stbuf->st_size = na->data_size;			stbuf->st_blocks = na->allocated_size >> 9;			ntfs_attr_close(na);		}		stbuf->st_nlink = 1;	/* Make find(1) work */	} else {		/* Regular or Interix (INTX) file. */		stbuf->st_mode = S_IFREG;		stbuf->st_size = ni->data_size;		/* 		 * Temporary fix to make ActiveSync work via Samba 3.0.		 * See more on the ntfs-3g-devel list.		 */		stbuf->st_blocks = (ni->allocated_size + 511) >> 9;		stbuf->st_nlink = le16_to_cpu(ni->mrec->link_count);		if (ni->flags & FILE_ATTR_SYSTEM || stream_name_len) {			na = ntfs_attr_open(ni, AT_DATA, stream_name,					stream_name_len);			if (!na) {				if (stream_name_len)					res = -ENOENT;				goto exit;			}			if (stream_name_len) {				stbuf->st_size = na->data_size;				stbuf->st_blocks = na->allocated_size >> 9;			}			/* Check whether it's Interix FIFO or socket. */			if (!(ni->flags & FILE_ATTR_HIDDEN) &&					!stream_name_len) {				/* FIFO. */				if (na->data_size == 0)					stbuf->st_mode = S_IFIFO;				/* Socket link. */				if (na->data_size == 1)					stbuf->st_mode = S_IFSOCK;			}			/*			 * Check whether it's Interix symbolic link, block or			 * character device.			 */			if (na->data_size <= sizeof(INTX_FILE_TYPES) + 			    sizeof(ntfschar) * PATH_MAX && 			    na->data_size > sizeof(INTX_FILE_TYPES) && 			    !stream_name_len) {								INTX_FILE *intx_file;				intx_file = ntfs_malloc(na->data_size);				if (!intx_file) {					res = -errno;					ntfs_attr_close(na);					goto exit;				}				if (ntfs_attr_pread(na, 0, na->data_size,						intx_file) != na->data_size) {					res = -errno;					free(intx_file);					ntfs_attr_close(na);					goto exit;				}				if (intx_file->magic == INTX_BLOCK_DEVICE &&						na->data_size == offsetof(						INTX_FILE, device_end)) {					stbuf->st_mode = S_IFBLK;					stbuf->st_rdev = makedev(le64_to_cpu(							intx_file->major),							le64_to_cpu(							intx_file->minor));				}				if (intx_file->magic == INTX_CHARACTER_DEVICE &&						na->data_size == offsetof(						INTX_FILE, device_end)) {					stbuf->st_mode = S_IFCHR;					stbuf->st_rdev = makedev(le64_to_cpu(							intx_file->major),							le64_to_cpu(							intx_file->minor));				}				if (intx_file->magic == INTX_SYMBOLIC_LINK)					stbuf->st_mode = S_IFLNK;				free(intx_file);			}			ntfs_attr_close(na);		}		stbuf->st_mode |= (0777 & ~ctx->fmask);	}	stbuf->st_uid = ctx->uid;	stbuf->st_gid = ctx->gid;	stbuf->st_ino = ni->mft_no;	stbuf->st_atime = ni->last_access_time;	stbuf->st_ctime = ni->last_mft_change_time;	stbuf->st_mtime = ni->last_data_change_time;exit:	if (ntfs_inode_close(ni))		set_fuse_error(&res);	free(path);	if (stream_name_len)		free(stream_name);	return res;}static int ntfs_fuse_readlink(const char *org_path, char *buf, size_t buf_size){	char *path;	ntfschar *stream_name;	ntfs_inode *ni = NULL;	ntfs_attr *na = NULL;	INTX_FILE *intx_file = NULL;	int stream_name_len, res = 0;	/* Get inode. */	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);	if (stream_name_len < 0)		return stream_name_len;	if (stream_name_len > 0) {		res = -EINVAL;		goto exit;	}	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);	if (!ni) {		res = -errno;		goto exit;	}	/* Sanity checks. */	if (!(ni->flags & FILE_ATTR_SYSTEM)) {		res = -EINVAL;		goto exit;	}	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);	if (!na) {		res = -errno;		goto exit;	}	if (na->data_size <= sizeof(INTX_FILE_TYPES)) {		res = -EINVAL;		goto exit;	}	if (na->data_size > sizeof(INTX_FILE_TYPES) +			sizeof(ntfschar) * PATH_MAX) {		res = -ENAMETOOLONG;		goto exit;	}	/* Receive file content. */	intx_file = ntfs_malloc(na->data_size);	if (!intx_file) {		res = -errno;		goto exit;	}	if (ntfs_attr_pread(na, 0, na->data_size, intx_file) != na->data_size) {		res = -errno;		goto exit;	}	/* Sanity check. */	if (intx_file->magic != INTX_SYMBOLIC_LINK) {		res = -EINVAL;		goto exit;	}	/* Convert link from unicode to local encoding. */	if (ntfs_ucstombs(intx_file->target, (na->data_size -			offsetof(INTX_FILE, target)) / sizeof(ntfschar),			&buf, buf_size) < 0) {		res = -errno;		goto exit;	}exit:	if (intx_file)		free(intx_file);	if (na)		ntfs_attr_close(na);	if (ntfs_inode_close(ni))		set_fuse_error(&res);	free(path);	if (stream_name_len)		free(stream_name);	return res;}static int ntfs_fuse_filler(ntfs_fuse_fill_context_t *fill_ctx,		const ntfschar *name, const int name_len, const int name_type,		const s64 pos __attribute__((unused)), const MFT_REF mref,		const unsigned dt_type __attribute__((unused))){	char *filename = NULL;	int ret = 0;	if (name_type == FILE_NAME_DOS)		return 0;		if (ntfs_ucstombs(name, name_len, &filename, 0) < 0) {		ntfs_log_perror("Skipping unrepresentable filename (inode %llu)",				(unsigned long long)MREF(mref));		return 0;	}		if (ntfs_fuse_is_named_data_stream(filename)) {		ntfs_log_error("Unable to access '%s' (inode %llu) with "				"current named streams access interface.\n",				filename, (unsigned long long)MREF(mref));		free(filename);		return 0;	}		if (MREF(mref) == FILE_root || MREF(mref) >= FILE_first_user ||			ctx->show_sys_files) {		struct stat st = { .st_ino = MREF(mref) };		 		if (dt_type == NTFS_DT_REG)			st.st_mode = S_IFREG | (0777 & ~ctx->fmask);		else if (dt_type == NTFS_DT_DIR)			st.st_mode = S_IFDIR | (0777 & ~ctx->dmask); 				ret = fill_ctx->filler(fill_ctx->buf, filename, &st, 0);	}		free(filename);	return ret;}static int ntfs_fuse_readdir(const char *path, void *buf,		fuse_fill_dir_t filler, off_t offset __attribute__((unused)),

⌨️ 快捷键说明

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