?? inode.c
字號(hào):
/* * ROMFS file system, Linux implementation * * Copyright (C) 1997 Janos Farkas <chexum@shadow.banki.hu> * * Using parts of the minix filesystem * Copyright (C) 1991, 1992 Linus Torvalds * * and parts of the affs filesystem additionally * Copyright (C) 1993 Ray Burr * Copyright (C) 1996 Hans-Joachim Widmaier * * 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. * * Changes * Changed for 2.1.19 modules * Jan 1997 Initial release * Nov 1997 2.0.32 Merging applicable 2.1 bugfixes *//* todo: * - see Documentation/filesystems/romfs.txt * - use malloced memory for file names? * - quicklist routines from fs/namei.c, get_page is possibly not * intended to be used now * - considering write access... * - network (tftp) files? * - in the ancient times something leaked to made umounts * impossible, but I've not seen it in the last months *//* * Sorry about some optimizations and for some goto's. I just wanted * to squeeze some more bytes out of this code.. :) */#include <linux/module.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/malloc.h>#include <linux/romfs_fs.h>#include <linux/fs.h>#include <linux/locks.h>#include <asm/byteorder.h>static int inline min(int a, int b){ return a<b ? a : b;}static __s32romfs_checksum(void *data, int size){ __s32 sum, *ptr; sum = 0; ptr = data; size>>=2; while (size>0) { sum += ntohl(*ptr++); size--; } return sum;}static struct super_operations romfs_ops;static struct super_block *romfs_read_super(struct super_block *s, void *data, int silent){ struct buffer_head *bh; kdev_t dev = s->s_dev; struct romfs_super_block *rsb; int sz; MOD_INC_USE_COUNT; /* I would parse the options here, but there are none.. :) */ lock_super(s); set_blocksize(dev, ROMBSIZE); s->s_blocksize = ROMBSIZE; s->s_blocksize_bits = ROMBSBITS; bh = bread(dev, 0, ROMBSIZE); if (!bh) { /* XXX merge with other printk? */ printk ("romfs: unable to read superblock\n"); goto outnobh; } rsb = (struct romfs_super_block *)bh->b_data; sz = ntohl(rsb->size);#if 0 printk("romfs_read_super: b_data %x, sz %d, word0 %x, word1 %x\n", bh->b_data, sz, rsb->word0, rsb->word1);#endif if (rsb->word0 != ROMSB_WORD0 || rsb->word1 != ROMSB_WORD1 || sz < ROMFH_SIZE) { if (!silent) printk ("VFS: Can't find a romfs filesystem on dev " "%s.\n", kdevname(dev)); goto out; } if (romfs_checksum(rsb, min(sz,512))) { printk ("romfs: bad initial checksum on dev " "%s.\n", kdevname(dev)); goto out; } s->s_magic = ROMFS_MAGIC; s->u.romfs_sb.s_maxsize = sz; s->s_flags |= MS_RDONLY; /* Find the start of the fs */ sz = (ROMFH_SIZE + strnlen(rsb->name, ROMFS_MAXFN) + 1 + ROMFH_PAD) & ROMFH_MASK; brelse(bh); s->s_op = &romfs_ops; if (!(s->s_mounted = iget(s, sz))) goto outnobh; unlock_super(s); /* Ehrhm; sorry.. :) And thanks to Hans-Joachim Widmaier :) */ if (0) {out: brelse(bh);outnobh: s->s_dev = 0; unlock_super(s); MOD_DEC_USE_COUNT; s = NULL; } return s;}/* Nothing to do.. */static voidromfs_put_super(struct super_block *sb){ lock_super(sb); sb->s_dev = 0; unlock_super(sb); MOD_DEC_USE_COUNT; return;}/* That's simple too. */static voidromfs_statfs(struct super_block *sb, struct statfs *buf, int bufsize){ struct statfs tmp; memset(&tmp, 0, sizeof(tmp)); tmp.f_type = ROMFS_MAGIC; tmp.f_bsize = ROMBSIZE; tmp.f_blocks = (sb->u.romfs_sb.s_maxsize+ROMBSIZE-1)>>ROMBSBITS; memcpy_tofs(buf, &tmp, bufsize);}/* some helper routines */static intromfs_strnlen(struct inode *i, unsigned long offset, unsigned long count){ struct buffer_head *bh; unsigned long avail, maxsize, res; maxsize = i->i_sb->u.romfs_sb.s_maxsize; if (offset >= maxsize) return -1; /* strnlen is almost always valid */ if (count > maxsize || offset+count > maxsize) count = maxsize-offset; bh = bread(i->i_dev, offset>>ROMBSBITS, ROMBSIZE); if (!bh) return -1; /* error */ avail = ROMBSIZE - (offset & ROMBMASK); maxsize = min(count, avail); res = strnlen(((char *)bh->b_data)+(offset&ROMBMASK), maxsize); brelse(bh); if (res < maxsize) return res; /* found all of it */ while (res < count) { offset += maxsize; bh = bread(i->i_dev, offset>>ROMBSBITS, ROMBSIZE); if (!bh) return -1; maxsize = min(count-res, ROMBSIZE); avail = strnlen(bh->b_data, maxsize); res += avail; brelse(bh); if (avail < maxsize) return res; } return res;}static intromfs_copyfrom(struct inode *i, void *dest, unsigned long offset, unsigned long count){ struct buffer_head *bh; unsigned long avail, maxsize, res; maxsize = i->i_sb->u.romfs_sb.s_maxsize; if (offset >= maxsize || count > maxsize || offset+count>maxsize) return -1; bh = bread(i->i_dev, offset>>ROMBSBITS, ROMBSIZE); if (!bh) return -1; /* error */ avail = ROMBSIZE - (offset & ROMBMASK); maxsize = min(count, avail); memcpy(dest, ((char *)bh->b_data) + (offset & ROMBMASK), maxsize); brelse(bh); res = maxsize; /* all of it */ while (res < count) { offset += maxsize; dest += maxsize; bh = bread(i->i_dev, offset>>ROMBSBITS, ROMBSIZE); if (!bh) return -1; maxsize = min(count-res, ROMBSIZE); memcpy(dest, bh->b_data, maxsize); brelse(bh); res += maxsize; } return res;}/* Directory operations */static intromfs_readdir(struct inode *i, struct file *filp, void *dirent, filldir_t filldir){ struct romfs_inode ri; unsigned long offset, maxoff; int j, ino, nextfh; int stored = 0; char fsname[ROMFS_MAXFN]; /* XXX dynamic? */ if (!i || !S_ISDIR(i->i_mode)) return -EBADF; maxoff = i->i_sb->u.romfs_sb.s_maxsize; offset = filp->f_pos; if (!offset) { offset = i->i_ino & ROMFH_MASK; if (romfs_copyfrom(i, &ri, offset, ROMFH_SIZE) <= 0) return stored; offset = ntohl(ri.spec) & ROMFH_MASK; } /* Not really failsafe, but we are read-only... */ for(;;) { if (!offset || offset >= maxoff) { offset = 0xffffffff; filp->f_pos = offset; return stored; } filp->f_pos = offset; /* Fetch inode info */ if (romfs_copyfrom(i, &ri, offset, ROMFH_SIZE) <= 0) return stored; j = romfs_strnlen(i, offset+ROMFH_SIZE, sizeof(fsname)-1); if (j < 0) return stored; fsname[j]=0; romfs_copyfrom(i, fsname, offset+ROMFH_SIZE, j); ino = offset; nextfh = ntohl(ri.next); if ((nextfh & ROMFH_TYPE) == ROMFH_HRD) ino = ntohl(ri.spec); if (filldir(dirent, fsname, j, offset, ino) < 0) { return stored; } stored++; offset = nextfh & ROMFH_MASK; }}static intromfs_lookup(struct inode *dir, const char *name, int len, struct inode **result){ unsigned long offset, maxoff; int fslen, res; char fsname[ROMFS_MAXFN]; /* XXX dynamic? */ struct romfs_inode ri; *result = NULL; if (!dir || !S_ISDIR(dir->i_mode)) { res = -EBADF; goto out; } offset = dir->i_ino & ROMFH_MASK; if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) { res = -ENOENT; goto out; } maxoff = dir->i_sb->u.romfs_sb.s_maxsize; offset = ntohl(ri.spec) & ROMFH_MASK; for(;;) { if (!offset || offset >= maxoff || romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) { res = -ENOENT; goto out; } /* try to match the first 16 bytes of name */ fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, ROMFH_SIZE); if (len < ROMFH_SIZE) { if (len == fslen) { /* both are shorter, and same size */ romfs_copyfrom(dir, fsname, offset+ROMFH_SIZE, len+1); if (strncmp (name, fsname, len) == 0) break; } } else if (fslen >= ROMFH_SIZE) { /* both are longer; XXX optimize max size */ fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, sizeof(fsname)-1); if (len == fslen) { romfs_copyfrom(dir, fsname, offset+ROMFH_SIZE, len+1); if (strncmp(name, fsname, len) == 0) break; } }
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -