📄 inode.c
字号:
/* * linux/fs/isofs/inode.c * * (C) 1991 Linus Torvalds - minix filesystem * 1992, 1993, 1994 Eric Youngdale Modified for ISO 9660 filesystem. * 1994 Eberhard Mönkeberg - multi session handling. * 1995 Mark Dobie - allow mounting of some weird VideoCDs and PhotoCDs. * 1997 Gordon Chaffee - Joliet CDs * 1998 Eric Lammerts - ISO 9660 Level 3 * 2004 Paul Serice - Inode Support pushed out from 4GB to 128GB * 2004 Paul Serice - NFS Export Operations */#include <linux/init.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/nls.h>#include <linux/ctype.h>#include <linux/smp_lock.h>#include <linux/statfs.h>#include <linux/cdrom.h>#include <linux/parser.h>#include "isofs.h"#include "zisofs.h"#define BEQUIETstatic int isofs_hashi(struct dentry *parent, struct qstr *qstr);static int isofs_hash(struct dentry *parent, struct qstr *qstr);static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);static int isofs_dentry_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);#ifdef CONFIG_JOLIETstatic int isofs_hashi_ms(struct dentry *parent, struct qstr *qstr);static int isofs_hash_ms(struct dentry *parent, struct qstr *qstr);static int isofs_dentry_cmpi_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);static int isofs_dentry_cmp_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);#endifstatic void isofs_put_super(struct super_block *sb){ struct isofs_sb_info *sbi = ISOFS_SB(sb);#ifdef CONFIG_JOLIET if (sbi->s_nls_iocharset) { unload_nls(sbi->s_nls_iocharset); sbi->s_nls_iocharset = NULL; }#endif kfree(sbi); sb->s_fs_info = NULL; return;}static void isofs_read_inode(struct inode *);static int isofs_statfs (struct dentry *, struct kstatfs *);static struct kmem_cache *isofs_inode_cachep;static struct inode *isofs_alloc_inode(struct super_block *sb){ struct iso_inode_info *ei; ei = kmem_cache_alloc(isofs_inode_cachep, GFP_KERNEL); if (!ei) return NULL; return &ei->vfs_inode;}static void isofs_destroy_inode(struct inode *inode){ kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode));}static void init_once(struct kmem_cache *cachep, void *foo){ struct iso_inode_info *ei = foo; inode_init_once(&ei->vfs_inode);}static int init_inodecache(void){ isofs_inode_cachep = kmem_cache_create("isofs_inode_cache", sizeof(struct iso_inode_info), 0, (SLAB_RECLAIM_ACCOUNT| SLAB_MEM_SPREAD), init_once); if (isofs_inode_cachep == NULL) return -ENOMEM; return 0;}static void destroy_inodecache(void){ kmem_cache_destroy(isofs_inode_cachep);}static int isofs_remount(struct super_block *sb, int *flags, char *data){ /* we probably want a lot more here */ *flags |= MS_RDONLY; return 0;}static const struct super_operations isofs_sops = { .alloc_inode = isofs_alloc_inode, .destroy_inode = isofs_destroy_inode, .read_inode = isofs_read_inode, .put_super = isofs_put_super, .statfs = isofs_statfs, .remount_fs = isofs_remount,};static struct dentry_operations isofs_dentry_ops[] = { { .d_hash = isofs_hash, .d_compare = isofs_dentry_cmp, }, { .d_hash = isofs_hashi, .d_compare = isofs_dentry_cmpi, },#ifdef CONFIG_JOLIET { .d_hash = isofs_hash_ms, .d_compare = isofs_dentry_cmp_ms, }, { .d_hash = isofs_hashi_ms, .d_compare = isofs_dentry_cmpi_ms, },#endif};struct iso9660_options{ char map; char rock; char joliet; char cruft; char hide; char showassoc; char nocompress; unsigned char check; unsigned int blocksize; mode_t mode; gid_t gid; uid_t uid; char *iocharset; unsigned char utf8; /* LVE */ s32 session; s32 sbsector;};/* * Compute the hash for the isofs name corresponding to the dentry. */static intisofs_hash_common(struct dentry *dentry, struct qstr *qstr, int ms){ const char *name; int len; len = qstr->len; name = qstr->name; if (ms) { while (len && name[len-1] == '.') len--; } qstr->hash = full_name_hash(name, len); return 0;}/* * Compute the hash for the isofs name corresponding to the dentry. */static intisofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms){ const char *name; int len; char c; unsigned long hash; len = qstr->len; name = qstr->name; if (ms) { while (len && name[len-1] == '.') len--; } hash = init_name_hash(); while (len--) { c = tolower(*name++); hash = partial_name_hash(c, hash); } qstr->hash = end_name_hash(hash); return 0;}/* * Case insensitive compare of two isofs names. */static int isofs_dentry_cmpi_common(struct dentry *dentry, struct qstr *a, struct qstr *b, int ms){ int alen, blen; /* A filename cannot end in '.' or we treat it like it has none */ alen = a->len; blen = b->len; if (ms) { while (alen && a->name[alen-1] == '.') alen--; while (blen && b->name[blen-1] == '.') blen--; } if (alen == blen) { if (strnicmp(a->name, b->name, alen) == 0) return 0; } return 1;}/* * Case sensitive compare of two isofs names. */static int isofs_dentry_cmp_common(struct dentry *dentry, struct qstr *a, struct qstr *b, int ms){ int alen, blen; /* A filename cannot end in '.' or we treat it like it has none */ alen = a->len; blen = b->len; if (ms) { while (alen && a->name[alen-1] == '.') alen--; while (blen && b->name[blen-1] == '.') blen--; } if (alen == blen) { if (strncmp(a->name, b->name, alen) == 0) return 0; } return 1;}static intisofs_hash(struct dentry *dentry, struct qstr *qstr){ return isofs_hash_common(dentry, qstr, 0);}static intisofs_hashi(struct dentry *dentry, struct qstr *qstr){ return isofs_hashi_common(dentry, qstr, 0);}static intisofs_dentry_cmp(struct dentry *dentry,struct qstr *a,struct qstr *b){ return isofs_dentry_cmp_common(dentry, a, b, 0);}static intisofs_dentry_cmpi(struct dentry *dentry,struct qstr *a,struct qstr *b){ return isofs_dentry_cmpi_common(dentry, a, b, 0);}#ifdef CONFIG_JOLIETstatic intisofs_hash_ms(struct dentry *dentry, struct qstr *qstr){ return isofs_hash_common(dentry, qstr, 1);}static intisofs_hashi_ms(struct dentry *dentry, struct qstr *qstr){ return isofs_hashi_common(dentry, qstr, 1);}static intisofs_dentry_cmp_ms(struct dentry *dentry,struct qstr *a,struct qstr *b){ return isofs_dentry_cmp_common(dentry, a, b, 1);}static intisofs_dentry_cmpi_ms(struct dentry *dentry,struct qstr *a,struct qstr *b){ return isofs_dentry_cmpi_common(dentry, a, b, 1);}#endifenum { Opt_block, Opt_check_r, Opt_check_s, Opt_cruft, Opt_gid, Opt_ignore, Opt_iocharset, Opt_map_a, Opt_map_n, Opt_map_o, Opt_mode, Opt_nojoliet, Opt_norock, Opt_sb, Opt_session, Opt_uid, Opt_unhide, Opt_utf8, Opt_err, Opt_nocompress, Opt_hide, Opt_showassoc,};static match_table_t tokens = { {Opt_norock, "norock"}, {Opt_nojoliet, "nojoliet"}, {Opt_unhide, "unhide"}, {Opt_hide, "hide"}, {Opt_showassoc, "showassoc"}, {Opt_cruft, "cruft"}, {Opt_utf8, "utf8"}, {Opt_iocharset, "iocharset=%s"}, {Opt_map_a, "map=acorn"}, {Opt_map_a, "map=a"}, {Opt_map_n, "map=normal"}, {Opt_map_n, "map=n"}, {Opt_map_o, "map=off"}, {Opt_map_o, "map=o"}, {Opt_session, "session=%u"}, {Opt_sb, "sbsector=%u"}, {Opt_check_r, "check=relaxed"}, {Opt_check_r, "check=r"}, {Opt_check_s, "check=strict"}, {Opt_check_s, "check=s"}, {Opt_uid, "uid=%u"}, {Opt_gid, "gid=%u"}, {Opt_mode, "mode=%u"}, {Opt_block, "block=%u"}, {Opt_ignore, "conv=binary"}, {Opt_ignore, "conv=b"}, {Opt_ignore, "conv=text"}, {Opt_ignore, "conv=t"}, {Opt_ignore, "conv=mtext"}, {Opt_ignore, "conv=m"}, {Opt_ignore, "conv=auto"}, {Opt_ignore, "conv=a"}, {Opt_nocompress, "nocompress"}, {Opt_err, NULL}};static int parse_options(char *options, struct iso9660_options *popt){ char *p; int option; popt->map = 'n'; popt->rock = 'y'; popt->joliet = 'y'; popt->cruft = 'n'; popt->hide = 'n'; popt->showassoc = 'n'; popt->check = 'u'; /* unset */ popt->nocompress = 0; popt->blocksize = 1024; popt->mode = S_IRUGO | S_IXUGO; /* * r-x for all. The disc could * be shared with DOS machines so * virtually anything could be * a valid executable. */ popt->gid = 0; popt->uid = 0; popt->iocharset = NULL; popt->utf8 = 0; popt->session=-1; popt->sbsector=-1; if (!options) return 1; while ((p = strsep(&options, ",")) != NULL) { int token; substring_t args[MAX_OPT_ARGS]; unsigned n; if (!*p) continue; token = match_token(p, tokens, args); switch (token) { case Opt_norock: popt->rock = 'n'; break; case Opt_nojoliet: popt->joliet = 'n'; break; case Opt_hide: popt->hide = 'y'; break; case Opt_unhide: case Opt_showassoc: popt->showassoc = 'y'; break; case Opt_cruft: popt->cruft = 'y'; break; case Opt_utf8: popt->utf8 = 1; break;#ifdef CONFIG_JOLIET case Opt_iocharset: popt->iocharset = match_strdup(&args[0]); break;#endif case Opt_map_a: popt->map = 'a'; break; case Opt_map_o: popt->map = 'o'; break; case Opt_map_n: popt->map = 'n'; break; case Opt_session: if (match_int(&args[0], &option)) return 0; n = option; if (n > 99) return 0; popt->session = n + 1; break; case Opt_sb: if (match_int(&args[0], &option)) return 0; popt->sbsector = option; break; case Opt_check_r: popt->check = 'r'; break; case Opt_check_s: popt->check = 's'; break; case Opt_ignore: break; case Opt_uid: if (match_int(&args[0], &option)) return 0; popt->uid = option; break; case Opt_gid: if (match_int(&args[0], &option)) return 0; popt->gid = option; break; case Opt_mode: if (match_int(&args[0], &option)) return 0; popt->mode = option; break; case Opt_block: if (match_int(&args[0], &option)) return 0; n = option; if (n != 512 && n != 1024 && n != 2048) return 0; popt->blocksize = n; break; case Opt_nocompress: popt->nocompress = 1; break; default: return 0; } } return 1;}/* * look if the driver can tell the multi session redirection value * * don't change this if you don't know what you do, please! * Multisession is legal only with XA disks. * A non-XA disk with more than one volume descriptor may do it right, but * usually is written in a nowhere standardized "multi-partition" manner. * Multisession uses absolute addressing (solely the first frame of the whole * track is #0), multi-partition uses relative addressing (each first frame of * each track is #0), and a track is not a session. * * A broken CDwriter software or drive firmware does not set new standards, * at least not if conflicting with the existing ones. * * emoenke@gwdg.de */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -