Import 2.3.26pre2
[davej-history.git] / fs / adfs / inode.c
blob6c8814567ab2d74a8d135ad1d7e32c386715a42b
1 /*
2 * linux/fs/adfs/inode.c
4 * Copyright (C) 1997 Russell King
5 */
7 #include <linux/errno.h>
8 #include <linux/fs.h>
9 #include <linux/adfs_fs.h>
10 #include <linux/sched.h>
11 #include <linux/stat.h>
12 #include <linux/string.h>
13 #include <linux/locks.h>
14 #include <linux/mm.h>
17 * Old Inode numbers:
18 * bit 30 - 16 FragID of parent object
19 * bit 15 0 1
20 * bit 14 - 0 FragID of object Offset into parent FragID
22 * New Inode numbers:
23 * Inode = Frag ID of parent (14) + Frag Offset (8) + (index into directory + 1)(8)
25 #define inode_frag(ino) ((ino) >> 8)
26 #define inode_idx(ino) ((ino) & 0xff)
27 #define inode_dirindex(idx) (((idx) & 0xff) * 26 - 21)
29 #define frag_id(x) (((x) >> 8) & 0x7fff)
30 #define off(x) (((x) & 0xff) ? (((x) & 0xff) - 1) << sb->u.adfs_sb.s_dr->log2sharesize : 0)
32 static inline int adfs_inode_validate_no (struct super_block *sb, unsigned int inode_no)
34 unsigned long max_frag_id;
36 max_frag_id = sb->u.adfs_sb.s_map_size * sb->u.adfs_sb.s_ids_per_zone;
38 return (inode_no & 0x800000ff) ||
39 (frag_id (inode_frag (inode_no)) > max_frag_id) ||
40 (frag_id (inode_frag (inode_no)) < 2);
43 int adfs_inode_validate (struct inode *inode)
45 struct super_block *sb = inode->i_sb;
47 return adfs_inode_validate_no (sb, inode->i_ino & 0xffffff00) ||
48 adfs_inode_validate_no (sb, inode->u.adfs_i.file_id << 8);
51 unsigned long adfs_inode_generate (unsigned long parent_id, int diridx)
53 if (!parent_id)
54 return -1;
56 if (diridx)
57 diridx = (diridx + 21) / 26;
59 return (parent_id << 8) | diridx;
62 unsigned long adfs_inode_objid (struct inode *inode)
64 if (adfs_inode_validate (inode)) {
65 adfs_error (inode->i_sb, "adfs_inode_objid",
66 "bad inode number: %lu (%X,%X)",
67 inode->i_ino, inode->i_ino, inode->u.adfs_i.file_id);
68 return 0;
71 return inode->u.adfs_i.file_id;
74 int adfs_bmap (struct inode *inode, int block)
76 struct super_block *sb = inode->i_sb;
77 unsigned int blk;
79 if (adfs_inode_validate (inode)) {
80 adfs_error (sb, "adfs_bmap",
81 "bad inode number: %lu (%X,%X)",
82 inode->i_ino, inode->i_ino, inode->u.adfs_i.file_id);
83 return 0;
86 if (block < 0) {
87 adfs_error(sb, "adfs_bmap", "block(%d) < 0", block);
88 return 0;
91 if (block > inode->i_blocks)
92 return 0;
94 block += off(inode->u.adfs_i.file_id);
96 if (frag_id(inode->u.adfs_i.file_id) == ADFS_ROOT_FRAG)
97 blk = sb->u.adfs_sb.s_map_block + block;
98 else
99 blk = adfs_map_lookup (sb, frag_id(inode->u.adfs_i.file_id), block);
100 return blk;
103 unsigned int adfs_parent_bmap (struct inode *inode, int block)
105 struct super_block *sb = inode->i_sb;
106 unsigned int blk, fragment;
108 if (adfs_inode_validate_no (sb, inode->i_ino & 0xffffff00)) {
109 adfs_error (sb, "adfs_parent_bmap",
110 "bad inode number: %lu (%X,%X)",
111 inode->i_ino, inode->i_ino, inode->u.adfs_i.file_id);
112 return 0;
115 fragment = inode_frag (inode->i_ino);
116 if (frag_id (fragment) == ADFS_ROOT_FRAG)
117 blk = sb->u.adfs_sb.s_map_block + off(fragment) + block;
118 else
119 blk = adfs_map_lookup (sb, frag_id (fragment), off(fragment) + block);
120 return blk;
123 static int adfs_atts2mode(struct super_block *sb, unsigned char mode, unsigned int filetype)
125 int omode = 0;
127 if (filetype == 0xfc0 /* LinkFS */) {
128 omode = S_IFLNK|S_IRUSR|S_IWUSR|S_IXUSR|
129 S_IRGRP|S_IWGRP|S_IXGRP|
130 S_IROTH|S_IWOTH|S_IXOTH;
131 } else {
132 if (mode & ADFS_NDA_DIRECTORY) {
133 omode |= S_IRUGO & sb->u.adfs_sb.s_owner_mask;
134 omode |= S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH;
135 } else
136 omode |= S_IFREG;
138 if (mode & ADFS_NDA_OWNER_READ) {
139 omode |= S_IRUGO & sb->u.adfs_sb.s_owner_mask;
140 if (filetype == 0xfe6 /* UnixExec */)
141 omode |= S_IXUGO & sb->u.adfs_sb.s_owner_mask;
144 if (mode & ADFS_NDA_OWNER_WRITE)
145 omode |= S_IWUGO & sb->u.adfs_sb.s_owner_mask;
147 if (mode & ADFS_NDA_PUBLIC_READ) {
148 omode |= S_IRUGO & sb->u.adfs_sb.s_other_mask;
149 if (filetype == 0xfe6 /* UnixExec */)
150 omode |= S_IXUGO & sb->u.adfs_sb.s_other_mask;
153 if (mode & ADFS_NDA_PUBLIC_WRITE)
154 omode |= S_IWUGO & sb->u.adfs_sb.s_other_mask;
156 return omode;
159 void adfs_read_inode (struct inode *inode)
161 struct super_block *sb;
162 struct buffer_head *bh[4];
163 struct adfs_idir_entry ide;
164 int buffers;
166 sb = inode->i_sb;
167 inode->i_uid = sb->u.adfs_sb.s_uid;
168 inode->i_gid = sb->u.adfs_sb.s_gid;
169 inode->i_version = ++event;
171 if (adfs_inode_validate_no (sb, inode->i_ino & 0xffffff00)) {
172 adfs_error (sb, "adfs_read_inode",
173 "bad inode number: %lu", inode->i_ino);
174 goto bad;
177 if (frag_id(inode_frag (inode->i_ino)) == ADFS_ROOT_FRAG &&
178 inode_idx (inode->i_ino) == 0) {
179 /* root dir */
180 inode->i_mode = S_IRWXUGO | S_IFDIR;
181 inode->i_nlink = 2;
182 inode->i_size = ADFS_NEWDIR_SIZE;
183 inode->i_blksize = PAGE_SIZE;
184 inode->i_blocks = inode->i_size / sb->s_blocksize;
185 inode->i_mtime =
186 inode->i_atime =
187 inode->i_ctime = 0;
188 inode->u.adfs_i.file_id = inode_frag (inode->i_ino);
189 } else {
190 if (!(buffers = adfs_dir_read_parent (inode, bh)))
191 goto bad;
193 if (adfs_dir_check (inode, bh, buffers, NULL)) {
194 adfs_dir_free (bh, buffers);
195 goto bad;
198 if (!adfs_dir_find_entry (sb, bh, buffers, inode_dirindex (inode->i_ino), &ide)) {
199 adfs_dir_free (bh, buffers);
200 goto bad;
202 adfs_dir_free (bh, buffers);
203 inode->i_mode = adfs_atts2mode(sb, ide.mode, ide.filetype);
204 inode->i_nlink = 2;
205 inode->i_size = ide.size;
206 inode->i_blksize = PAGE_SIZE;
207 inode->i_blocks = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
208 inode->i_mtime =
209 inode->i_atime =
210 inode->i_ctime = ide.mtime;
211 inode->u.adfs_i.file_id = ide.file_id;
214 if (S_ISDIR(inode->i_mode))
215 inode->i_op = &adfs_dir_inode_operations;
216 else if (S_ISREG(inode->i_mode))
217 inode->i_op = &adfs_file_inode_operations;
218 return;
220 bad:
221 make_bad_inode(inode);