This source file includes following definitions.
- isofs_put_super
- parse_options
- 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
1
2
3
4
5
6
7
8 #include <linux/config.h>
9 #include <linux/stat.h>
10 #include <linux/sched.h>
11 #include <linux/iso_fs.h>
12 #include <linux/kernel.h>
13 #include <linux/mm.h>
14 #include <linux/string.h>
15 #include <linux/locks.h>
16
17 #include <asm/system.h>
18 #include <asm/segment.h>
19 #include <linux/errno.h>
20
21 #ifndef CONFIG_BLK_DEV_SR
22 #error The iso9660 filesystem can only be used with CDROM.
23 #endif
24
25 extern int check_cdrom_media_change(int, int);
26
27 #ifdef LEAK_CHECK
28 static int check_malloc = 0;
29 static int check_bread = 0;
30 #endif
31
32 void isofs_put_super(struct super_block *sb)
33 {
34 lock_super(sb);
35
36 #ifdef LEAK_CHECK
37 printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
38 check_malloc, check_bread);
39 #endif
40 sb->s_dev = 0;
41 unlock_super(sb);
42 return;
43 }
44
45 static struct super_operations isofs_sops = {
46 isofs_read_inode,
47 NULL,
48 NULL,
49 NULL,
50 isofs_put_super,
51 NULL,
52 isofs_statfs
53 };
54
55
56
57 static int parse_options(char *options,char *map,char *conversion, char * rock, char * cruft)
58 {
59 char *this,*value;
60
61 *map = 'n';
62 *rock = 'y';
63 *cruft = 'n';
64 *conversion = 'a';
65 if (!options) return 1;
66 for (this = strtok(options,","); this; this = strtok(NULL,",")) {
67 if (strncmp(this,"norock",6) == 0) {
68 *rock = 'n';
69 continue;
70 };
71 if (strncmp(this,"cruft",5) == 0) {
72 *cruft = 'y';
73 continue;
74 };
75 if ((value = strchr(this,'=')) != NULL)
76 *value++ = 0;
77 if (!strcmp(this,"map") && value) {
78 if (value[0] && !value[1] && strchr("on",*value))
79 *map = *value;
80 else if (!strcmp(value,"off")) *map = 'o';
81 else if (!strcmp(value,"normal")) *map = 'n';
82 else return 0;
83 }
84 else if (!strcmp(this,"conv") && value) {
85 if (value[0] && !value[1] && strchr("bta",*value))
86 *conversion = *value;
87 else if (!strcmp(value,"binary")) *conversion = 'b';
88 else if (!strcmp(value,"text")) *conversion = 't';
89 else if (!strcmp(value,"mtext")) *conversion = 'm';
90 else if (!strcmp(value,"auto")) *conversion = 'a';
91 else return 0;
92 }
93 else return 0;
94 }
95 return 1;
96 }
97
98 struct super_block *isofs_read_super(struct super_block *s,void *data)
99 {
100 struct buffer_head *bh;
101 int iso_blknum;
102 int high_sierra;
103 int dev=s->s_dev;
104 struct iso_volume_descriptor *vdp;
105 struct hs_volume_descriptor *hdp;
106
107 struct iso_primary_descriptor *pri = NULL;
108 struct hs_primary_descriptor *h_pri = NULL;
109
110 struct iso_directory_record *rootp;
111
112 char map, conversion, rock, cruft;
113
114 if (!parse_options((char *) data,&map,&conversion, &rock, &cruft)) {
115 s->s_dev = 0;
116 return NULL;
117 }
118
119 lock_super(s);
120
121 s->u.isofs_sb.s_high_sierra = high_sierra = 0;
122
123 for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
124 if (!(bh = bread(dev, iso_blknum << (ISOFS_BLOCK_BITS-ISOFS_BUFFER_BITS), ISOFS_BUFFER_SIZE))) {
125 s->s_dev=0;
126 printk("isofs_read_super: bread failed, dev 0x%x iso_blknum %d\n",
127 dev, iso_blknum);
128 unlock_super(s);
129 return NULL;
130 }
131
132 vdp = (struct iso_volume_descriptor *)bh->b_data;
133 hdp = (struct hs_volume_descriptor *)bh->b_data;
134
135
136 if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) {
137 if (isonum_711 (hdp->type) != ISO_VD_PRIMARY)
138 goto out;
139 if (isonum_711 (hdp->type) == ISO_VD_END)
140 goto out;
141
142 s->u.isofs_sb.s_high_sierra = 1;
143 high_sierra = 1;
144 rock = 'n';
145 h_pri = (struct hs_primary_descriptor *)vdp;
146 break;
147 };
148
149 if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) {
150 if (isonum_711 (vdp->type) != ISO_VD_PRIMARY)
151 goto out;
152 if (isonum_711 (vdp->type) == ISO_VD_END)
153 goto out;
154
155 pri = (struct iso_primary_descriptor *)vdp;
156 break;
157 };
158
159 brelse(bh);
160 }
161 if(iso_blknum == 100) {
162 printk("Unable to identify CD-ROM format.\n");
163 s->s_dev = 0;
164 unlock_super(s);
165 return NULL;
166 };
167
168
169 if(high_sierra){
170 rootp = (struct iso_directory_record *) h_pri->root_directory_record;
171 if (isonum_723 (h_pri->volume_set_size) != 1) {
172 printk("Multi-volume disks not (yet) supported.\n");
173 goto out;
174 };
175 s->u.isofs_sb.s_nzones = isonum_733 (h_pri->volume_space_size);
176 s->u.isofs_sb.s_log_zone_size = isonum_723 (h_pri->logical_block_size);
177 s->u.isofs_sb.s_max_size = isonum_733(h_pri->volume_space_size);
178 } else {
179 rootp = (struct iso_directory_record *) pri->root_directory_record;
180 if (isonum_723 (pri->volume_set_size) != 1) {
181 printk("Multi-volume disks not (yet) supported.\n");
182 goto out;
183 };
184 s->u.isofs_sb.s_nzones = isonum_733 (pri->volume_space_size);
185 s->u.isofs_sb.s_log_zone_size = isonum_723 (pri->logical_block_size);
186 s->u.isofs_sb.s_max_size = isonum_733(pri->volume_space_size);
187 }
188
189 s->u.isofs_sb.s_ninodes = 0;
190
191 s->u.isofs_sb.s_firstdatazone = isonum_733( rootp->extent) <<
192 (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
193 s->s_magic = ISOFS_SUPER_MAGIC;
194
195
196
197
198
199
200 s->s_flags = MS_RDONLY ;
201
202 if(s->u.isofs_sb.s_log_zone_size != (1 << ISOFS_BLOCK_BITS)) {
203 printk("1 <<Block bits != Block size\n");
204 goto out;
205 };
206
207 brelse(bh);
208
209 printk("Max size:%d Log zone size:%d\n",s->u.isofs_sb.s_max_size,
210 s->u.isofs_sb.s_log_zone_size);
211 printk("First datazone:%d Root inode number %d\n",s->u.isofs_sb.s_firstdatazone,
212 isonum_733 (rootp->extent) << ISOFS_BLOCK_BITS);
213 if(high_sierra) printk("Disc in High Sierra format.\n");
214 unlock_super(s);
215
216
217 s->s_dev = dev;
218 s->s_op = &isofs_sops;
219 s->u.isofs_sb.s_mapping = map;
220 s->u.isofs_sb.s_rock = (rock == 'y' ? 1 : 0);
221 s->u.isofs_sb.s_conversion = conversion;
222 s->u.isofs_sb.s_cruft = cruft;
223 s->s_blocksize = ISOFS_BUFFER_SIZE;
224 s->s_mounted = iget(s, isonum_733 (rootp->extent) << ISOFS_BLOCK_BITS);
225 unlock_super(s);
226
227 if (!(s->s_mounted)) {
228 s->s_dev=0;
229 printk("get root inode failed\n");
230 return NULL;
231 }
232 if(MAJOR(s->s_dev) == 11) {
233
234 if(check_cdrom_media_change(s->s_dev, 0))
235 goto out;
236 };
237 return s;
238 out:
239 brelse(bh);
240 s->s_dev = 0;
241 unlock_super(s);
242 return NULL;
243 }
244
245 void isofs_statfs (struct super_block *sb, struct statfs *buf)
246 {
247 put_fs_long(ISOFS_SUPER_MAGIC, &buf->f_type);
248 put_fs_long(1 << ISOFS_BLOCK_BITS, &buf->f_bsize);
249 put_fs_long(sb->u.isofs_sb.s_nzones, &buf->f_blocks);
250 put_fs_long(0, &buf->f_bfree);
251 put_fs_long(0, &buf->f_bavail);
252 put_fs_long(sb->u.isofs_sb.s_ninodes, &buf->f_files);
253 put_fs_long(0, &buf->f_ffree);
254
255 }
256
257 int isofs_bmap(struct inode * inode,int block)
258 {
259
260 if (block<0) {
261 printk("_isofs_bmap: block<0");
262 return 0;
263 }
264 return inode->u.isofs_i.i_first_extent + block;
265 }
266
267 void isofs_read_inode(struct inode * inode)
268 {
269 struct buffer_head * bh;
270 unsigned char * pnt, *cpnt = 0;
271 struct iso_directory_record * raw_inode;
272 int high_sierra;
273 int block;
274 int i;
275
276 block = inode->i_ino >> ISOFS_BUFFER_BITS;
277 if (!(bh=bread(inode->i_dev,block, ISOFS_BUFFER_SIZE)))
278 panic("unable to read i-node block");
279
280 pnt = ((char *) bh->b_data) + (inode->i_ino & (ISOFS_BUFFER_SIZE - 1));
281
282 raw_inode = ((struct iso_directory_record *) pnt);
283 high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
284
285 if ((inode->i_ino & (ISOFS_BUFFER_SIZE - 1)) + *pnt > ISOFS_BUFFER_SIZE){
286 cpnt = kmalloc(1 << ISOFS_BLOCK_BITS, GFP_KERNEL);
287 memcpy(cpnt, bh->b_data, ISOFS_BUFFER_SIZE);
288 brelse(bh);
289 if (!(bh = bread(inode->i_dev,++block, ISOFS_BUFFER_SIZE)))
290 panic("unable to read i-node block");
291 memcpy(cpnt+ISOFS_BUFFER_SIZE, bh->b_data, ISOFS_BUFFER_SIZE);
292 pnt = ((char *) cpnt) + (inode->i_ino & (ISOFS_BUFFER_SIZE - 1));
293 raw_inode = ((struct iso_directory_record *) pnt);
294 };
295
296
297 inode->i_mode = 0444;
298 inode->i_nlink = 1;
299
300 if (raw_inode->flags[-high_sierra] & 2) {
301 inode->i_mode = 0555 | S_IFDIR;
302 inode->i_nlink = 2;
303
304 } else {
305 inode->i_mode = 0444;
306 inode->i_nlink = 1;
307 inode->i_mode |= S_IFREG;
308
309 for(i=0; i< raw_inode->name_len[0]; i++)
310 if(raw_inode->name[i]=='.' || raw_inode->name[i]==';')
311 break;
312 if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';')
313 inode->i_mode |= 0111;
314 };
315 inode->i_uid = 0;
316 inode->i_gid = 0;
317 inode->i_size = isonum_733 (raw_inode->size);
318
319
320
321 if(inode->i_size < 0 || inode->i_size > 700000000) {
322 printk("Warning: defective cdrom. Enabling \"cruft\" mount option.\n");
323 inode->i_sb->u.isofs_sb.s_cruft = 'y';
324 };
325
326
327
328
329
330 if(inode->i_sb->u.isofs_sb.s_cruft == 'y' &&
331 inode->i_size & 0xff000000){
332
333 inode->i_size &= 0x00ffffff;
334 };
335
336 if (isonum_723 (raw_inode->volume_sequence_number) != 1) {
337 panic("Multi volume CD somehow got mounted.\n");
338 };
339
340 if (raw_inode->interleave[0]) {
341 printk("Interleaved files not (yet) supported.\n");
342 inode->i_size = 0;
343 };
344
345 #ifdef DEBUG
346
347
348 if(raw_inode->ext_attr_length[0] != 0){
349 printk("Extended attributes present for ISO file (%d).\n",
350 inode->i_ino);
351 }
352 #endif
353
354
355
356 if(raw_inode->file_unit_size[0] != 0){
357 printk("File unit size != 0 for ISO file.(%d)\n",inode->i_ino);
358 }
359
360
361
362 if((raw_inode->flags[-high_sierra] & ~2)!= 0){
363 printk("Unusual flag settings for ISO file.(%d %x)\n",
364 inode->i_ino, raw_inode->flags[-high_sierra]);
365 }
366
367 #ifdef DEBUG
368 printk("Get inode %d: %d %d: %d\n",inode->i_ino, block,
369 ((int)pnt) & 0x3ff, inode->i_size);
370 #endif
371
372 inode->i_mtime = inode->i_atime = inode->i_ctime =
373 iso_date(raw_inode->date, high_sierra);
374
375 inode->u.isofs_i.i_first_extent = isonum_733 (raw_inode->extent) <<
376 (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
377
378 inode->u.isofs_i.i_backlink = -1;
379 switch (inode->i_sb->u.isofs_sb.s_conversion){
380 case 'a':
381 inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN;
382 break;
383 case 'b':
384 inode->u.isofs_i.i_file_format = ISOFS_FILE_BINARY;
385 break;
386 case 't':
387 inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT;
388 break;
389 case 'm':
390 inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT_M;
391 break;
392 };
393
394
395
396
397
398 if (!high_sierra)
399 parse_rock_ridge_inode(raw_inode, inode);
400
401 #ifdef DEBUG
402 printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent);
403 #endif
404 brelse(bh);
405
406 if (cpnt) {
407 kfree_s (cpnt, 1 << ISOFS_BLOCK_BITS);
408 cpnt = 0;
409 };
410
411 inode->i_op = NULL;
412 if (S_ISREG(inode->i_mode))
413 inode->i_op = &isofs_file_inode_operations;
414 else if (S_ISDIR(inode->i_mode))
415 inode->i_op = &isofs_dir_inode_operations;
416 else if (S_ISLNK(inode->i_mode))
417 inode->i_op = &isofs_symlink_inode_operations;
418 else if (S_ISCHR(inode->i_mode))
419 inode->i_op = &isofs_chrdev_inode_operations;
420 else if (S_ISBLK(inode->i_mode))
421 inode->i_op = &isofs_blkdev_inode_operations;
422 else if (S_ISFIFO(inode->i_mode)) {
423 inode->i_op = &isofs_fifo_inode_operations;
424 inode->i_pipe = 1;
425 PIPE_BASE(*inode) = NULL;
426 PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
427 PIPE_READ_WAIT(*inode) = PIPE_WRITE_WAIT(*inode) = NULL;
428 PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
429 }
430 }
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451 int isofs_lookup_grandparent(struct inode * parent, int extent) {
452 unsigned int block,offset;
453 int parent_dir, inode_number;
454 int old_offset;
455 char * cpnt = 0;
456 int result;
457 struct buffer_head * bh;
458 struct iso_directory_record * de;
459
460 offset = 0;
461 block = extent << (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
462 if (!(bh = bread(parent->i_dev, block, ISOFS_BUFFER_SIZE))) return 0;
463
464 while (1 == 1) {
465 de = (struct iso_directory_record *) (offset + bh->b_data);
466
467 if (*((char*) de) == 0)
468 {
469 brelse(bh);
470 return -1;
471 }
472
473 offset += *((unsigned char*) de);
474
475 if (offset >= ISOFS_BUFFER_SIZE)
476 {
477 printk(".. Directory not in first block of directory.\n");
478 brelse(bh);
479 return -1;
480 }
481
482 if (de->name_len[0] == 1 && de->name[0] == 1)
483 {
484 brelse(bh);
485 parent_dir = find_rock_ridge_relocation(de, parent);
486 break;
487 };
488 }
489 #ifdef DEBUG
490 printk("Parent dir:%x\n",parent_dir);
491 #endif
492
493
494
495
496 result = -1;
497
498 offset = 0;
499 block = parent_dir << (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS);
500 if (!block || !(bh = bread(parent->i_dev,block, ISOFS_BUFFER_SIZE)))
501 return 0;
502
503 while (1==1) {
504 de = (struct iso_directory_record *) (offset + bh->b_data);
505 inode_number = (block << ISOFS_BUFFER_BITS)+(offset & (ISOFS_BUFFER_SIZE - 1));
506
507
508
509
510 if (*((char*) de) == 0)
511 {
512 brelse(bh);
513 offset = 0;
514 block++;
515 if(block & 1) return -1;
516 if (!block || !(bh = bread(parent->i_dev,block, ISOFS_BUFFER_SIZE)))
517 return -1;
518 continue;
519 }
520
521
522
523
524
525 old_offset = offset;
526 offset += *((unsigned char*) de);
527 if (offset >= ISOFS_BUFFER_SIZE)
528 {
529 cpnt = kmalloc(1<<ISOFS_BLOCK_BITS,GFP_KERNEL);
530 memcpy(cpnt, bh->b_data, ISOFS_BUFFER_SIZE);
531 de = (struct iso_directory_record *) (old_offset + cpnt);
532 brelse(bh);
533 offset -= ISOFS_BUFFER_SIZE;
534 block++;
535 if((block & 1) == 0) return -1;
536 if (!(bh = bread(parent->i_dev,block, ISOFS_BUFFER_SIZE)))
537 return -1;
538 memcpy(cpnt+ISOFS_BUFFER_SIZE, bh->b_data, ISOFS_BUFFER_SIZE);
539 }
540
541 if (find_rock_ridge_relocation(de, parent) == extent){
542 result = inode_number;
543 goto out;
544 };
545
546 if (cpnt) {
547 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
548 cpnt = 0;
549 };
550 }
551
552
553
554 out:
555 if (cpnt) {
556 kfree_s(cpnt, 1 << ISOFS_BLOCK_BITS);
557 cpnt = 0;
558 };
559 brelse(bh);
560 #ifdef DEBUG
561 printk("Resultant Inode %d\n",result);
562 #endif
563 return result;
564 }
565
566 #ifdef LEAK_CHECK
567 #undef malloc
568 #undef free_s
569 #undef bread
570 #undef brelse
571
572 void * leak_check_malloc(unsigned int size){
573 void * tmp;
574 check_malloc++;
575 tmp = kmalloc(size, GFP_KERNEL);
576 return tmp;
577 }
578
579 void leak_check_free_s(void * obj, int size){
580 check_malloc--;
581 return kfree_s(obj, size);
582 }
583
584 struct buffer_head * leak_check_bread(int dev, int block, int size){
585 check_bread++;
586 return bread(dev, block, size);
587 }
588
589 void leak_check_brelse(struct buffer_head * bh){
590 check_bread--;
591 return brelse(bh);
592 }
593
594 #endif