📄 linuxvfs.c
字号:
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 + -