diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
commit | 27cfca1ec98e91261b1a5355d10a8996464b63af (patch) | |
tree | 8e895a53e372fa682b4c0a585b9377d67ed70d0e /fs/adfs/inode.c | |
parent | 6a76fb7214c477ccf6582bd79c5b4ccc4f9c41b1 (diff) |
Look Ma' what I found on my harddisk ...
o New faster syscalls for 2.1.x, too
o Upgrade to 2.1.89.
Don't try to run this. It's flaky as hell. But feel free to debug ...
Diffstat (limited to 'fs/adfs/inode.c')
-rw-r--r-- | fs/adfs/inode.c | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c new file mode 100644 index 000000000..37daaa3c3 --- /dev/null +++ b/fs/adfs/inode.c @@ -0,0 +1,216 @@ +/* + * linux/fs/adfs/inode.c + * + * Copyright (C) 1997 Russell King + */ + +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/adfs_fs.h> +#include <linux/sched.h> +#include <linux/stat.h> +#include <linux/string.h> +#include <linux/locks.h> +#include <linux/mm.h> + +/* + * Old Inode numbers: + * bit 30 - 16 FragID of parent object + * bit 15 0 1 + * bit 14 - 0 FragID of object Offset into parent FragID + * + * New Inode numbers: + * Inode = Frag ID of parent (14) + Frag Offset (8) + (index into directory + 1)(8) + */ +#define inode_frag(ino) ((ino) >> 8) +#define inode_idx(ino) ((ino) & 0xff) +#define inode_dirindex(idx) (((idx) & 0xff) * 26 - 21) + +#define frag_id(x) (((x) >> 8) & 0x7fff) +#define off(x) (((x) & 0xff) ? ((x) & 0xff) - 1 : 0) + +static inline int adfs_inode_validate_no (struct super_block *sb, unsigned int inode_no) +{ + unsigned long max_frag_id; + + max_frag_id = sb->u.adfs_sb.s_map_size * sb->u.adfs_sb.s_ids_per_zone; + + return (inode_no & 0x800000ff) || + (frag_id (inode_frag (inode_no)) > max_frag_id) || + (frag_id (inode_frag (inode_no)) < 2); +} + +int adfs_inode_validate (struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + + return adfs_inode_validate_no (sb, inode->i_ino & 0xffffff00) || + adfs_inode_validate_no (sb, inode->u.adfs_i.file_id << 8); +} + +unsigned long adfs_inode_generate (unsigned long parent_id, int diridx) +{ + if (!parent_id) + return -1; + + if (diridx) + diridx = (diridx + 21) / 26; + + return (parent_id << 8) | diridx; +} + +unsigned long adfs_inode_objid (struct inode *inode) +{ + if (adfs_inode_validate (inode)) { + adfs_error (inode->i_sb, "adfs_inode_objid", + "bad inode number: %lu (%X,%X)", + inode->i_ino, inode->i_ino, inode->u.adfs_i.file_id); + return 0; + } + + return inode->u.adfs_i.file_id; +} + +int adfs_bmap (struct inode *inode, int block) +{ + struct super_block *sb = inode->i_sb; + unsigned int blk; + + if (adfs_inode_validate (inode)) { + adfs_error (sb, "adfs_bmap", + "bad inode number: %lu (%X,%X)", + inode->i_ino, inode->i_ino, inode->u.adfs_i.file_id); + return 0; + } + + if (frag_id(inode->u.adfs_i.file_id) == ADFS_ROOT_FRAG) + blk = sb->u.adfs_sb.s_map_block + off(inode_frag (inode->i_ino)) + block; + else + blk = adfs_map_lookup (sb, frag_id(inode->u.adfs_i.file_id), + off (inode->u.adfs_i.file_id) + block); + return blk; +} + +unsigned int adfs_parent_bmap (struct inode *inode, int block) +{ + struct super_block *sb = inode->i_sb; + unsigned int blk, fragment; + + if (adfs_inode_validate_no (sb, inode->i_ino & 0xffffff00)) { + adfs_error (sb, "adfs_parent_bmap", + "bad inode number: %lu (%X,%X)", + inode->i_ino, inode->i_ino, inode->u.adfs_i.file_id); + return 0; + } + + fragment = inode_frag (inode->i_ino); + if (frag_id (fragment) == ADFS_ROOT_FRAG) + blk = sb->u.adfs_sb.s_map_block + off (fragment) + block; + else + blk = adfs_map_lookup (sb, frag_id (fragment), off (fragment) + block); + return blk; +} + +static int adfs_atts2mode (unsigned char mode, unsigned int filetype) +{ + int omode = 0; + + if (filetype == 0xfc0 /* LinkFS */) { + omode = S_IFLNK|S_IRUSR|S_IWUSR|S_IXUSR| + S_IRGRP|S_IWGRP|S_IXGRP| + S_IROTH|S_IWOTH|S_IXOTH; + } else { + if (mode & ADFS_NDA_DIRECTORY) + omode |= S_IFDIR|S_IRUSR|S_IXUSR|S_IXGRP|S_IXOTH; + else + omode |= S_IFREG; + if (mode & ADFS_NDA_OWNER_READ) { + omode |= S_IRUSR; + if (filetype == 0xfe6 /* UnixExec */) + omode |= S_IXUSR; + } + if (mode & ADFS_NDA_OWNER_WRITE) + omode |= S_IWUSR; + if (mode & ADFS_NDA_PUBLIC_READ) { + omode |= S_IRGRP | S_IROTH; + if (filetype == 0xfe6) + omode |= S_IXGRP | S_IXOTH; + } + if (mode & ADFS_NDA_PUBLIC_WRITE) + omode |= S_IWGRP | S_IWOTH; + } + return omode; +} + +void adfs_read_inode (struct inode *inode) +{ + struct super_block *sb; + struct buffer_head *bh[4]; + struct adfs_idir_entry ide; + int buffers; + + sb = inode->i_sb; + inode->i_uid = 0; + inode->i_gid = 0; + inode->i_version = ++event; + + if (adfs_inode_validate_no (sb, inode->i_ino & 0xffffff00)) { + adfs_error (sb, "adfs_read_inode", + "bad inode number: %lu", inode->i_ino); + goto bad; + } + + if (frag_id(inode_frag (inode->i_ino)) == ADFS_ROOT_FRAG && + inode_idx (inode->i_ino) == 0) { + /* root dir */ + inode->i_mode = S_IRWXUGO | S_IFDIR; + inode->i_nlink = 2; + inode->i_size = ADFS_NEWDIR_SIZE; + inode->i_blksize = PAGE_SIZE; + inode->i_blocks = inode->i_size / sb->s_blocksize; + inode->i_mtime = + inode->i_atime = + inode->i_ctime = 0; + inode->u.adfs_i.file_id = inode_frag (inode->i_ino); + } else { + if (!(buffers = adfs_dir_read_parent (inode, bh))) + goto bad; + + if (adfs_dir_check (inode, bh, buffers, NULL)) { + adfs_dir_free (bh, buffers); + goto bad; + } + + if (!adfs_dir_find_entry (sb, bh, buffers, inode_dirindex (inode->i_ino), &ide)) { + adfs_dir_free (bh, buffers); + goto bad; + } + adfs_dir_free (bh, buffers); + inode->i_mode = adfs_atts2mode (ide.mode, ide.filetype); + inode->i_nlink = 2; + inode->i_size = ide.size; + inode->i_blksize = PAGE_SIZE; + inode->i_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; + inode->i_mtime = + inode->i_atime = + inode->i_ctime = ide.mtime; + inode->u.adfs_i.file_id = ide.file_id; + } + + if (S_ISDIR(inode->i_mode)) + inode->i_op = &adfs_dir_inode_operations; + else if (S_ISREG(inode->i_mode)) + inode->i_op = &adfs_file_inode_operations; + return; + +bad: + inode->i_mode = 0; + inode->i_nlink = 1; + inode->i_size = 0; + inode->i_blksize = 0; + inode->i_blocks = 0; + inode->i_mtime = + inode->i_atime = + inode->i_ctime = 0; + inode->i_op = NULL; +} |