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

📄 fs.c

📁 EM85XX读NTFS修正代码包
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * fs.c - NTFS driver for Linux 2.4.x * * Legato Systems, Inc. (http://www.legato.com) have sponsored Anton * Altaparmakov to develop NTFS on Linux since June 2001. * * Copyright (C) 1995-1997, 1999 Martin von L鰓is * Copyright (C) 1996 Richard Russon * Copyright (C) 1996-1997 R間is Duchesne * Copyright (C) 2000-2001, Anton Altaparmakov (AIA) */#include <linux/config.h>#include <linux/errno.h>#include "ntfstypes.h"#include "struct.h"#include "util.h"#include "inode.h"#include "super.h"#include "dir.h"#include "support.h"#include "macros.h"#include "sysctl.h"#include "attr.h"#include <linux/module.h>#include <asm/uaccess.h>#include <linux/locks.h>#include <linux/init.h>#include <linux/smp_lock.h>#include <linux/blkdev.h>#include <asm/page.h>#include <linux/nls.h>#include <linux/ntfs_fs.h>/* Forward declarations. */static struct inode_operations ntfs_dir_inode_operations;static struct file_operations ntfs_dir_operations;#define ITEM_SIZE 2040/* Io functions to user space. */static void ntfs_putuser(ntfs_io* dest, void *src, ntfs_size_t len){	copy_to_user(dest->param, src, len);	dest->param += len;}#ifdef CONFIG_NTFS_RWstruct ntfs_getuser_update_vm_s {	const char *user;	struct inode *ino;	loff_t off;};static void ntfs_getuser_update_vm(void *dest, ntfs_io *src, ntfs_size_t len){	struct ntfs_getuser_update_vm_s *p = src->param;		copy_from_user(dest, p->user, len);	p->user += len;	p->off += len;}#endif/* loff_t is 64 bit signed, so is cool. */static ssize_t ntfs_read(struct file *filp, char *buf, size_t count,loff_t *off){	int error;	ntfs_io io;	ntfs_attribute *attr;	ntfs_inode *ino = NTFS_LINO2NINO(filp->f_dentry->d_inode);	/* Inode is not properly initialized. */	if (!ino)		return -EINVAL;	ntfs_debug(DEBUG_OTHER, "ntfs_read %x, %Lx, %x ->",		   (unsigned)ino->i_number, (unsigned long long)*off,		   (unsigned)count);	attr = ntfs_find_attr(ino, ino->vol->at_data, NULL);	/* Inode has no unnamed data attribute. */	if (!attr) {		ntfs_debug(DEBUG_OTHER, "ntfs_read: $DATA not found!\n");		return -EINVAL;	}	if (attr->flags & ATTR_IS_ENCRYPTED)		return -EACCES;	/* Read the data. */	io.fn_put = ntfs_putuser;	io.fn_get = 0;	io.param = buf;	io.size = count;	error = ntfs_read_attr(ino, ino->vol->at_data, NULL, *off, &io);	if (error && !io.size) {		ntfs_debug(DEBUG_OTHER, "ntfs_read: read_attr failed with "				"error %i, io size %u.\n", error, io.size);		return error;	}	*off += io.size;	ntfs_debug(DEBUG_OTHER, "ntfs_read: finished. read %u bytes.\n",								io.size);	return io.size;}#ifdef CONFIG_NTFS_RWstatic ssize_t ntfs_write(struct file *filp, const char *buf, size_t count,		loff_t *pos){	int err;	struct inode *vfs_ino = filp->f_dentry->d_inode;	ntfs_inode *ntfs_ino = NTFS_LINO2NINO(vfs_ino);	ntfs_attribute *data;	ntfs_io io;	struct ntfs_getuser_update_vm_s param;	if (!ntfs_ino)		return -EINVAL;	ntfs_debug(DEBUG_LINUX, "%s(): Entering for inode 0x%lx, *pos 0x%Lx, "			"count 0x%x.\n", __FUNCTION__, ntfs_ino->i_number,			*pos, count);	/* Allows to lock fs ro at any time. */	if (vfs_ino->i_sb->s_flags & MS_RDONLY)		return -EROFS;	data = ntfs_find_attr(ntfs_ino, ntfs_ino->vol->at_data, NULL);	if (!data)		return -EINVAL;	/* Evaluating O_APPEND is the file system's job... */	if (filp->f_flags & O_APPEND)		*pos = vfs_ino->i_size;	if (!data->resident && *pos + count > data->allocated) {		err = ntfs_extend_attr(ntfs_ino, data, *pos + count);		if (err < 0)			return err;	}	param.user = buf;	param.ino = vfs_ino;	param.off = *pos;	io.fn_put = 0;	io.fn_get = ntfs_getuser_update_vm;	io.param = &param;	io.size = count;	io.do_read = 0;	err = ntfs_readwrite_attr(ntfs_ino, data, *pos, &io);	ntfs_debug(DEBUG_LINUX, "%s(): Returning %i\n", __FUNCTION__, -err);	if (!err) {		*pos += io.size;		if (*pos > vfs_ino->i_size)			vfs_ino->i_size = *pos;		mark_inode_dirty(vfs_ino);		return io.size;	}	return err;}#endifstruct ntfs_filldir {	struct inode *dir;	filldir_t filldir;	unsigned int type;	u32 ph, pl;	void *dirent;	char *name;	int namelen;	int ret_code;};static int ntfs_printcb(ntfs_u8 *entry, void *param){	unsigned long inum = NTFS_GETU64(entry) & 0xffffffffffff;	struct ntfs_filldir *nf = param;	u32 flags = NTFS_GETU32(entry + 0x48);	char show_sys_files = 0;	u8 name_len = NTFS_GETU8(entry + 0x50);	u8 name_type = NTFS_GETU8(entry + 0x51);	int err;	unsigned file_type;	switch (nf->type) {	case ngt_dos:		/* Don't display long names. */		if (!(name_type & 2))			return 0;		break;	case ngt_nt:		/* Don't display short-only names. */		if ((name_type & 3) == 2)			return 0;		break;	case ngt_posix:		break;	case ngt_full:		show_sys_files = 1;		break;	default:		BUG();	}	err = ntfs_encodeuni(NTFS_INO2VOL(nf->dir), (ntfs_u16*)(entry + 0x52),			name_len, &nf->name, &nf->namelen);	if (err) {		ntfs_debug(DEBUG_OTHER, "%s(): Skipping unrepresentable "				"file.\n", __FUNCTION__);		err = 0;		goto err_noname;	}	if (!show_sys_files && inum < 0x10UL) {		ntfs_debug(DEBUG_OTHER, "%s(): Skipping system file (%s).\n",				__FUNCTION__, nf->name);		err = 0;		goto err_ret;	}	/* Do not return ".", as this is faked. */	if (nf->namelen == 1 && nf->name[0] == '.') {		ntfs_debug(DEBUG_OTHER, "%s(): Skipping \".\"\n", __FUNCTION__);		err = 0;		goto err_ret;	}	nf->name[nf->namelen] = 0;	if (flags & 0x10000000) /* FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT */		file_type = DT_DIR;	else		file_type = DT_REG;	ntfs_debug(DEBUG_OTHER, "%s(): Calling filldir for %s with "			"len %i, f_pos 0x%Lx, inode %lu, %s.\n", __FUNCTION__,			nf->name, nf->namelen, (loff_t)(nf->ph << 16) | nf->pl,			inum, file_type == DT_DIR ? "DT_DIR" : "DT_REG");	/*	 * Userspace side of filldir expects an off_t rather than an loff_t.	 * And it also doesn't like the most significant bit being set as it	 * then considers the value to be negative. Thus this implementation	 * limits the number of index records to 32766, which should be plenty.	 */	err = nf->filldir(nf->dirent, nf->name, nf->namelen,			(loff_t)(nf->ph << 16) | nf->pl, inum, file_type);	if (err)		nf->ret_code = err;err_ret:	ntfs_free(nf->name);err_noname:	nf->namelen = 0;	nf->name = NULL;	return err;}/* * readdir returns '.', then '..', then the directory entries in sequence. * As the root directory contains an entry for itself, '.' is not emulated for * the root directory. */static int ntfs_readdir(struct file* filp, void *dirent, filldir_t filldir){	struct inode *dir = filp->f_dentry->d_inode;	int err;	struct ntfs_filldir cb;	cb.ret_code = 0;	cb.pl = filp->f_pos & 0xffff;	cb.ph = (filp->f_pos >> 16) & 0x7fff;	filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;	ntfs_debug(DEBUG_OTHER, "%s(): Entering for inode %lu, f_pos 0x%Lx, "			"i_mode 0x%x, i_count %lu.\n", __FUNCTION__,			dir->i_ino, filp->f_pos, (unsigned int)dir->i_mode,			atomic_read(&dir->i_count));	if (!cb.ph) {		/* Start of directory. Emulate "." and "..". */		if (!cb.pl) {			ntfs_debug(DEBUG_OTHER, "%s(): Calling filldir for . "				    "with len 1, f_pos 0x%Lx, inode %lu, "				    "DT_DIR.\n", __FUNCTION__, filp->f_pos,				    dir->i_ino);			cb.ret_code = filldir(dirent, ".", 1, filp->f_pos,				    dir->i_ino, DT_DIR);			if (cb.ret_code)				goto done;			cb.pl++;			filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;		}		if (cb.pl == (u32)1) {			ntfs_debug(DEBUG_OTHER, "%s(): Calling filldir for .. "				    "with len 2, f_pos 0x%Lx, inode %lu, "				    "DT_DIR.\n", __FUNCTION__, filp->f_pos,				    filp->f_dentry->d_parent->d_inode->i_ino);			cb.ret_code = filldir(dirent, "..", 2, filp->f_pos,				    filp->f_dentry->d_parent->d_inode->i_ino,				    DT_DIR);			if (cb.ret_code)				goto done;			cb.pl++;			filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;		}	} else if (cb.ph >= 0x7fff)		/* End of directory. */		goto done;	cb.dir = dir;	cb.filldir = filldir;	cb.dirent = dirent;	cb.type = NTFS_INO2VOL(dir)->ngt;	do {		ntfs_debug(DEBUG_OTHER, "%s(): Looking for next file using "				"ntfs_getdir_unsorted(), f_pos 0x%Lx.\n",				__FUNCTION__, (loff_t)(cb.ph << 16) | cb.pl);		err = ntfs_getdir_unsorted(NTFS_LINO2NINO(dir), &cb.ph, &cb.pl,				ntfs_printcb, &cb);	} while (!err && !cb.ret_code && cb.ph < 0x7fff);	filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;	ntfs_debug(DEBUG_OTHER, "%s(): After ntfs_getdir_unsorted()"			" calls, f_pos 0x%Lx.\n", __FUNCTION__, filp->f_pos);	if (!err) {done:#ifdef DEBUG		if (!cb.ret_code)			ntfs_debug(DEBUG_OTHER, "%s(): EOD, f_pos 0x%Lx, "					"returning 0.\n", __FUNCTION__,					filp->f_pos);		else 			ntfs_debug(DEBUG_OTHER, "%s(): filldir returned %i, "					"returning 0, f_pos 0x%Lx.\n",					__FUNCTION__, cb.ret_code, filp->f_pos);#endif		return 0;	}	ntfs_debug(DEBUG_OTHER, "%s(): Returning %i, f_pos 0x%Lx.\n",			__FUNCTION__, err, filp->f_pos);	return err;}/* Copied from vfat driver. */static int simple_getbool(char *s, int *setval){	if (s) {		if (!strcmp(s, "1") || !strcmp(s, "yes") || !strcmp(s, "true"))			*setval = 1;		else if (!strcmp(s, "0") || !strcmp(s, "no") ||							!strcmp(s, "false"))			*setval = 0;		else			return 0;	} else		*setval = 1;	return 1;}/* * This needs to be outside parse_options() otherwise a remount will reset * these unintentionally. */static void init_ntfs_super_block(ntfs_volume* vol){	vol->uid = vol->gid = 0;	vol->umask = 0077;	vol->ngt = ngt_nt;	vol->nls_map = (void*)-1;	vol->mft_zone_multiplier = -1;}/* Parse the (re)mount options. */static int parse_options(ntfs_volume *vol, char *opt){	char *value;		/* Defaults if not specified and !remount. */	ntfs_uid_t uid = -1;	/* 0, root user only */	ntfs_gid_t gid = -1;	/* 0, root user only */	int umask = -1;		/* 0077, owner access only */	unsigned int ngt = -1;	/* ngt_nt */	void *nls_map = NULL;	/* Try to load the default NLS. */	int use_utf8 = -1;	/* If no NLS specified and loading the default				   NLS failed use utf8. */	int mft_zone_mul = -1;	/* 1 */	if (!opt)		goto done;	for (opt = strtok(opt, ","); opt; opt = strtok(NULL, ",")) {		if ((value = strchr(opt, '=')) != NULL)			*value ++= '\0';		if (strcmp(opt, "uid") == 0) {			if (!value || !*value)				goto needs_arg;			uid = simple_strtoul(value, &value, 0);			if (*value) {				printk(KERN_ERR "NTFS: uid invalid argument\n");				return 0;			}		} else if (strcmp(opt, "gid") == 0) {			if (!value || !*value)				goto needs_arg;			gid = simple_strtoul(value, &value, 0);			if (*value) {				printk(KERN_ERR "NTFS: gid invalid argument\n");				return 0;			}		} else if (strcmp(opt, "umask") == 0) {			if (!value || !*value)				goto needs_arg;

⌨️ 快捷键说明

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