* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-0.99 / fs / isofs / inode.c
blobd800d59ffcda1ba8318492307435d19585f714f3
1 /*
2 * linux/fs/isofs/inode.c
3 *
4 * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem.
6 * (C) 1991 Linus Torvalds - minix filesystem
7 */
9 #include <linux/config.h>
10 #include <linux/stat.h>
11 #include <linux/sched.h>
12 #include <linux/iso_fs.h>
13 #include <linux/kernel.h>
14 #include <linux/major.h>
15 #include <linux/mm.h>
16 #include <linux/string.h>
17 #include <linux/locks.h>
18 #include <linux/malloc.h>
19 #include <linux/errno.h>
21 #include <asm/system.h>
22 #include <asm/segment.h>
24 #if defined(CONFIG_BLK_DEV_SR)
25 extern int check_cdrom_media_change(int, int);
26 #endif
27 #if defined(CONFIG_CDU31A)
28 extern int check_cdu31a_media_change(int, int);
29 #endif
30 #if defined(CONFIG_MCD)
31 extern int check_mcd_media_change(int, int);
32 #endif
33 #if defined (CONFIG_SBPCD)
34 extern int check_sbpcd_media_change(int, int);
35 #endif CONFIG_SBPCD
37 #ifdef LEAK_CHECK
38 static int check_malloc = 0;
39 static int check_bread = 0;
40 #endif
42 void isofs_put_super(struct super_block *sb)
44 lock_super(sb);
46 #ifdef LEAK_CHECK
47 printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
48 check_malloc, check_bread);
49 #endif
50 sb->s_dev = 0;
51 unlock_super(sb);
52 return;
55 static struct super_operations isofs_sops = {
56 isofs_read_inode,
57 NULL, /* notify_change */
58 NULL, /* write_inode */
59 NULL, /* put_inode */
60 isofs_put_super,
61 NULL, /* write_super */
62 isofs_statfs,
63 NULL
68 static int parse_options(char *options,char *map,char *conversion, char * rock, char * cruft, unsigned int * blocksize)
70 char *this_char,*value;
72 *map = 'n';
73 *rock = 'y';
74 *cruft = 'n';
75 *conversion = 'a';
76 *blocksize = 1024;
77 if (!options) return 1;
78 for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
79 if (strncmp(this_char,"norock",6) == 0) {
80 *rock = 'n';
81 continue;
83 if (strncmp(this_char,"cruft",5) == 0) {
84 *cruft = 'y';
85 continue;
87 if ((value = strchr(this_char,'=')) != NULL)
88 *value++ = 0;
89 if (!strcmp(this_char,"map") && value) {
90 if (value[0] && !value[1] && strchr("on",*value))
91 *map = *value;
92 else if (!strcmp(value,"off")) *map = 'o';
93 else if (!strcmp(value,"normal")) *map = 'n';
94 else return 0;
96 else if (!strcmp(this_char,"conv") && value) {
97 if (value[0] && !value[1] && strchr("bta",*value))
98 *conversion = *value;
99 else if (!strcmp(value,"binary")) *conversion = 'b';
100 else if (!strcmp(value,"text")) *conversion = 't';
101 else if (!strcmp(value,"mtext")) *conversion = 'm';
102 else if (!strcmp(value,"auto")) *conversion = 'a';
103 else return 0;
105 else if (!strcmp(this_char,"block") && value) {
106 char * vpnt = value;
107 unsigned int ivalue;
108 ivalue = 0;
109 while(*vpnt){
110 if(*vpnt < '0' || *vpnt > '9') break;
111 ivalue = ivalue * 10 + (*vpnt - '0');
112 vpnt++;
114 if (*vpnt) return 0;
115 if (ivalue != 1024 && ivalue != 2048) return 0;
116 *blocksize = ivalue;
118 else return 0;
120 return 1;
123 struct super_block *isofs_read_super(struct super_block *s,void *data,
124 int silent)
126 struct buffer_head *bh;
127 int iso_blknum;
128 unsigned int blocksize, blocksize_bits;
129 int high_sierra;
130 int dev=s->s_dev;
131 struct iso_volume_descriptor *vdp;
132 struct hs_volume_descriptor *hdp;
134 struct iso_primary_descriptor *pri = NULL;
135 struct hs_primary_descriptor *h_pri = NULL;
137 struct iso_directory_record *rootp;
139 char map, conversion, rock, cruft;
141 if (!parse_options((char *) data,&map,&conversion, &rock, &cruft, &blocksize)) {
142 s->s_dev = 0;
143 return NULL;
146 blocksize_bits = 0;
148 int i = blocksize;
149 while (i != 1){
150 blocksize_bits++;
151 i >>=1;
154 set_blocksize(dev, blocksize);
156 lock_super(s);
158 s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
160 for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
161 if (!(bh = bread(dev, iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits), blocksize))) {
162 s->s_dev=0;
163 printk("isofs_read_super: bread failed, dev 0x%x iso_blknum %d\n",
164 dev, iso_blknum);
165 unlock_super(s);
166 return NULL;
169 vdp = (struct iso_volume_descriptor *)bh->b_data;
170 hdp = (struct hs_volume_descriptor *)bh->b_data;
173 if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
174 if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
175 goto out;
176 if (isonum_711 (hdp->type) == ISO_VD_END)
177 goto out;
179 s->u.isofs_sb.s_high_sierra = 1;
180 high_sierra = 1;
181 rock = 'n';
182 h_pri = (struct hs_primary_descriptor *)vdp;
183 break;
186 if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
187 if (isonum_711 (vdp->type) != ISO_VD_PRIMARY)
188 goto out;
189 if (isonum_711 (vdp->type) == ISO_VD_END)
190 goto out;
192 pri = (struct iso_primary_descriptor *)vdp;
193 break;
196 brelse(bh);
198 if(iso_blknum == 100) {
199 if (!silent)
200 printk("Unable to identify CD-ROM format.\n");
201 s->s_dev = 0;
202 unlock_super(s);
203 return NULL;
207 if(high_sierra){
208 rootp = (struct iso_directory_record *) h_pri->root_directory_record;
209 if (isonum_723 (h_pri->volume_set_size) != 1) {
210 printk("Multi-volume disks not (yet) supported.\n");
211 goto out;
213 s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
214 s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
215 s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
216 } else {
217 rootp = (struct iso_directory_record *) pri->root_directory_record;
218 if (isonum_723 (pri->volume_set_size) != 1) {
219 printk("Multi-volume disks not (yet) supported.\n");
220 goto out;
222 s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
223 s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
224 s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
227 s->u.isofs_sb.s_ninodes = 0; /* No way to figure this out easily */
229 s->u.isofs_sb.s_firstdatazone = isonum_733( rootp->extent) <<
230 (ISOFS_BLOCK_BITS - blocksize_bits);
231 s->s_magic = ISOFS_SUPER_MAGIC;
233 /* The CDROM is read-only, has no nodes (devices) on it, and since
234 all of the files appear to be owned by root, we really do not want
235 to allow suid. (suid or devices will not show up unless we have
236 Rock Ridge extensions) */
238 s->s_flags = MS_RDONLY /* | MS_NODEV | MS_NOSUID */;
240 if(s->u.isofs_sb.s_log_zone_size != (1 << ISOFS_BLOCK_BITS)) {
241 printk("1 <<Block bits != Block size\n");
242 goto out;
245 brelse(bh);
247 printk("Max size:%ld Log zone size:%ld\n",
248 s->u.isofs_sb.s_max_size,
249 s->u.isofs_sb.s_log_zone_size);
250 printk("First datazone:%ld Root inode number %d\n",
251 s->u.isofs_sb.s_firstdatazone,
252 isonum_733 (rootp->extent) << ISOFS_BLOCK_BITS);
253 if(high_sierra) printk("Disc in High Sierra format.\n");
254 unlock_super(s);
255 /* set up enough so that it can read an inode */
257 s->s_dev = dev;
258 s->s_op = &isofs_sops;
259 s->u.isofs_sb.s_mapping = map;
260 s->u.isofs_sb.s_rock = (rock == 'y' ? 1 : 0);
261 s->u.isofs_sb.s_conversion = conversion;
262 s->u.isofs_sb.s_cruft = cruft;
263 s->s_blocksize = blocksize;
264 s->s_blocksize_bits = blocksize_bits;
265 s->s_mounted = iget(s, isonum_733 (rootp->extent) << ISOFS_BLOCK_BITS);
266 unlock_super(s);
268 if (!(s->s_mounted)) {
269 s->s_dev=0;
270 printk("get root inode failed\n");
271 return NULL;
273 #if defined(CONFIG_BLK_DEV_SR) && defined(CONFIG_SCSI)
274 if (MAJOR(s->s_dev) == SCSI_CDROM_MAJOR) {
275 /* Check this one more time. */
276 if(check_cdrom_media_change(s->s_dev, 0))
277 goto out;
279 #endif
280 #if defined(CONFIG_CDU31A)
281 if (MAJOR(s->s_dev) == CDU31A_CDROM_MAJOR) {
282 /* Check this one more time. */
283 if(check_cdu31a_media_change(s->s_dev, 0))
284 goto out;
286 #endif
287 #if defined(CONFIG_MCD)
288 if (MAJOR(s->s_dev) == MITSUMI_CDROM_MAJOR) {
289 /* Check this one more time. */
290 if(check_mcd_media_change(s->s_dev, 0))
291 goto out;
293 #endif
294 #if defined(CONFIG_SBPCD)
295 if (MAJOR(s->s_dev) == MATSUSHITA_CDROM_MAJOR) {
296 if (check_sbpcd_media_change(s->s_dev,0))
297 goto out;
299 #endif CONFIG_SBPCD
301 return s;
302 out: /* Kick out for various error conditions */
303 brelse(bh);
304 s->s_dev = 0;
305 unlock_super(s);
306 return NULL;
309 void isofs_statfs (struct super_block *sb, struct statfs *buf)
311 put_fs_long(ISOFS_SUPER_MAGIC, &buf->f_type);
312 put_fs_long(1 << ISOFS_BLOCK_BITS, &buf->f_bsize);
313 put_fs_long(sb->u.isofs_sb.s_nzones, &buf->f_blocks);
314 put_fs_long(0, &buf->f_bfree);
315 put_fs_long(0, &buf->f_bavail);
316 put_fs_long(sb->u.isofs_sb.s_ninodes, &buf->f_files);
317 put_fs_long(0, &buf->f_ffree);
318 put_fs_long(NAME_MAX, &buf->f_namelen);
319 /* Don't know what value to put in buf->f_fsid */
322 int isofs_bmap(struct inode * inode,int block)
325 if (block<0) {
326 printk("_isofs_bmap: block<0");
327 return 0;
329 return inode->u.isofs_i.i_first_extent + block;
332 void isofs_read_inode(struct inode * inode)
334 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
335 struct buffer_head * bh;
336 struct iso_directory_record * raw_inode;
337 unsigned char *pnt = NULL;
338 void *cpnt = NULL;
339 int high_sierra;
340 int block;
341 int i;
343 block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
344 if (!(bh=bread(inode->i_dev,block, bufsize))) {
345 printk("unable to read i-node block");
346 goto fail;
349 pnt = ((unsigned char *) bh->b_data
350 + (inode->i_ino & (bufsize - 1)));
351 raw_inode = ((struct iso_directory_record *) pnt);
352 high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
354 if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){
355 cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
356 memcpy(cpnt, bh->b_data, bufsize);
357 brelse(bh);
358 if (!(bh = bread(inode->i_dev,++block, bufsize))) {
359 kfree_s (cpnt, 1 << ISOFS_BLOCK_BITS);
360 printk("unable to read i-node block");
361 goto fail;
363 memcpy((char *)cpnt + bufsize, bh->b_data, bufsize);
364 pnt = ((unsigned char *) cpnt
365 + (inode->i_ino & (bufsize - 1)));
366 raw_inode = ((struct iso_directory_record *) pnt);
369 inode->i_mode = S_IRUGO; /* Everybody gets to read the file. */
370 inode->i_nlink = 1;
372 if (raw_inode->flags[-high_sierra] & 2) {
373 inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
374 inode->i_nlink = 2; /* There are always at least 2. It is
375 hard to figure out what is correct*/
376 } else {
377 inode->i_mode = S_IRUGO; /* Everybody gets to read the file. */
378 inode->i_nlink = 1;
379 inode->i_mode |= S_IFREG;
380 /* If there are no periods in the name, then set the execute permission bit */
381 for(i=0; i< raw_inode->name_len[0]; i++)
382 if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
383 break;
384 if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';')
385 inode->i_mode |= S_IXUGO; /* execute permission */
387 inode->i_uid = 0;
388 inode->i_gid = 0;
389 inode->i_size = isonum_733 (raw_inode->size);
391 /* There are defective discs out there - we do this to protect
392 ourselves. A cdrom will never contain more than 700Mb */
393 if((inode->i_size < 0 || inode->i_size > 700000000) &&
394 inode->i_sb->u.isofs_sb.s_cruft == 'n') {
395 printk("Warning: defective cdrom. Enabling \"cruft\" mount option.\n");
396 inode->i_sb->u.isofs_sb.s_cruft = 'y';
399 /* Some dipshit decided to store some other bit of information in the high
400 byte of the file length. Catch this and holler. WARNING: this will make
401 it impossible for a file to be > 16Mb on the CDROM!!!*/
403 if(inode->i_sb->u.isofs_sb.s_cruft == 'y' &&
404 inode->i_size & 0xff000000){
405 /* printk("Illegal format on cdrom. Pester manufacturer.\n"); */
406 inode->i_size &= 0x00ffffff;
409 if (raw_inode->interleave[0]) {
410 printk("Interleaved files not (yet) supported.\n");
411 inode->i_size = 0;
414 #ifdef DEBUG
415 /* I have no idea what extended attributes are used for, so
416 we will flag it for now */
417 if(raw_inode->ext_attr_length[0] != 0){
418 printk("Extended attributes present for ISO file (%ld).\n",
419 inode->i_ino);
421 #endif
423 /* I have no idea what file_unit_size is used for, so
424 we will flag it for now */
425 if(raw_inode->file_unit_size[0] != 0){
426 printk("File unit size != 0 for ISO file (%ld).\n",inode->i_ino);
429 /* I have no idea what other flag bits are used for, so
430 we will flag it for now */
431 if((raw_inode->flags[-high_sierra] & ~2)!= 0){
432 printk("Unusual flag settings for ISO file (%ld %x).\n",
433 inode->i_ino, raw_inode->flags[-high_sierra]);
436 #ifdef DEBUG
437 printk("Get inode %d: %d %d: %d\n",inode->i_ino, block,
438 ((int)pnt) & 0x3ff, inode->i_size);
439 #endif
441 inode->i_mtime = inode->i_atime = inode->i_ctime =
442 iso_date(raw_inode->date, high_sierra);
444 inode->u.isofs_i.i_first_extent = isonum_733 (raw_inode->extent) <<
445 (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS(inode));
447 inode->u.isofs_i.i_backlink = 0xffffffff; /* Will be used for previous directory */
448 switch (inode->i_sb->u.isofs_sb.s_conversion){
449 case 'a':
450 inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN; /* File type */
451 break;
452 case 'b':
453 inode->u.isofs_i.i_file_format = ISOFS_FILE_BINARY; /* File type */
454 break;
455 case 't':
456 inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT; /* File type */
457 break;
458 case 'm':
459 inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT_M; /* File type */
460 break;
464 /* Now test for possible Rock Ridge extensions which will override some of
465 these numbers in the inode structure. */
467 if (!high_sierra)
468 parse_rock_ridge_inode(raw_inode, inode);
470 #ifdef DEBUG
471 printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
472 #endif
473 brelse(bh);
475 if (cpnt) {
476 kfree_s (cpnt, 1 << ISOFS_BLOCK_BITS);
477 cpnt = NULL;
480 inode->i_op = NULL;
481 if (inode->i_sb->u.isofs_sb.s_cruft != 'y' &&
482 isonum_723 (raw_inode->volume_sequence_number) != 1) {
483 printk("Multi volume CD somehow got mounted.\n");
484 } else {
485 if (S_ISREG(inode->i_mode))
486 inode->i_op = &isofs_file_inode_operations;
487 else if (S_ISDIR(inode->i_mode))
488 inode->i_op = &isofs_dir_inode_operations;
489 else if (S_ISLNK(inode->i_mode))
490 inode->i_op = &isofs_symlink_inode_operations;
491 else if (S_ISCHR(inode->i_mode))
492 inode->i_op = &chrdev_inode_operations;
493 else if (S_ISBLK(inode->i_mode))
494 inode->i_op = &blkdev_inode_operations;
495 else if (S_ISFIFO(inode->i_mode))
496 init_fifo(inode);
498 return;
499 fail:
500 /* With a data error we return this information */
501 inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
502 inode->u.isofs_i.i_first_extent = 0;
503 inode->u.isofs_i.i_backlink = 0xffffffff;
504 inode->i_size = 0;
505 inode->i_nlink = 1;
506 inode->i_uid = inode->i_gid = 0;
507 inode->i_mode = S_IFREG; /*Regular file, noone gets to read*/
508 inode->i_op = NULL;
509 return;
512 /* There are times when we need to know the inode number of a parent of
513 a particular directory. When control passes through a routine that
514 has access to the parent information, it fills it into the inode structure,
515 but sometimes the inode gets flushed out of the queue, and someone
516 remmembers the number. When they try to open up again, we have lost
517 the information. The '..' entry on the disc points to the data area
518 for a particular inode, so we can follow these links back up, but since
519 we do not know the inode number, we do not actually know how large the
520 directory is. The disc is almost always correct, and there is
521 enough error checking on the drive itself, but an open ended search
522 makes me a little nervous.
524 The bsd iso filesystem uses the extent number for an inode, and this
525 would work really nicely for us except that the read_inode function
526 would not have any clean way of finding the actual directory record
527 that goes with the file. If we had such info, then it would pay
528 to change the inode numbers and eliminate this function.
531 int isofs_lookup_grandparent(struct inode * parent, int extent)
533 unsigned long bufsize = ISOFS_BUFFER_SIZE(parent);
534 unsigned char bufbits = ISOFS_BUFFER_BITS(parent);
535 unsigned int block,offset;
536 int parent_dir, inode_number;
537 int old_offset;
538 void * cpnt = NULL;
539 int result;
540 struct buffer_head * bh;
541 struct iso_directory_record * de;
543 offset = 0;
544 block = extent << (ISOFS_BLOCK_BITS - bufbits);
545 if (!(bh = bread(parent->i_dev, block, bufsize))) return -1;
547 while (1 == 1) {
548 de = (struct iso_directory_record *) (bh->b_data + offset);
549 if (*((unsigned char *) de) == 0)
551 brelse(bh);
552 return -1;
555 offset += *((unsigned char *) de);
557 if (offset >= bufsize)
559 printk(".. Directory not in first block"
560 " of directory.\n");
561 brelse(bh);
562 return -1;
565 if (de->name_len[0] == 1 && de->name[0] == 1)
567 parent_dir = find_rock_ridge_relocation(de, parent);
568 brelse(bh);
569 break;
572 #ifdef DEBUG
573 printk("Parent dir:%x\n",parent_dir);
574 #endif
575 /* Now we know the extent where the parent dir starts on. We have no
576 idea how long it is, so we just start reading until we either find
577 it or we find some kind of unreasonable circumstance. */
579 result = -1;
581 offset = 0;
582 block = parent_dir << (ISOFS_BLOCK_BITS - bufbits);
583 if (!block || !(bh = bread(parent->i_dev,block, bufsize)))
584 return -1;
586 for(;;)
588 de = (struct iso_directory_record *) (bh->b_data + offset);
589 inode_number = (block << bufbits)+(offset & (bufsize - 1));
591 /* If the length byte is zero, we should move on to the next
592 CDROM sector. If we are at the end of the directory, we
593 kick out of the while loop. */
595 if (*((unsigned char *) de) == 0)
597 brelse(bh);
598 offset = 0;
599 block++;
600 if(block & 1) return -1;
601 if (!block
602 || !(bh = bread(parent->i_dev,block, bufsize)))
603 return -1;
604 continue;
607 /* Make sure that the entire directory record is in the current
608 bh block. If not, we malloc a buffer, and put the two
609 halves together, so that we can cleanly read the block. */
611 old_offset = offset;
612 offset += *((unsigned char *) de);
614 if (offset >= bufsize)
616 if((block & 1) != 0) return -1;
617 cpnt = kmalloc(1<<ISOFS_BLOCK_BITS,GFP_KERNEL);
618 memcpy(cpnt, bh->b_data, bufsize);
619 de = (struct iso_directory_record *)
620 ((char *)cpnt + old_offset);
621 brelse(bh);
622 offset -= bufsize;
623 block++;
624 if (!(bh = bread(parent->i_dev,block,bufsize))) {
625 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
626 return -1;
628 memcpy((char *)cpnt+bufsize, bh->b_data, bufsize);
631 if (find_rock_ridge_relocation(de, parent) == extent){
632 result = inode_number;
633 goto out;
636 if (cpnt) {
637 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
638 cpnt = NULL;
642 /* We go here for any condition we cannot handle.
643 We also drop through to here at the end of the directory. */
645 out:
646 if (cpnt) {
647 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
648 cpnt = NULL;
650 brelse(bh);
651 #ifdef DEBUG
652 printk("Resultant Inode %d\n",result);
653 #endif
654 return result;
657 #ifdef LEAK_CHECK
658 #undef malloc
659 #undef free_s
660 #undef bread
661 #undef brelse
663 void * leak_check_malloc(unsigned int size){
664 void * tmp;
665 check_malloc++;
666 tmp = kmalloc(size, GFP_KERNEL);
667 return tmp;
670 void leak_check_free_s(void * obj, int size){
671 check_malloc--;
672 return kfree_s(obj, size);
675 struct buffer_head * leak_check_bread(int dev, int block, int size){
676 check_bread++;
677 return bread(dev, block, size);
680 void leak_check_brelse(struct buffer_head * bh){
681 check_bread--;
682 return brelse(bh);
685 #endif