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

📄 linuxvfs.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
static void befs_put_link(struct dentry *dentry, struct nameidata *nd, void *p){	befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);	if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {		char *p = nd_get_link(nd);		if (!IS_ERR(p))			kfree(p);	}}/* * UTF-8 to NLS charset  convert routine *  * * Changed 8/10/01 by Will Dyson. Now use uni2char() / char2uni() rather than * the nls tables directly */static intbefs_utf2nls(struct super_block *sb, const char *in,	     int in_len, char **out, int *out_len){	struct nls_table *nls = BEFS_SB(sb)->nls;	int i, o;	wchar_t uni;	int unilen, utflen;	char *result;	/* The utf8->nls conversion won't make the final nls string bigger	 * than the utf one, but if the string is pure ascii they'll have the	 * same width and an extra char is needed to save the additional \0	 */	int maxlen = in_len + 1;	befs_debug(sb, "---> utf2nls()");	if (!nls) {		befs_error(sb, "befs_utf2nls called with no NLS table loaded");		return -EINVAL;	}	*out = result = kmalloc(maxlen, GFP_NOFS);	if (!*out) {		befs_error(sb, "befs_utf2nls() cannot allocate memory");		*out_len = 0;		return -ENOMEM;	}	for (i = o = 0; i < in_len; i += utflen, o += unilen) {		/* convert from UTF-8 to Unicode */		utflen = utf8_mbtowc(&uni, &in[i], in_len - i);		if (utflen < 0) {			goto conv_err;		}		/* convert from Unicode to nls */		unilen = nls->uni2char(uni, &result[o], in_len - o);		if (unilen < 0) {			goto conv_err;		}	}	result[o] = '\0';	*out_len = o;	befs_debug(sb, "<--- utf2nls()");	return o;      conv_err:	befs_error(sb, "Name using character set %s contains a character that "		   "cannot be converted to unicode.", nls->charset);	befs_debug(sb, "<--- utf2nls()");	kfree(result);	return -EILSEQ;}/** * befs_nls2utf - Convert NLS string to utf8 encodeing * @sb: Superblock * @src: Input string buffer in NLS format * @srclen: Length of input string in bytes * @dest: The output string in UTF-8 format * @destlen: Length of the output buffer *  * Converts input string @src, which is in the format of the loaded NLS map, * into a utf8 string. *  * The destination string @dest is allocated by this function and the caller is * responsible for freeing it with kfree() *  * On return, *@destlen is the length of @dest in bytes. * * On success, the return value is the number of utf8 characters written to * the output buffer @dest. *   * On Failure, a negative number coresponding to the error code is returned. */static intbefs_nls2utf(struct super_block *sb, const char *in,	     int in_len, char **out, int *out_len){	struct nls_table *nls = BEFS_SB(sb)->nls;	int i, o;	wchar_t uni;	int unilen, utflen;	char *result;	/* There're nls characters that will translate to 3-chars-wide UTF-8	 * characters, a additional byte is needed to save the final \0	 * in special cases */	int maxlen = (3 * in_len) + 1;	befs_debug(sb, "---> nls2utf()\n");	if (!nls) {		befs_error(sb, "befs_nls2utf called with no NLS table loaded.");		return -EINVAL;	}	*out = result = kmalloc(maxlen, GFP_NOFS);	if (!*out) {		befs_error(sb, "befs_nls2utf() cannot allocate memory");		*out_len = 0;		return -ENOMEM;	}	for (i = o = 0; i < in_len; i += unilen, o += utflen) {		/* convert from nls to unicode */		unilen = nls->char2uni(&in[i], in_len - i, &uni);		if (unilen < 0) {			goto conv_err;		}		/* convert from unicode to UTF-8 */		utflen = utf8_wctomb(&result[o], uni, 3);		if (utflen <= 0) {			goto conv_err;		}	}	result[o] = '\0';	*out_len = o;	befs_debug(sb, "<--- nls2utf()");	return i;      conv_err:	befs_error(sb, "Name using charecter set %s contains a charecter that "		   "cannot be converted to unicode.", nls->charset);	befs_debug(sb, "<--- nls2utf()");	kfree(result);	return -EILSEQ;}/** * Use the * */enum {	Opt_uid, Opt_gid, Opt_charset, Opt_debug, Opt_err,};static match_table_t befs_tokens = {	{Opt_uid, "uid=%d"},	{Opt_gid, "gid=%d"},	{Opt_charset, "iocharset=%s"},	{Opt_debug, "debug"},	{Opt_err, NULL}};static intparse_options(char *options, befs_mount_options * opts){	char *p;	substring_t args[MAX_OPT_ARGS];	int option;	/* Initialize options */	opts->uid = 0;	opts->gid = 0;	opts->use_uid = 0;	opts->use_gid = 0;	opts->iocharset = NULL;	opts->debug = 0;	if (!options)		return 1;	while ((p = strsep(&options, ",")) != NULL) {		int token;		if (!*p)			continue;		token = match_token(p, befs_tokens, args);		switch (token) {		case Opt_uid:			if (match_int(&args[0], &option))				return 0;			if (option < 0) {				printk(KERN_ERR "BeFS: Invalid uid %d, "						"using default\n", option);				break;			}			opts->uid = option;			opts->use_uid = 1;			break;		case Opt_gid:			if (match_int(&args[0], &option))				return 0;			if (option < 0) {				printk(KERN_ERR "BeFS: Invalid gid %d, "						"using default\n", option);				break;			}			opts->gid = option;			opts->use_gid = 1;			break;		case Opt_charset:			kfree(opts->iocharset);			opts->iocharset = match_strdup(&args[0]);			if (!opts->iocharset) {				printk(KERN_ERR "BeFS: allocation failure for "						"iocharset string\n");				return 0;			}			break;		case Opt_debug:			opts->debug = 1;			break;		default:			printk(KERN_ERR "BeFS: Unrecognized mount option \"%s\" "					"or missing value\n", p);			return 0;		}	}	return 1;}/* This function has the responsibiltiy of getting the * filesystem ready for unmounting.  * Basicly, we free everything that we allocated in * befs_read_inode */static voidbefs_put_super(struct super_block *sb){	kfree(BEFS_SB(sb)->mount_opts.iocharset);	BEFS_SB(sb)->mount_opts.iocharset = NULL;	if (BEFS_SB(sb)->nls) {		unload_nls(BEFS_SB(sb)->nls);		BEFS_SB(sb)->nls = NULL;	}	kfree(sb->s_fs_info);	sb->s_fs_info = NULL;	return;}/* Allocate private field of the superblock, fill it. * * Finish filling the public superblock fields * Make the root directory * Load a set of NLS translations if needed. */static intbefs_fill_super(struct super_block *sb, void *data, int silent){	struct buffer_head *bh;	befs_sb_info *befs_sb;	befs_super_block *disk_sb;	struct inode *root;	const unsigned long sb_block = 0;	const off_t x86_sb_off = 512;	sb->s_fs_info = kmalloc(sizeof (*befs_sb), GFP_KERNEL);	if (sb->s_fs_info == NULL) {		printk(KERN_ERR		       "BeFS(%s): Unable to allocate memory for private "		       "portion of superblock. Bailing.\n", sb->s_id);		goto unacquire_none;	}	befs_sb = BEFS_SB(sb);	memset(befs_sb, 0, sizeof(befs_sb_info));	if (!parse_options((char *) data, &befs_sb->mount_opts)) {		befs_error(sb, "cannot parse mount options");		goto unacquire_priv_sbp;	}	befs_debug(sb, "---> befs_fill_super()");#ifndef CONFIG_BEFS_RW	if (!(sb->s_flags & MS_RDONLY)) {		befs_warning(sb,			     "No write support. Marking filesystem read-only");		sb->s_flags |= MS_RDONLY;	}#endif				/* CONFIG_BEFS_RW */	/*	 * Set dummy blocksize to read super block.	 * Will be set to real fs blocksize later.	 *	 * Linux 2.4.10 and later refuse to read blocks smaller than	 * the hardsect size for the device. But we also need to read at 	 * least 1k to get the second 512 bytes of the volume.	 * -WD 10-26-01	 */ 	sb_min_blocksize(sb, 1024);	if (!(bh = sb_bread(sb, sb_block))) {		befs_error(sb, "unable to read superblock");		goto unacquire_priv_sbp;	}	/* account for offset of super block on x86 */	disk_sb = (befs_super_block *) bh->b_data;	if ((le32_to_cpu(disk_sb->magic1) == BEFS_SUPER_MAGIC1) ||	    (be32_to_cpu(disk_sb->magic1) == BEFS_SUPER_MAGIC1)) {		befs_debug(sb, "Using PPC superblock location");	} else {		befs_debug(sb, "Using x86 superblock location");		disk_sb =		    (befs_super_block *) ((void *) bh->b_data + x86_sb_off);	}	if (befs_load_sb(sb, disk_sb) != BEFS_OK)		goto unacquire_bh;	befs_dump_super_block(sb, disk_sb);	brelse(bh);	if (befs_check_sb(sb) != BEFS_OK)		goto unacquire_priv_sbp;	if( befs_sb->num_blocks > ~((sector_t)0) ) {		befs_error(sb, "blocks count: %Lu "			"is larger than the host can use",			befs_sb->num_blocks);		goto unacquire_priv_sbp;	}	/*	 * set up enough so that it can read an inode	 * Fill in kernel superblock fields from private sb	 */	sb->s_magic = BEFS_SUPER_MAGIC;	/* Set real blocksize of fs */	sb_set_blocksize(sb, (ulong) befs_sb->block_size);	sb->s_op = (struct super_operations *) &befs_sops;	root = iget(sb, iaddr2blockno(sb, &(befs_sb->root_dir)));	sb->s_root = d_alloc_root(root);	if (!sb->s_root) {		iput(root);		befs_error(sb, "get root inode failed");		goto unacquire_priv_sbp;	}	/* load nls library */	if (befs_sb->mount_opts.iocharset) {		befs_debug(sb, "Loading nls: %s",			   befs_sb->mount_opts.iocharset);		befs_sb->nls = load_nls(befs_sb->mount_opts.iocharset);		if (!befs_sb->nls) {			befs_warning(sb, "Cannot load nls %s"					" loading default nls",					befs_sb->mount_opts.iocharset);			befs_sb->nls = load_nls_default();		}	/* load default nls if none is specified  in mount options */	} else {		befs_debug(sb, "Loading default nls");		befs_sb->nls = load_nls_default();	}	return 0;/*****************/      unacquire_bh:	brelse(bh);      unacquire_priv_sbp:	kfree(sb->s_fs_info);      unacquire_none:	sb->s_fs_info = NULL;	return -EINVAL;}static intbefs_remount(struct super_block *sb, int *flags, char *data){	if (!(*flags & MS_RDONLY))		return -EINVAL;	return 0;}static intbefs_statfs(struct dentry *dentry, struct kstatfs *buf){	struct super_block *sb = dentry->d_sb;	befs_debug(sb, "---> befs_statfs()");	buf->f_type = BEFS_SUPER_MAGIC;	buf->f_bsize = sb->s_blocksize;	buf->f_blocks = BEFS_SB(sb)->num_blocks;	buf->f_bfree = BEFS_SB(sb)->num_blocks - BEFS_SB(sb)->used_blocks;	buf->f_bavail = buf->f_bfree;	buf->f_files = 0;	/* UNKNOWN */	buf->f_ffree = 0;	/* UNKNOWN */	buf->f_namelen = BEFS_NAME_LEN;	befs_debug(sb, "<--- befs_statfs()");	return 0;}static intbefs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name,	    void *data, struct vfsmount *mnt){	return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super,			   mnt);}static struct file_system_type befs_fs_type = {	.owner		= THIS_MODULE,	.name		= "befs",	.get_sb		= befs_get_sb,	.kill_sb	= kill_block_super,	.fs_flags	= FS_REQUIRES_DEV,	};static int __initinit_befs_fs(void){	int err;	printk(KERN_INFO "BeFS version: %s\n", BEFS_VERSION);	err = befs_init_inodecache();	if (err)		goto unacquire_none;	err = register_filesystem(&befs_fs_type);	if (err)		goto unacquire_inodecache;	return 0;unacquire_inodecache:	befs_destroy_inodecache();unacquire_none:	return err;}static void __exitexit_befs_fs(void){	befs_destroy_inodecache();	unregister_filesystem(&befs_fs_type);}/*Macros that typecheck the init and exit functions,ensures that they are called at init and cleanup,and eliminates warnings about unused functions.*/module_init(init_befs_fs)module_exit(exit_befs_fs)

⌨️ 快捷键说明

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