This source file includes following definitions.
- isofs_put_super
- parse_options
- isofs_get_last_session
- isofs_read_super
- isofs_statfs
- isofs_bmap
- isofs_read_inode
- isofs_lookup_grandparent
- leak_check_malloc
- leak_check_free_s
- leak_check_bread
- leak_check_brelse
- init_iso9660_fs
- init_module
- cleanup_module
1
2
3
4
5
6
7
8
9
10
11 #include <linux/module.h>
12
13 #include <linux/stat.h>
14 #include <linux/sched.h>
15 #include <linux/iso_fs.h>
16 #include <linux/kernel.h>
17 #include <linux/major.h>
18 #include <linux/mm.h>
19 #include <linux/string.h>
20 #include <linux/locks.h>
21 #include <linux/malloc.h>
22 #include <linux/errno.h>
23 #include <linux/cdrom.h>
24
25 #include <asm/system.h>
26 #include <asm/segment.h>
27
28 #define MULTI_VOLUME
29 #ifdef LEAK_CHECK
30 static int check_malloc = 0;
31 static int check_bread = 0;
32 #endif
33
34 void isofs_put_super(struct super_block *sb)
35 {
36 lock_super(sb);
37
38 #ifdef LEAK_CHECK
39 printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
40 check_malloc, check_bread);
41 #endif
42 sb->s_dev = 0;
43 unlock_super(sb);
44 MOD_DEC_USE_COUNT;
45 return;
46 }
47
48 static struct super_operations isofs_sops = {
49 isofs_read_inode,
50 NULL,
51 NULL,
52 NULL,
53 isofs_put_super,
54 NULL,
55 isofs_statfs,
56 NULL
57 };
58
59 struct iso9660_options{
60 char map;
61 char rock;
62 char cruft;
63 char unhide;
64 unsigned char check;
65 unsigned char conversion;
66 unsigned int blocksize;
67 mode_t mode;
68 gid_t gid;
69 uid_t uid;
70 };
71
72 static int parse_options(char *options, struct iso9660_options * popt)
73 {
74 char *this_char,*value;
75
76 popt->map = 'n';
77 popt->rock = 'y';
78 popt->cruft = 'n';
79 popt->unhide = 'n';
80 popt->check = 's';
81 popt->conversion = 'b';
82 popt->blocksize = 1024;
83 popt->mode = S_IRUGO;
84 popt->gid = 0;
85 popt->uid = 0;
86 if (!options) return 1;
87 for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
88 if (strncmp(this_char,"norock",6) == 0) {
89 popt->rock = 'n';
90 continue;
91 };
92 if (strncmp(this_char,"unhide",6) == 0) {
93 popt->unhide = 'y';
94 continue;
95 };
96 if (strncmp(this_char,"cruft",5) == 0) {
97 popt->cruft = 'y';
98 continue;
99 };
100 if ((value = strchr(this_char,'=')) != NULL)
101 *value++ = 0;
102 if (!strcmp(this_char,"map") && value) {
103 if (value[0] && !value[1] && strchr("on",*value))
104 popt->map = *value;
105 else if (!strcmp(value,"off")) popt->map = 'o';
106 else if (!strcmp(value,"normal")) popt->map = 'n';
107 else return 0;
108 }
109 else if (!strcmp(this_char,"check") && value) {
110 if (value[0] && !value[1] && strchr("rs",*value))
111 popt->check = *value;
112 else if (!strcmp(value,"relaxed")) popt->check = 'r';
113 else if (!strcmp(value,"strict")) popt->check = 's';
114 else return 0;
115 }
116 else if (!strcmp(this_char,"conv") && value) {
117 if (value[0] && !value[1] && strchr("btma",*value))
118 popt->conversion = *value;
119 else if (!strcmp(value,"binary")) popt->conversion = 'b';
120 else if (!strcmp(value,"text")) popt->conversion = 't';
121 else if (!strcmp(value,"mtext")) popt->conversion = 'm';
122 else if (!strcmp(value,"auto")) popt->conversion = 'a';
123 else return 0;
124 }
125 else if (value &&
126 (!strcmp(this_char,"block") ||
127 !strcmp(this_char,"mode") ||
128 !strcmp(this_char,"uid") ||
129 !strcmp(this_char,"gid"))) {
130 char * vpnt = value;
131 unsigned int ivalue;
132 ivalue = 0;
133 while(*vpnt){
134 if(*vpnt < '0' || *vpnt > '9') break;
135 ivalue = ivalue * 10 + (*vpnt - '0');
136 vpnt++;
137 };
138 if (*vpnt) return 0;
139 switch(*this_char) {
140 case 'b':
141 if ( ivalue != 512
142 && ivalue != 1024
143 && ivalue != 2048) return 0;
144 popt->blocksize = ivalue;
145 break;
146 case 'u':
147 popt->uid = ivalue;
148 break;
149 case 'g':
150 popt->gid = ivalue;
151 break;
152 case 'm':
153 popt->mode = ivalue;
154 break;
155 }
156 }
157 else return 1;
158 }
159 return 1;
160 }
161
162
163
164
165 static unsigned int isofs_get_last_session(kdev_t dev)
166 {
167 struct cdrom_multisession ms_info;
168 unsigned int vol_desc_start;
169 struct inode inode_fake;
170 extern struct file_operations * get_blkfops(unsigned int);
171 int i;
172
173 vol_desc_start=0;
174 if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
175 {
176 inode_fake.i_rdev=dev;
177 ms_info.addr_format=CDROM_LBA;
178 set_fs(KERNEL_DS);
179 i=get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
180 NULL,
181 CDROMMULTISESSION,
182 (unsigned long) &ms_info);
183 set_fs(USER_DS);
184 #if 0
185 printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
186 if (i==0)
187 {
188 printk("isofs.inode: XA disk: %s\n", ms_info.xa_flag ? "yes":"no");
189 printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
190 }
191 #endif 0
192 if ((i==0)&&(ms_info.xa_flag)) vol_desc_start=ms_info.addr.lba;
193 }
194 return vol_desc_start;
195 }
196
197 struct super_block *isofs_read_super(struct super_block *s,void *data,
198 int silent)
199 {
200 struct buffer_head *bh=NULL;
201 int iso_blknum;
202 unsigned int blocksize_bits;
203 int high_sierra;
204 kdev_t dev = s->s_dev;
205 unsigned int vol_desc_start;
206 int orig_zonesize;
207
208 struct iso_volume_descriptor *vdp;
209 struct hs_volume_descriptor *hdp;
210
211 struct iso_primary_descriptor *pri = NULL;
212 struct hs_primary_descriptor *h_pri = NULL;
213
214 struct iso_directory_record *rootp;
215
216 struct iso9660_options opt;
217
218 MOD_INC_USE_COUNT;
219
220 if (!parse_options((char *) data,&opt)) {
221 s->s_dev = 0;
222 MOD_DEC_USE_COUNT;
223 return NULL;
224 }
225
226 #if 0
227 printk("map = %c\n", opt.map);
228 printk("rock = %c\n", opt.rock);
229 printk("check = %c\n", opt.check);
230 printk("cruft = %c\n", opt.cruft);
231 printk("unhide = %c\n", opt.unhide);
232 printk("conversion = %c\n", opt.conversion);
233 printk("blocksize = %d\n", opt.blocksize);
234 printk("gid = %d\n", opt.gid);
235 printk("uid = %d\n", opt.uid);
236 #endif
237
238 blocksize_bits = 0;
239 {
240 int i = opt.blocksize;
241 while (i != 1){
242 blocksize_bits++;
243 i >>=1;
244 };
245 };
246 set_blocksize(dev, opt.blocksize);
247
248 lock_super(s);
249
250 s->u.isofs_sb.s_high_sierra = high_sierra = 0;
251
252 vol_desc_start = isofs_get_last_session(dev);
253
254 for (iso_blknum = vol_desc_start+16; iso_blknum < vol_desc_start+100; iso_blknum++) {
255 #if 0
256 printk("isofs.inode: iso_blknum=%d\n", iso_blknum);
257 #endif 0
258 if (!(bh = bread(dev, iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits), opt.blocksize))) {
259 s->s_dev = 0;
260 printk("isofs_read_super: bread failed, dev "
261 "%s iso_blknum %d\n",
262 kdevname(dev), iso_blknum);
263 unlock_super(s);
264 MOD_DEC_USE_COUNT;
265 return NULL;
266 }
267
268 vdp = (struct iso_volume_descriptor *)bh->b_data;
269 hdp = (struct hs_volume_descriptor *)bh->b_data;
270
271
272 if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
273 if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
274 goto out;
275 if (isonum_711 (hdp->type) == ISO_VD_END)
276 goto out;
277
278 s->u.isofs_sb.s_high_sierra = 1;
279 high_sierra = 1;
280 opt.rock = 'n';
281 h_pri = (struct hs_primary_descriptor *)vdp;
282 break;
283 };
284
285 if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
286 if (isonum_711 (vdp->type) != ISO_VD_PRIMARY)
287 goto out;
288 if (isonum_711 (vdp->type) == ISO_VD_END)
289 goto out;
290
291 pri = (struct iso_primary_descriptor *)vdp;
292 break;
293 };
294
295 brelse(bh);
296 }
297 if(iso_blknum == vol_desc_start + 100) {
298 if (!silent)
299 printk("Unable to identify CD-ROM format.\n");
300 s->s_dev = 0;
301 unlock_super(s);
302 MOD_DEC_USE_COUNT;
303 return NULL;
304 };
305
306
307 if(high_sierra){
308 rootp = (struct iso_directory_record *) h_pri->root_directory_record;
309 if (isonum_723 (h_pri->volume_set_size) != 1) {
310 #ifndef MULTI_VOLUME
311 printk("Multi-volume disks not (yet) supported.\n");
312 goto out;
313 #endif
314 };
315 s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
316 s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
317 s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
318 } else {
319 rootp = (struct iso_directory_record *) pri->root_directory_record;
320 if (isonum_723 (pri->volume_set_size) != 1) {
321 #ifndef MULTI_VOLUME
322 printk("Multi-volume disks not (yet) supported.\n");
323 goto out;
324 #endif
325 };
326 s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
327 s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
328 s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
329 }
330
331 s->u.isofs_sb.s_ninodes = 0;
332
333
334
335 orig_zonesize = s -> u.isofs_sb.s_log_zone_size;
336 switch (s -> u.isofs_sb.s_log_zone_size)
337 { case 512: s -> u.isofs_sb.s_log_zone_size = 9; break;
338 case 1024: s -> u.isofs_sb.s_log_zone_size = 10; break;
339 case 2048: s -> u.isofs_sb.s_log_zone_size = 11; break;
340
341 default:
342 printk("Bad logical zone size %ld\n", s -> u.isofs_sb.s_log_zone_size);
343 goto out;
344 }
345
346
347
348 s->u.isofs_sb.s_firstdatazone = ((isonum_733 (rootp->extent) +
349 isonum_711 (rootp->ext_attr_length))
350 << s -> u.isofs_sb.s_log_zone_size);
351 s->s_magic = ISOFS_SUPER_MAGIC;
352
353
354
355
356
357
358 s->s_flags |= MS_RDONLY ;
359
360 brelse(bh);
361
362 printk(KERN_DEBUG "Max size:%ld Log zone size:%ld\n",
363 s->u.isofs_sb.s_max_size,
364 1UL << s->u.isofs_sb.s_log_zone_size);
365 printk(KERN_DEBUG "First datazone:%ld Root inode number %d\n",
366 s->u.isofs_sb.s_firstdatazone >> s -> u.isofs_sb.s_log_zone_size,
367 (isonum_733(rootp->extent) + isonum_711(rootp->ext_attr_length))
368 << s -> u.isofs_sb.s_log_zone_size);
369 if(high_sierra) printk(KERN_DEBUG "Disc in High Sierra format.\n");
370 unlock_super(s);
371
372
373
374
375
376
377
378 if( orig_zonesize < opt.blocksize )
379 {
380 opt.blocksize = orig_zonesize;
381 blocksize_bits = 0;
382 {
383 int i = opt.blocksize;
384 while (i != 1){
385 blocksize_bits++;
386 i >>=1;
387 }
388 }
389 set_blocksize(dev, opt.blocksize);
390 printk(KERN_DEBUG "Forcing new log zone size:%d\n", opt.blocksize);
391 }
392
393 s->s_dev = dev;
394 s->s_op = &isofs_sops;
395 s->u.isofs_sb.s_mapping = opt.map;
396 s->u.isofs_sb.s_rock = (opt.rock == 'y' ? 1 : 0);
397 s->u.isofs_sb.s_name_check = opt.check;
398 s->u.isofs_sb.s_conversion = opt.conversion;
399 s->u.isofs_sb.s_cruft = opt.cruft;
400 s->u.isofs_sb.s_unhide = opt.unhide;
401 s->u.isofs_sb.s_uid = opt.uid;
402 s->u.isofs_sb.s_gid = opt.gid;
403
404
405
406
407 s->u.isofs_sb.s_mode = opt.mode & 0777;
408 s->s_blocksize = opt.blocksize;
409 s->s_blocksize_bits = blocksize_bits;
410 s->s_mounted = iget(s, (isonum_733(rootp->extent) +
411 isonum_711(rootp->ext_attr_length))
412 << s -> u.isofs_sb.s_log_zone_size);
413 unlock_super(s);
414
415 if (!(s->s_mounted)) {
416 s->s_dev = 0;
417 printk("get root inode failed\n");
418 MOD_DEC_USE_COUNT;
419 return NULL;
420 }
421
422 if(!check_disk_change(s->s_dev)) {
423 return s;
424 }
425 out:
426 brelse(bh);
427 s->s_dev = 0;
428 unlock_super(s);
429 MOD_DEC_USE_COUNT;
430 return NULL;
431 }
432
433 void isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
434 {
435 struct statfs tmp;
436
437 tmp.f_type = ISOFS_SUPER_MAGIC;
438 tmp.f_bsize = sb->s_blocksize;
439 tmp.f_blocks = (sb->u.isofs_sb.s_nzones
440 << (sb->u.isofs_sb.s_log_zone_size - sb->s_blocksize_bits));
441 tmp.f_bfree = 0;
442 tmp.f_bavail = 0;
443 tmp.f_files = sb->u.isofs_sb.s_ninodes;
444 tmp.f_ffree = 0;
445 tmp.f_namelen = NAME_MAX;
446 memcpy_tofs(buf, &tmp, bufsiz);
447 }
448
449 int isofs_bmap(struct inode * inode,int block)
450 {
451
452 if (block<0) {
453 printk("_isofs_bmap: block<0");
454 return 0;
455 }
456 return (inode->u.isofs_i.i_first_extent >> ISOFS_BUFFER_BITS(inode)) + block;
457 }
458
459 void isofs_read_inode(struct inode * inode)
460 {
461 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
462 struct buffer_head * bh;
463 struct iso_directory_record * raw_inode;
464 unsigned char *pnt = NULL;
465 void *cpnt = NULL;
466 int high_sierra;
467 int block;
468 int volume_seq_no ;
469 int i;
470
471 block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
472 if (!(bh=bread(inode->i_dev,block, bufsize))) {
473 printk("unable to read i-node block");
474 goto fail;
475 }
476
477 pnt = ((unsigned char *) bh->b_data
478 + (inode->i_ino & (bufsize - 1)));
479 raw_inode = ((struct iso_directory_record *) pnt);
480 high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
481
482 if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){
483 int frag1, offset;
484
485 offset = (inode->i_ino & (bufsize - 1));
486 frag1 = bufsize - offset;
487 cpnt = kmalloc(*pnt,GFP_KERNEL);
488 if (cpnt == NULL) {
489 printk(KERN_INFO "NoMem ISO inode %lu\n",inode->i_ino);
490 brelse(bh);
491 goto fail;
492 }
493 memcpy(cpnt, bh->b_data + offset, frag1);
494 brelse(bh);
495 if (!(bh = bread(inode->i_dev,++block, bufsize))) {
496 kfree(cpnt);
497 printk("unable to read i-node block");
498 goto fail;
499 }
500 offset += *pnt - bufsize;
501 memcpy((char *)cpnt+frag1, bh->b_data, offset);
502 pnt = ((unsigned char *) cpnt);
503 raw_inode = ((struct iso_directory_record *) pnt);
504 }
505
506 if (raw_inode->flags[-high_sierra] & 2) {
507 inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
508 inode->i_nlink = 1;
509
510
511
512
513 } else {
514 inode->i_mode = inode->i_sb->u.isofs_sb.s_mode;
515 inode->i_nlink = 1;
516 inode->i_mode |= S_IFREG;
517
518 for(i=0; i< raw_inode->name_len[0]; i++)
519 if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
520 break;
521 if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';')
522 inode->i_mode |= S_IXUGO;
523 }
524 inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
525 inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;
526 inode->i_size = isonum_733 (raw_inode->size);
527
528
529
530 if((inode->i_size < 0 || inode->i_size > 800000000) &&
531 inode->i_sb->u.isofs_sb.s_cruft == 'n') {
532 printk("Warning: defective cdrom. Enabling \"cruft\" mount option.\n");
533 inode->i_sb->u.isofs_sb.s_cruft = 'y';
534 }
535
536
537
538
539
540 if(inode->i_sb->u.isofs_sb.s_cruft == 'y' &&
541 inode->i_size & 0xff000000){
542
543 inode->i_size &= 0x00ffffff;
544 }
545
546 if (raw_inode->interleave[0]) {
547 printk("Interleaved files not (yet) supported.\n");
548 inode->i_size = 0;
549 }
550
551
552
553 if(raw_inode->file_unit_size[0] != 0){
554 printk("File unit size != 0 for ISO file (%ld).\n",inode->i_ino);
555 }
556
557
558
559 #ifdef DEBUG
560 if((raw_inode->flags[-high_sierra] & ~2)!= 0){
561 printk("Unusual flag settings for ISO file (%ld %x).\n",
562 inode->i_ino, raw_inode->flags[-high_sierra]);
563 }
564 #endif
565
566 #ifdef DEBUG
567 printk("Get inode %d: %d %d: %d\n",inode->i_ino, block,
568 ((int)pnt) & 0x3ff, inode->i_size);
569 #endif
570
571 inode->i_mtime = inode->i_atime = inode->i_ctime =
572 iso_date(raw_inode->date, high_sierra);
573
574 inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) +
575 isonum_711 (raw_inode->ext_attr_length))
576 << inode -> i_sb -> u.isofs_sb.s_log_zone_size;
577
578 inode->u.isofs_i.i_backlink = 0xffffffff;
579 switch (inode->i_sb->u.isofs_sb.s_conversion){
580 case 'a':
581 inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN;
582 break;
583 case 'b':
584 inode->u.isofs_i.i_file_format = ISOFS_FILE_BINARY;
585 break;
586 case 't':
587 inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT;
588 break;
589 case 'm':
590 inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT_M;
591 break;
592 }
593
594
595
596
597 if (!high_sierra)
598 parse_rock_ridge_inode(raw_inode, inode);
599
600 #ifdef DEBUG
601 printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
602 #endif
603 brelse(bh);
604
605 inode->i_op = NULL;
606
607
608 volume_seq_no = isonum_723 (raw_inode->volume_sequence_number) ;
609
610
611
612
613
614
615
616 if (inode->i_sb->u.isofs_sb.s_cruft == 'n' &&
617 (volume_seq_no != 0) && (volume_seq_no != 1)) {
618 printk("Warning: defective cdrom. Enabling \"cruft\" mount option.\n");
619 inode->i_sb->u.isofs_sb.s_cruft = 'y';
620 }
621
622 #ifndef MULTI_VOLUME
623 if (inode->i_sb->u.isofs_sb.s_cruft != 'y' &&
624 (volume_seq_no != 0) && (volume_seq_no != 1)) {
625 printk("Multi volume CD somehow got mounted.\n");
626 } else
627 #endif
628 {
629 if (S_ISREG(inode->i_mode))
630 inode->i_op = &isofs_file_inode_operations;
631 else if (S_ISDIR(inode->i_mode))
632 inode->i_op = &isofs_dir_inode_operations;
633 else if (S_ISLNK(inode->i_mode))
634 inode->i_op = &isofs_symlink_inode_operations;
635 else if (S_ISCHR(inode->i_mode))
636 inode->i_op = &chrdev_inode_operations;
637 else if (S_ISBLK(inode->i_mode))
638 inode->i_op = &blkdev_inode_operations;
639 else if (S_ISFIFO(inode->i_mode))
640 init_fifo(inode);
641 }
642 if (cpnt) {
643 kfree (cpnt);
644 cpnt = NULL;
645 }
646 return;
647 fail:
648
649 inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
650 inode->u.isofs_i.i_first_extent = 0;
651 inode->u.isofs_i.i_backlink = 0xffffffff;
652 inode->i_size = 0;
653 inode->i_nlink = 1;
654 inode->i_uid = inode->i_gid = 0;
655 inode->i_mode = S_IFREG;
656 inode->i_op = NULL;
657 return;
658 }
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679 int isofs_lookup_grandparent(struct inode * parent, int extent)
680 {
681 unsigned long bufsize = ISOFS_BUFFER_SIZE(parent);
682 unsigned char bufbits = ISOFS_BUFFER_BITS(parent);
683 unsigned int block,offset;
684 int parent_dir, inode_number;
685 int old_offset;
686 void * cpnt = NULL;
687 int result;
688 int directory_size;
689 struct buffer_head * bh;
690 struct iso_directory_record * de;
691
692 offset = 0;
693 block = extent << (ISOFS_ZONE_BITS(parent) - bufbits);
694 if (!(bh = bread(parent->i_dev, block, bufsize))) return -1;
695
696 while (1 == 1) {
697 de = (struct iso_directory_record *) (bh->b_data + offset);
698 if (*((unsigned char *) de) == 0)
699 {
700 brelse(bh);
701 printk("Directory .. not found\n");
702 return -1;
703 }
704
705 offset += *((unsigned char *) de);
706
707 if (offset >= bufsize)
708 {
709 printk(".. Directory not in first block"
710 " of directory.\n");
711 brelse(bh);
712 return -1;
713 }
714
715 if (de->name_len[0] == 1 && de->name[0] == 1)
716 {
717 parent_dir = find_rock_ridge_relocation(de, parent);
718 directory_size = isonum_733 (de->size);
719 brelse(bh);
720 break;
721 }
722 }
723 #ifdef DEBUG
724 printk("Parent dir:%x\n",parent_dir);
725 #endif
726
727
728 result = -1;
729
730 offset = 0;
731 block = parent_dir << (ISOFS_ZONE_BITS(parent) - bufbits);
732 if (!block || !(bh = bread(parent->i_dev,block, bufsize)))
733 {
734 return -1;
735 }
736
737 for(;;)
738 {
739 de = (struct iso_directory_record *) (bh->b_data + offset);
740 inode_number = (block << bufbits)+(offset & (bufsize - 1));
741
742
743
744
745
746 if (*((unsigned char *) de) == 0)
747 {
748 brelse(bh);
749 offset = 0;
750 block++;
751 directory_size -= bufsize;
752 if(directory_size < 0) return -1;
753 if((block & 1) && (ISOFS_ZONE_BITS(parent) - bufbits) == 1)
754 {
755 return -1;
756 }
757 if((block & 3) && (ISOFS_ZONE_BITS(parent) - bufbits) == 2)
758 {
759 return -1;
760 }
761 if (!block
762 || !(bh = bread(parent->i_dev,block, bufsize)))
763 {
764 return -1;
765 }
766 continue;
767 }
768
769
770
771
772
773 old_offset = offset;
774 offset += *((unsigned char *) de);
775
776 if (offset >= bufsize)
777 {
778 unsigned int frag1;
779 frag1 = bufsize - old_offset;
780 cpnt = kmalloc(*((unsigned char *) de),GFP_KERNEL);
781 if (!cpnt) return -1;
782 memcpy(cpnt, bh->b_data + old_offset, frag1);
783 de = (struct iso_directory_record *) ((char *)cpnt);
784 brelse(bh);
785 offset -= bufsize;
786 directory_size -= bufsize;
787 if(directory_size < 0)
788 {
789 printk("Directory size < 0\n");
790 return -1;
791 }
792 block++;
793 if(!(bh = bread(parent->i_dev,block,bufsize))) {
794 kfree(cpnt);
795 return -1;
796 };
797 memcpy((char *)cpnt+frag1, bh->b_data, offset);
798 }
799
800 if (find_rock_ridge_relocation(de, parent) == extent){
801 result = inode_number;
802 goto out;
803 }
804
805 if (cpnt) {
806 kfree(cpnt);
807 cpnt = NULL;
808 }
809 }
810
811
812
813
814 out:
815 if (cpnt) {
816 kfree(cpnt);
817 cpnt = NULL;
818 }
819 brelse(bh);
820 #ifdef DEBUG
821 printk("Resultant Inode %d\n",result);
822 #endif
823 return result;
824 }
825
826 #ifdef LEAK_CHECK
827 #undef malloc
828 #undef free_s
829 #undef bread
830 #undef brelse
831
832 void * leak_check_malloc(unsigned int size){
833 void * tmp;
834 check_malloc++;
835 tmp = kmalloc(size, GFP_KERNEL);
836 return tmp;
837 }
838
839 void leak_check_free_s(void * obj, int size){
840 check_malloc--;
841 return kfree_s(obj, size);
842 }
843
844 struct buffer_head * leak_check_bread(int dev, int block, int size){
845 check_bread++;
846 return bread(dev, block, size);
847 }
848
849 void leak_check_brelse(struct buffer_head * bh){
850 check_bread--;
851 return brelse(bh);
852 }
853
854 #endif
855
856 static struct file_system_type iso9660_fs_type = {
857 isofs_read_super, "iso9660", 1, NULL
858 };
859
860 int init_iso9660_fs(void)
861 {
862 return register_filesystem(&iso9660_fs_type);
863 }
864
865 #ifdef MODULE
866 int init_module(void)
867 {
868 int status;
869
870 if ((status = init_iso9660_fs()) == 0)
871 register_symtab(0);
872 return status;
873 }
874
875 void cleanup_module(void)
876 {
877 unregister_filesystem(&iso9660_fs_type);
878 }
879
880 #endif
881