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;
255 iso_blknum < vol_desc_start+100; iso_blknum++) {
256 int b = iso_blknum << (ISOFS_BLOCK_BITS-blocksize_bits);
257
258 if (!(bh = bread(dev,b,opt.blocksize))) {
259 s->s_dev = 0;
260 printk("isofs_read_super: bread failed, dev "
261 "%s iso_blknum %d block %d\n",
262 kdevname(dev), iso_blknum, b);
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 if(high_sierra){
307 rootp = (struct iso_directory_record *) h_pri->root_directory_record;
308 if (isonum_723 (h_pri->volume_set_size) != 1) {
309 #ifndef MULTI_VOLUME
310 printk("Multi-volume disks not (yet) supported.\n");
311 goto out;
312 #endif
313 }
314 s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
315 s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
316 s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
317 } else {
318 rootp = (struct iso_directory_record *) pri->root_directory_record;
319 if (isonum_723 (pri->volume_set_size) != 1) {
320 #ifndef MULTI_VOLUME
321 printk("Multi-volume disks not (yet) supported.\n");
322 goto out;
323 #endif
324 }
325 s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
326 s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
327 s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
328 }
329
330 s->u.isofs_sb.s_ninodes = 0;
331
332
333
334 orig_zonesize = s -> u.isofs_sb.s_log_zone_size;
335 switch (s -> u.isofs_sb.s_log_zone_size)
336 { case 512: s -> u.isofs_sb.s_log_zone_size = 9; break;
337 case 1024: s -> u.isofs_sb.s_log_zone_size = 10; break;
338 case 2048: s -> u.isofs_sb.s_log_zone_size = 11; break;
339
340 default:
341 printk("Bad logical zone size %ld\n", s -> u.isofs_sb.s_log_zone_size);
342 goto out;
343 }
344
345
346
347 s->u.isofs_sb.s_firstdatazone = ((isonum_733 (rootp->extent) +
348 isonum_711 (rootp->ext_attr_length))
349 << s -> u.isofs_sb.s_log_zone_size);
350 s->s_magic = ISOFS_SUPER_MAGIC;
351
352
353
354
355
356
357 s->s_flags |= MS_RDONLY ;
358
359 brelse(bh);
360
361 printk(KERN_DEBUG "Max size:%ld Log zone size:%ld\n",
362 s->u.isofs_sb.s_max_size,
363 1UL << s->u.isofs_sb.s_log_zone_size);
364 printk(KERN_DEBUG "First datazone:%ld Root inode number %d\n",
365 s->u.isofs_sb.s_firstdatazone >> s -> u.isofs_sb.s_log_zone_size,
366 (isonum_733(rootp->extent) + isonum_711(rootp->ext_attr_length))
367 << s -> u.isofs_sb.s_log_zone_size);
368 if(high_sierra) printk(KERN_DEBUG "Disc in High Sierra format.\n");
369 unlock_super(s);
370
371
372
373
374
375
376
377 if( orig_zonesize < opt.blocksize )
378 {
379 opt.blocksize = orig_zonesize;
380 blocksize_bits = 0;
381 {
382 int i = opt.blocksize;
383 while (i != 1){
384 blocksize_bits++;
385 i >>=1;
386 }
387 }
388 set_blocksize(dev, opt.blocksize);
389 printk(KERN_DEBUG "Forcing new log zone size:%d\n", opt.blocksize);
390 }
391
392 s->s_dev = dev;
393 s->s_op = &isofs_sops;
394 s->u.isofs_sb.s_mapping = opt.map;
395 s->u.isofs_sb.s_rock = (opt.rock == 'y' ? 1 : 0);
396 s->u.isofs_sb.s_name_check = opt.check;
397 s->u.isofs_sb.s_conversion = opt.conversion;
398 s->u.isofs_sb.s_cruft = opt.cruft;
399 s->u.isofs_sb.s_unhide = opt.unhide;
400 s->u.isofs_sb.s_uid = opt.uid;
401 s->u.isofs_sb.s_gid = opt.gid;
402
403
404
405
406 s->u.isofs_sb.s_mode = opt.mode & 0777;
407 s->s_blocksize = opt.blocksize;
408 s->s_blocksize_bits = blocksize_bits;
409 s->s_mounted = iget(s, (isonum_733(rootp->extent) +
410 isonum_711(rootp->ext_attr_length))
411 << s -> u.isofs_sb.s_log_zone_size);
412 unlock_super(s);
413
414 if (!(s->s_mounted)) {
415 s->s_dev = 0;
416 printk("get root inode failed\n");
417 MOD_DEC_USE_COUNT;
418 return NULL;
419 }
420
421 if(!check_disk_change(s->s_dev)) {
422 return s;
423 }
424 out:
425 brelse(bh);
426 s->s_dev = 0;
427 unlock_super(s);
428 MOD_DEC_USE_COUNT;
429 return NULL;
430 }
431
432 void isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
433 {
434 struct statfs tmp;
435
436 tmp.f_type = ISOFS_SUPER_MAGIC;
437 tmp.f_bsize = sb->s_blocksize;
438 tmp.f_blocks = (sb->u.isofs_sb.s_nzones
439 << (sb->u.isofs_sb.s_log_zone_size - sb->s_blocksize_bits));
440 tmp.f_bfree = 0;
441 tmp.f_bavail = 0;
442 tmp.f_files = sb->u.isofs_sb.s_ninodes;
443 tmp.f_ffree = 0;
444 tmp.f_namelen = NAME_MAX;
445 memcpy_tofs(buf, &tmp, bufsiz);
446 }
447
448 int isofs_bmap(struct inode * inode,int block)
449 {
450
451 if (block<0) {
452 printk("_isofs_bmap: block<0");
453 return 0;
454 }
455 return (inode->u.isofs_i.i_first_extent >> ISOFS_BUFFER_BITS(inode)) + block;
456 }
457
458 void isofs_read_inode(struct inode * inode)
459 {
460 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
461 struct buffer_head * bh;
462 struct iso_directory_record * raw_inode;
463 unsigned char *pnt = NULL;
464 void *cpnt = NULL;
465 int high_sierra;
466 int block;
467 int volume_seq_no ;
468 int i;
469
470 block = inode->i_ino >> ISOFS_BUFFER_BITS(inode);
471 if (!(bh=bread(inode->i_dev,block, bufsize))) {
472 printk("unable to read i-node block");
473 goto fail;
474 }
475
476 pnt = ((unsigned char *) bh->b_data
477 + (inode->i_ino & (bufsize - 1)));
478 raw_inode = ((struct iso_directory_record *) pnt);
479 high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
480
481 if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){
482 int frag1, offset;
483
484 offset = (inode->i_ino & (bufsize - 1));
485 frag1 = bufsize - offset;
486 cpnt = kmalloc(*pnt,GFP_KERNEL);
487 if (cpnt == NULL) {
488 printk(KERN_INFO "NoMem ISO inode %lu\n",inode->i_ino);
489 brelse(bh);
490 goto fail;
491 }
492 memcpy(cpnt, bh->b_data + offset, frag1);
493 brelse(bh);
494 if (!(bh = bread(inode->i_dev,++block, bufsize))) {
495 kfree(cpnt);
496 printk("unable to read i-node block");
497 goto fail;
498 }
499 offset += *pnt - bufsize;
500 memcpy((char *)cpnt+frag1, bh->b_data, offset);
501 pnt = ((unsigned char *) cpnt);
502 raw_inode = ((struct iso_directory_record *) pnt);
503 }
504
505 if (raw_inode->flags[-high_sierra] & 2) {
506 inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
507 inode->i_nlink = 1;
508
509
510
511
512 } else {
513 inode->i_mode = inode->i_sb->u.isofs_sb.s_mode;
514 inode->i_nlink = 1;
515 inode->i_mode |= S_IFREG;
516
517 for(i=0; i< raw_inode->name_len[0]; i++)
518 if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
519 break;
520 if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';')
521 inode->i_mode |= S_IXUGO;
522 }
523 inode->i_uid = inode->i_sb->u.isofs_sb.s_uid;
524 inode->i_gid = inode->i_sb->u.isofs_sb.s_gid;
525 inode->i_size = isonum_733 (raw_inode->size);
526
527
528
529 if((inode->i_size < 0 || inode->i_size > 800000000) &&
530 inode->i_sb->u.isofs_sb.s_cruft == 'n') {
531 printk("Warning: defective cdrom. Enabling \"cruft\" mount option.\n");
532 inode->i_sb->u.isofs_sb.s_cruft = 'y';
533 }
534
535
536
537
538
539 if(inode->i_sb->u.isofs_sb.s_cruft == 'y' &&
540 inode->i_size & 0xff000000){
541
542 inode->i_size &= 0x00ffffff;
543 }
544
545 if (raw_inode->interleave[0]) {
546 printk("Interleaved files not (yet) supported.\n");
547 inode->i_size = 0;
548 }
549
550
551
552 if(raw_inode->file_unit_size[0] != 0){
553 printk("File unit size != 0 for ISO file (%ld).\n",inode->i_ino);
554 }
555
556
557
558 #ifdef DEBUG
559 if((raw_inode->flags[-high_sierra] & ~2)!= 0){
560 printk("Unusual flag settings for ISO file (%ld %x).\n",
561 inode->i_ino, raw_inode->flags[-high_sierra]);
562 }
563 #endif
564
565 #ifdef DEBUG
566 printk("Get inode %d: %d %d: %d\n",inode->i_ino, block,
567 ((int)pnt) & 0x3ff, inode->i_size);
568 #endif
569
570 inode->i_mtime = inode->i_atime = inode->i_ctime =
571 iso_date(raw_inode->date, high_sierra);
572
573 inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) +
574 isonum_711 (raw_inode->ext_attr_length))
575 << inode -> i_sb -> u.isofs_sb.s_log_zone_size;
576
577 inode->u.isofs_i.i_backlink = 0xffffffff;
578 switch (inode->i_sb->u.isofs_sb.s_conversion){
579 case 'a':
580 inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN;
581 break;
582 case 'b':
583 inode->u.isofs_i.i_file_format = ISOFS_FILE_BINARY;
584 break;
585 case 't':
586 inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT;
587 break;
588 case 'm':
589 inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT_M;
590 break;
591 }
592
593
594
595
596 if (!high_sierra)
597 parse_rock_ridge_inode(raw_inode, inode);
598
599 #ifdef DEBUG
600 printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
601 #endif
602 brelse(bh);
603
604 inode->i_op = NULL;
605
606
607 volume_seq_no = isonum_723 (raw_inode->volume_sequence_number) ;
608
609
610
611
612
613
614
615 if (inode->i_sb->u.isofs_sb.s_cruft == 'n' &&
616 (volume_seq_no != 0) && (volume_seq_no != 1)) {
617 printk("Warning: defective cdrom. Enabling \"cruft\" mount option.\n");
618 inode->i_sb->u.isofs_sb.s_cruft = 'y';
619 }
620
621 #ifndef MULTI_VOLUME
622 if (inode->i_sb->u.isofs_sb.s_cruft != 'y' &&
623 (volume_seq_no != 0) && (volume_seq_no != 1)) {
624 printk("Multi volume CD somehow got mounted.\n");
625 } else
626 #endif
627 {
628 if (S_ISREG(inode->i_mode))
629 inode->i_op = &isofs_file_inode_operations;
630 else if (S_ISDIR(inode->i_mode))
631 inode->i_op = &isofs_dir_inode_operations;
632 else if (S_ISLNK(inode->i_mode))
633 inode->i_op = &isofs_symlink_inode_operations;
634 else if (S_ISCHR(inode->i_mode))
635 inode->i_op = &chrdev_inode_operations;
636 else if (S_ISBLK(inode->i_mode))
637 inode->i_op = &blkdev_inode_operations;
638 else if (S_ISFIFO(inode->i_mode))
639 init_fifo(inode);
640 }
641 if (cpnt) {
642 kfree (cpnt);
643 cpnt = NULL;
644 }
645 return;
646 fail:
647
648 inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
649 inode->u.isofs_i.i_first_extent = 0;
650 inode->u.isofs_i.i_backlink = 0xffffffff;
651 inode->i_size = 0;
652 inode->i_nlink = 1;
653 inode->i_uid = inode->i_gid = 0;
654 inode->i_mode = S_IFREG;
655 inode->i_op = NULL;
656 return;
657 }
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678 int isofs_lookup_grandparent(struct inode * parent, int extent)
679 {
680 unsigned long bufsize = ISOFS_BUFFER_SIZE(parent);
681 unsigned char bufbits = ISOFS_BUFFER_BITS(parent);
682 unsigned int block,offset;
683 int parent_dir, inode_number;
684 int old_offset;
685 void * cpnt = NULL;
686 int result;
687 int directory_size;
688 struct buffer_head * bh;
689 struct iso_directory_record * de;
690
691 offset = 0;
692 block = extent << (ISOFS_ZONE_BITS(parent) - bufbits);
693 if (!(bh = bread(parent->i_dev, block, bufsize))) return -1;
694
695 while (1 == 1) {
696 de = (struct iso_directory_record *) (bh->b_data + offset);
697 if (*((unsigned char *) de) == 0)
698 {
699 brelse(bh);
700 printk("Directory .. not found\n");
701 return -1;
702 }
703
704 offset += *((unsigned char *) de);
705
706 if (offset >= bufsize)
707 {
708 printk(".. Directory not in first block"
709 " of directory.\n");
710 brelse(bh);
711 return -1;
712 }
713
714 if (de->name_len[0] == 1 && de->name[0] == 1)
715 {
716 parent_dir = find_rock_ridge_relocation(de, parent);
717 directory_size = isonum_733 (de->size);
718 brelse(bh);
719 break;
720 }
721 }
722 #ifdef DEBUG
723 printk("Parent dir:%x\n",parent_dir);
724 #endif
725
726
727 result = -1;
728
729 offset = 0;
730 block = parent_dir << (ISOFS_ZONE_BITS(parent) - bufbits);
731 if (!block || !(bh = bread(parent->i_dev,block, bufsize)))
732 {
733 return -1;
734 }
735
736 for(;;)
737 {
738 de = (struct iso_directory_record *) (bh->b_data + offset);
739 inode_number = (block << bufbits)+(offset & (bufsize - 1));
740
741
742
743
744
745 if (*((unsigned char *) de) == 0)
746 {
747 brelse(bh);
748 offset = 0;
749 block++;
750 directory_size -= bufsize;
751 if(directory_size < 0) return -1;
752 if((block & 1) && (ISOFS_ZONE_BITS(parent) - bufbits) == 1)
753 {
754 return -1;
755 }
756 if((block & 3) && (ISOFS_ZONE_BITS(parent) - bufbits) == 2)
757 {
758 return -1;
759 }
760 if (!block
761 || !(bh = bread(parent->i_dev,block, bufsize)))
762 {
763 return -1;
764 }
765 continue;
766 }
767
768
769
770
771
772 old_offset = offset;
773 offset += *((unsigned char *) de);
774
775 if (offset >= bufsize)
776 {
777 unsigned int frag1;
778 frag1 = bufsize - old_offset;
779 cpnt = kmalloc(*((unsigned char *) de),GFP_KERNEL);
780 if (!cpnt) return -1;
781 memcpy(cpnt, bh->b_data + old_offset, frag1);
782 de = (struct iso_directory_record *) ((char *)cpnt);
783 brelse(bh);
784 offset -= bufsize;
785 directory_size -= bufsize;
786 if(directory_size < 0)
787 {
788 printk("Directory size < 0\n");
789 return -1;
790 }
791 block++;
792 if(!(bh = bread(parent->i_dev,block,bufsize))) {
793 kfree(cpnt);
794 return -1;
795 }
796 memcpy((char *)cpnt+frag1, bh->b_data, offset);
797 }
798
799 if (find_rock_ridge_relocation(de, parent) == extent){
800 result = inode_number;
801 goto out;
802 }
803
804 if (cpnt) {
805 kfree(cpnt);
806 cpnt = NULL;
807 }
808 }
809
810
811
812
813 out:
814 if (cpnt) {
815 kfree(cpnt);
816 cpnt = NULL;
817 }
818 brelse(bh);
819 #ifdef DEBUG
820 printk("Resultant Inode %d\n",result);
821 #endif
822 return result;
823 }
824
825 #ifdef LEAK_CHECK
826 #undef malloc
827 #undef free_s
828 #undef bread
829 #undef brelse
830
831 void * leak_check_malloc(unsigned int size){
832 void * tmp;
833 check_malloc++;
834 tmp = kmalloc(size, GFP_KERNEL);
835 return tmp;
836 }
837
838 void leak_check_free_s(void * obj, int size){
839 check_malloc--;
840 return kfree_s(obj, size);
841 }
842
843 struct buffer_head * leak_check_bread(int dev, int block, int size){
844 check_bread++;
845 return bread(dev, block, size);
846 }
847
848 void leak_check_brelse(struct buffer_head * bh){
849 check_bread--;
850 return brelse(bh);
851 }
852
853 #endif
854
855 static struct file_system_type iso9660_fs_type = {
856 isofs_read_super, "iso9660", 1, NULL
857 };
858
859 int init_iso9660_fs(void)
860 {
861 return register_filesystem(&iso9660_fs_type);
862 }
863
864 #ifdef MODULE
865 int init_module(void)
866 {
867 int status;
868
869 if ((status = init_iso9660_fs()) == 0)
870 register_symtab(0);
871 return status;
872 }
873
874 void cleanup_module(void)
875 {
876 unregister_filesystem(&iso9660_fs_type);
877 }
878
879 #endif
880