This source file includes following definitions.
- affs_put_super
- affs_parent_ino
- parse_options
- get_device_size
- affs_read_super
- affs_statfs
- affs_read_inode
- leak_check_malloc
- leak_check_free_s
- leak_check_bread
- leak_check_brelse
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <linux/stat.h>
14 #include <linux/sched.h>
15 #include <linux/affs_fs.h>
16 #include <linux/kernel.h>
17 #include <linux/mm.h>
18 #include <linux/string.h>
19 #include <linux/locks.h>
20
21 #include <asm/system.h>
22 #include <asm/segment.h>
23 #include <linux/errno.h>
24
25 #include <linux/genhd.h>
26
27 #include "amigaffs.h"
28
29 extern int check_cdrom_media_change(int, int);
30
31 #ifdef LEAK_CHECK
32 static int check_malloc = 0;
33 static int check_bread = 0;
34 #endif
35
36 void affs_put_super(struct super_block *sb)
37 {
38 lock_super(sb);
39
40 #ifdef LEAK_CHECK
41 printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
42 check_malloc, check_bread);
43 #endif
44 sb->s_dev = 0;
45 unlock_super(sb);
46 return;
47 }
48
49 static struct super_operations affs_sops = {
50 affs_read_inode,
51 NULL,
52 NULL,
53 NULL,
54 affs_put_super,
55 NULL,
56 affs_statfs,
57 NULL
58 };
59
60 int affs_parent_ino(struct inode *dir)
61 {
62 int root_ino = (dir->i_sb->u.affs_sb.s_root_block
63 - dir->i_sb->u.affs_sb.s_partition_offset);
64
65 if (!S_ISDIR (dir->i_mode)) {
66 printk ("affs_parent_ino: argument is not a directory\n");
67 return root_ino;
68 }
69 if (dir->i_ino == root_ino)
70 return root_ino;
71 return dir->u.affs_i.i_parent;
72 }
73
74 static int parse_options(char *options, struct affs_options *optp)
75 {
76 char *this_opt,*value,*end;
77 int n;
78
79 optp->offset = 0;
80 optp->size = 0;
81 optp->root = 0;
82 optp->conv_links = 0;
83
84 if (!options)
85 return 1;
86 for (this_opt = strtok(options,","); this_opt; this_opt = strtok(NULL,",")) {
87 if ((value = strchr(this_opt,'='))) *value++ = 0;
88
89 if (!strcmp(this_opt,"offset") && value) {
90 n = simple_strtoul (value, &end, 10);
91 if (end == value || *end != 0)
92 return 0;
93 optp->offset = n;
94 }
95 else if (!strcmp(this_opt,"size") && value) {
96 n = simple_strtoul (value, &end, 10);
97 if (end == value || *end != 0 || n <= 0)
98 return 0;
99 optp->size = n;
100 }
101 else if (!strcmp(this_opt,"root") && value) {
102 n = simple_strtoul (value, &end, 10);
103 if (end == value || *end != 0 || n <= 0)
104 return 0;
105 optp->root = n;
106 }
107 else if (!strcmp(this_opt,"conv_symlinks")) {
108 optp->conv_links = 1;
109 }
110 else return 0;
111 }
112 return 1;
113 }
114
115
116
117 static int get_device_size (dev_t dev)
118 {
119 struct gendisk *gd_p;
120 int dev_size = 0;
121
122 for (gd_p = gendisk_head ; gd_p ; gd_p=gd_p->next) {
123 if (gd_p->major != MAJOR(dev))
124 continue;
125 dev_size = gd_p->part[MINOR(dev)].nr_sects;
126 break;
127 }
128 return dev_size;
129 }
130
131 struct super_block *affs_read_super(struct super_block *s,void *data,
132 int silent)
133 {
134 struct buffer_head *bh;
135 int dev = s->s_dev;
136 int root_block;
137 int ptype, stype;
138 void *root_data;
139 struct affs_options *optp;
140
141 optp = &s->u.affs_sb.s_options;
142
143 if (!parse_options((char *) data, optp)) {
144 s->s_dev = 0;
145 printk ("AFFS: bad mount options\n");
146 return NULL;
147 }
148
149 lock_super(s);
150
151 root_block = 0;
152 if (optp->size) {
153 s->u.affs_sb.s_partition_size = optp->size;
154 }
155 else {
156 int size = get_device_size (dev);
157 if (size == 0) {
158 s->s_dev = 0;
159 unlock_super(s);
160 printk ("affs_read_super: could not"
161 "determine device size\n");
162 }
163 s->u.affs_sb.s_partition_size = size;
164 }
165
166 s->u.affs_sb.s_partition_offset = optp->offset;
167 root_block = optp->root;
168
169 if (!root_block)
170 root_block = (s->u.affs_sb.s_partition_offset
171 + s->u.affs_sb.s_partition_size / 2
172 + (s->u.affs_sb.s_partition_size & 1));
173 s->u.affs_sb.s_root_block = root_block;
174
175 s->u.affs_sb.s_block_size = AFFS_BLOCK_SIZE;
176
177 #if 0
178 printk ("affs_read_super: dev=0x%04x offset=%d "
179 "size=%d root=%d blocksize=%d\n",
180 dev,
181 s->u.affs_sb.s_partition_offset,
182 s->u.affs_sb.s_partition_size,
183 s->u.affs_sb.s_root_block,
184 s->u.affs_sb.s_block_size);
185 #endif
186
187 bh = affs_sread (dev, root_block, &root_data);
188 if (!bh) {
189 s->s_dev = 0;
190 unlock_super(s);
191 printk ("AFFS: unable to read superblock\n");
192 return NULL;
193 }
194
195 if (affs_checksum_block (AFFS_BLOCK_SIZE, root_data, &ptype, &stype)
196 || ptype != T_SHORT || stype != ST_ROOT) {
197 printk ("AFFS: invalid root block %d on device 0x%04x\n",
198 root_block, dev);
199 goto out;
200 }
201
202 #if 1
203 {
204 char *name;
205 int len;
206 char buf[33];
207 len = affs_get_file_name (AFFS_BLOCK_SIZE, root_data, &name);
208 memcpy (buf,name,len);
209 buf[len] = 0;
210 #if 0
211 printk ("affs_read_super: volume name \"%s\"\n", buf);
212 #endif
213 }
214 #endif
215
216 s->s_magic = AFFS_SUPER_MAGIC;
217
218 s->s_flags = MS_RDONLY | MS_NODEV | MS_NOSUID;
219
220 brelse(bh);
221
222
223 s->s_dev = dev;
224 s->s_op = &affs_sops;
225 s->s_blocksize = AFFS_BUFFER_SIZE;
226 s->s_mounted = iget (s, root_block - s->u.affs_sb.s_partition_offset);
227
228 unlock_super(s);
229
230 if (!(s->s_mounted)) {
231 s->s_dev = 0;
232 printk("AFFS: get root inode failed\n");
233 return NULL;
234 }
235
236 return s;
237
238 out:
239 brelse (bh);
240 s->s_dev = 0;
241 unlock_super(s);
242 return NULL;
243 }
244
245 void affs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
246 {
247 #ifdef DEBUG
248 printk ("AFFS: affs_statfs called\n");
249 #endif
250 put_fs_long(AFFS_SUPER_MAGIC, &buf->f_type);
251 put_fs_long(sb->u.affs_sb.s_block_size, &buf->f_bsize);
252 put_fs_long(sb->u.affs_sb.s_partition_size, &buf->f_blocks);
253 put_fs_long(0, &buf->f_bfree);
254 put_fs_long(0, &buf->f_bavail);
255 put_fs_long(0, &buf->f_files);
256 put_fs_long(0, &buf->f_ffree);
257
258 }
259
260 static int prot_table[9][2] = {
261 {PROT_OTR_EXECUTE, PROT_OTR_EXECUTE},
262 {PROT_OTR_WRITE, PROT_OTR_WRITE},
263 {PROT_OTR_READ, PROT_OTR_READ},
264 {PROT_GRP_EXECUTE, PROT_GRP_EXECUTE},
265 {PROT_GRP_WRITE, PROT_GRP_WRITE},
266 {PROT_GRP_READ, PROT_GRP_READ},
267 {PROT_EXECUTE, 0},
268 {PROT_WRITE, 0},
269 {PROT_READ, 0}
270 };
271
272 void affs_read_inode(struct inode * inode)
273 {
274 struct buffer_head *bh;
275 int block;
276 void *fh_data;
277 struct file_front *file_front;
278 struct file_end *file_end;
279 int i;
280 struct hardlink_end *link_end;
281 int link;
282
283 #ifdef DEBUG
284 printk ("AFFS: entering affs_read_inode\n");
285 #endif
286
287 inode->i_nlink = 1;
288 do {
289 link = 0;
290 block = inode->i_ino;
291 if (!(bh=affs_pread (inode, block, &fh_data))) {
292 printk("AFFS: unable to read i-node block %d\n", block);
293 return;
294 }
295
296 file_front = (struct file_front *) fh_data;
297 file_end = GET_END_PTR (struct file_end, fh_data,
298 AFFS_I2BSIZE (inode));
299
300
301 if (block == inode->i_sb->u.affs_sb.s_root_block) {
302 inode->u.affs_i.i_protect = 0;
303 inode->u.affs_i.i_parent = block;
304
305 inode->i_mode = S_IRWXUGO | S_IFDIR | S_ISVTX ;
306 inode->i_nlink = 2;
307
308 inode->i_size = 0;
309
310 inode->i_uid = 0;
311 inode->i_gid = 0;
312 }
313 else {
314
315 inode->u.affs_i.i_protect = file_end->protect;
316 inode->u.affs_i.i_parent = swap_long (file_end->parent);
317
318 inode->i_mode = 0;
319 for (i = 0; i < 9; i++)
320 if ((prot_table[i][0] & inode->u.affs_i.i_protect) == prot_table[i][1])
321 inode->i_mode |= 1<<i;
322 switch(swap_long(file_end->secondary_type)) {
323 case ST_USERDIR:
324 inode->i_mode |= ((inode->i_mode & 0444)>>2) | S_IFDIR;
325
326 inode->i_nlink++;
327
328 inode->i_size = 0;
329 break;
330 case ST_SOFTLINK:
331 inode->i_mode |= S_IFLNK;
332 inode->i_size = 0;
333 break;
334 case ST_LINKFILE:
335 case ST_LINKDIR:
336
337
338
339
340
341 link_end = (struct hardlink_end *)file_end;
342 inode->i_ino = link_end->original;
343 inode->i_nlink += 2;
344 brelse(bh);
345 link = 1;
346 break;
347 default:
348 printk("affs: unknown secondary type %ld; assuming file\n",
349 file_end->secondary_type);
350 case ST_FILE:
351 inode->i_mode |= S_IFREG;
352 inode->i_size = swap_long (file_end->byte_size);
353 break;
354 }
355 if (file_end->uid == 0xffff)
356 inode->i_uid = 0;
357 else if (file_end->uid == 0x0000) {
358 umode_t mode;
359 inode->i_uid = -1;
360
361
362
363
364
365
366
367
368 mode = (inode->i_mode >> 6) & 7;
369 inode->i_mode |= (mode << 3) | (mode);
370 } else
371 inode->i_uid = file_end->uid;
372 if (file_end->gid == 0xffff)
373 inode->i_gid = 0;
374 else if (file_end->gid == 0x0000)
375 inode->i_gid = -1;
376 else
377 inode->i_gid = file_end->gid;
378 }
379 }
380 while (link);
381
382 #ifdef DEBUG
383 printk ("AFFS: read inode %d: size=%d\n", block, inode->i_size);
384 #endif
385 inode->i_mtime = inode->i_atime = inode->i_ctime
386 = (swap_long (file_end->created.ds_Days) * (24 * 60 * 60)
387 + swap_long (file_end->created.ds_Minute) * 60
388 + swap_long (file_end->created.ds_Tick) / 50
389 + ((8 * 365 + 2) * 24 * 60 * 60));
390
391 brelse(bh);
392
393 inode->i_op = NULL;
394 if (S_ISREG(inode->i_mode))
395 inode->i_op = &affs_file_inode_operations;
396 else if (S_ISDIR(inode->i_mode))
397 inode->i_op = &affs_dir_inode_operations;
398 else if (S_ISLNK(inode->i_mode))
399 inode->i_op = &affs_symlink_inode_operations;
400 }
401
402
403 #ifdef LEAK_CHECK
404 #undef malloc
405 #undef free_s
406 #undef bread
407 #undef brelse
408
409 void * leak_check_malloc(unsigned int size){
410 void * tmp;
411 check_malloc++;
412 tmp = kmalloc(size, GFP_ATOMIC);
413 return tmp;
414 }
415
416 void leak_check_free_s(void * obj, int size){
417 check_malloc--;
418 return kfree_s(obj, size);
419 }
420
421 struct buffer_head * leak_check_bread(int dev, int block, int size){
422 check_bread++;
423 return bread(dev, block, size);
424 }
425
426 void leak_check_brelse(struct buffer_head * bh){
427 check_bread--;
428 return brelse(bh);
429 }
430
431 #endif