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