📄 inode.c
字号:
goto abort; ninode = iget(inode->i_sb, nextino); if (!ninode) goto abort; firstext = ninode->u.isofs_i.i_first_extent; sect_size = ninode->u.isofs_i.i_section_size; nextino = ninode->u.isofs_i.i_next_section_ino; iput(ninode); if (++section > 100) { printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n"); printk("isofs_get_blocks: ino=%lu block=%ld firstext=%u sect_size=%u nextino=%lu\n", inode->i_ino, iblock, firstext, (unsigned) sect_size, nextino); goto abort; } } } if ( *bh_result ) { (*bh_result)->b_dev = inode->i_dev; (*bh_result)->b_blocknr = firstext + b_off - offset; (*bh_result)->b_state |= (1UL << BH_Mapped); } else { *bh_result = sb_getblk(inode->i_sb, firstext+b_off-offset); if ( !*bh_result ) goto abort; } bh_result++; /* Next buffer head */ b_off++; /* Next buffer offset */ nblocks--; rv++; }abort: unlock_kernel(); return rv;}/* * Used by the standard interfaces. */static int isofs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create){ if ( create ) { printk("isofs_get_block: Kernel tries to allocate a block\n"); return -EROFS; } return isofs_get_blocks(inode, iblock, &bh_result, 1) ? 0 : -EIO;}static int isofs_bmap(struct inode *inode, int block){ struct buffer_head dummy; int error; dummy.b_state = 0; dummy.b_blocknr = -1000; error = isofs_get_block(inode, block, &dummy, 0); if (!error) return dummy.b_blocknr; return 0;}struct buffer_head *isofs_bread(struct inode *inode, unsigned int block){ unsigned int blknr = isofs_bmap(inode, block); if (!blknr) return NULL; return sb_bread(inode->i_sb, blknr);}static int isofs_readpage(struct file *file, struct page *page){ return block_read_full_page(page,isofs_get_block);}static int _isofs_bmap(struct address_space *mapping, long block){ return generic_block_bmap(mapping,block,isofs_get_block);}static struct address_space_operations isofs_aops = { readpage: isofs_readpage, sync_page: block_sync_page, bmap: _isofs_bmap};static inline void test_and_set_uid(uid_t *p, uid_t value){ if(value) { *p = value; }}static inline void test_and_set_gid(gid_t *p, gid_t value){ if(value) { *p = value; }}static int isofs_read_level3_size(struct inode * inode){ unsigned long f_pos = inode->i_ino; unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); int high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra; struct buffer_head * bh = NULL; unsigned long block, offset; int i = 0; int more_entries = 0; struct iso_directory_record * tmpde = NULL; inode->i_size = 0; inode->u.isofs_i.i_next_section_ino = 0; block = f_pos >> ISOFS_BUFFER_BITS(inode); offset = f_pos & (bufsize-1); do { struct iso_directory_record * de; unsigned int de_len; if (!bh) { bh = sb_bread(inode->i_sb, block); if (!bh) goto out_noread; } de = (struct iso_directory_record *) (bh->b_data + offset); de_len = *(unsigned char *) de; if (de_len == 0) { brelse(bh); bh = NULL; f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1); block = f_pos >> ISOFS_BUFFER_BITS(inode); offset = 0; continue; } offset += de_len; /* Make sure we have a full directory entry */ if (offset >= bufsize) { int slop = bufsize - offset + de_len; if (!tmpde) { tmpde = kmalloc(256, GFP_KERNEL); if (!tmpde) goto out_nomem; } memcpy(tmpde, de, slop); offset &= bufsize - 1; block++; brelse(bh); bh = NULL; if (offset) { bh = sb_bread(inode->i_sb, block); if (!bh) goto out_noread; memcpy((void *) tmpde + slop, bh->b_data, offset); } de = tmpde; } inode->i_size += isonum_733(de->size); if (i == 1) inode->u.isofs_i.i_next_section_ino = f_pos; more_entries = de->flags[-high_sierra] & 0x80; f_pos += de_len; i++; if(i > 100) goto out_toomany; } while(more_entries);out: if (tmpde) kfree(tmpde); if (bh) brelse(bh); return 0;out_nomem: if (bh) brelse(bh); return -ENOMEM;out_noread: printk(KERN_INFO "ISOFS: unable to read i-node block %lu\n", block); if (tmpde) kfree(tmpde); return -EIO;out_toomany: printk(KERN_INFO "isofs_read_level3_size: " "More than 100 file sections ?!?, aborting...\n" "isofs_read_level3_size: inode=%lu ino=%lu\n", inode->i_ino, f_pos); goto out;}static void isofs_read_inode(struct inode * inode){ struct super_block *sb = inode->i_sb; unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); int block = inode->i_ino >> ISOFS_BUFFER_BITS(inode); int high_sierra = sb->u.isofs_sb.s_high_sierra; struct buffer_head * bh = NULL; struct iso_directory_record * de; struct iso_directory_record * tmpde = NULL; unsigned int de_len; unsigned long offset; int volume_seq_no, i; bh = sb_bread(inode->i_sb, block); if (!bh) goto out_badread; offset = (inode->i_ino & (bufsize - 1)); de = (struct iso_directory_record *) (bh->b_data + offset); de_len = *(unsigned char *) de; if (offset + de_len > bufsize) { int frag1 = bufsize - offset; tmpde = kmalloc(de_len, GFP_KERNEL); if (tmpde == NULL) { printk(KERN_INFO "isofs_read_inode: out of memory\n"); goto fail; } memcpy(tmpde, bh->b_data + offset, frag1); brelse(bh); bh = sb_bread(inode->i_sb, ++block); if (!bh) goto out_badread; memcpy((char *)tmpde+frag1, bh->b_data, de_len - frag1); de = tmpde; } /* Assume it is a normal-format file unless told otherwise */ inode->u.isofs_i.i_file_format = isofs_file_normal; if (de->flags[-high_sierra] & 2) { inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR; inode->i_nlink = 1; /* Set to 1. We know there are 2, but the find utility tries to optimize if it is 2, and it screws up. It is easier to give 1 which tells find to do it the hard way. */ } else { /* Everybody gets to read the file. */ inode->i_mode = inode->i_sb->u.isofs_sb.s_mode; inode->i_nlink = 1; inode->i_mode |= S_IFREG; /* If there are no periods in the name, * then set the execute permission bit */ for(i=0; i< de->name_len[0]; i++) if(de->name[i]=='.' || de->name[i]==';') break; if(i == de->name_len[0] || de->name[i] == ';') inode->i_mode |= S_IXUGO; /* execute permission */ } inode->i_uid = inode->i_sb->u.isofs_sb.s_uid; inode->i_gid = inode->i_sb->u.isofs_sb.s_gid; inode->i_blocks = inode->i_blksize = 0; inode->u.isofs_i.i_section_size = isonum_733 (de->size); if(de->flags[-high_sierra] & 0x80) { if(isofs_read_level3_size(inode)) goto fail; } else { inode->i_size = isonum_733 (de->size); } /* * The ISO-9660 filesystem only stores 32 bits for file size. * mkisofs handles files up to 2GB-2 = 2147483646 = 0x7FFFFFFE bytes * in size. This is according to the large file summit paper from 1996. * WARNING: ISO-9660 filesystems > 1 GB and even > 2 GB are fully * legal. Do not prevent to use DVD's schilling@fokus.gmd.de */ if ((inode->i_size < 0 || inode->i_size > 0x7FFFFFFE) && inode->i_sb->u.isofs_sb.s_cruft == 'n') { printk(KERN_WARNING "Warning: defective CD-ROM. " "Enabling \"cruft\" mount option.\n"); inode->i_sb->u.isofs_sb.s_cruft = 'y'; } /* * Some dipshit decided to store some other bit of information * in the high byte of the file length. Catch this and holler. * WARNING: this will make it impossible for a file to be > 16MB * on the CDROM. */ if (inode->i_sb->u.isofs_sb.s_cruft == 'y' && inode->i_size & 0xff000000) { inode->i_size &= 0x00ffffff; } if (de->interleave[0]) { printk("Interleaved files not (yet) supported.\n"); inode->i_size = 0; } /* I have no idea what file_unit_size is used for, so we will flag it for now */ if (de->file_unit_size[0] != 0) { printk("File unit size != 0 for ISO file (%ld).\n", inode->i_ino); } /* I have no idea what other flag bits are used for, so we will flag it for now */#ifdef DEBUG if((de->flags[-high_sierra] & ~2)!= 0){ printk("Unusual flag settings for ISO file (%ld %x).\n", inode->i_ino, de->flags[-high_sierra]); }#endif inode->i_mtime = inode->i_atime = inode->i_ctime = iso_date(de->date, high_sierra); inode->u.isofs_i.i_first_extent = (isonum_733 (de->extent) + isonum_711 (de->ext_attr_length)); /* Set the number of blocks for stat() - should be done before RR */ inode->i_blksize = PAGE_CACHE_SIZE; /* For stat() only */ inode->i_blocks = (inode->i_size + 511) >> 9; /* * Now test for possible Rock Ridge extensions which will override * some of these numbers in the inode structure. */ if (!high_sierra) { parse_rock_ridge_inode(de, inode); /* if we want uid/gid set, override the rock ridge setting */ test_and_set_uid(&inode->i_uid, inode->i_sb->u.isofs_sb.s_uid); test_and_set_gid(&inode->i_gid, inode->i_sb->u.isofs_sb.s_gid); } /* get the volume sequence number */ volume_seq_no = isonum_723 (de->volume_sequence_number) ; /* * Disable checking if we see any volume number other than 0 or 1. * We could use the cruft option, but that has multiple purposes, one * of which is limiting the file size to 16Mb. Thus we silently allow * volume numbers of 0 to go through without complaining. */ if (inode->i_sb->u.isofs_sb.s_cruft == 'n' && (volume_seq_no != 0) && (volume_seq_no != 1)) { printk(KERN_WARNING "Warning: defective CD-ROM " "(volume sequence number %d). " "Enabling \"cruft\" mount option.\n", volume_seq_no); inode->i_sb->u.isofs_sb.s_cruft = 'y'; } /* Install the inode operations vector */#ifndef IGNORE_WRONG_MULTI_VOLUME_SPECS if (inode->i_sb->u.isofs_sb.s_cruft != 'y' && (volume_seq_no != 0) && (volume_seq_no != 1)) { printk(KERN_WARNING "Multi-volume CD somehow got mounted.\n"); } else#endif /*IGNORE_WRONG_MULTI_VOLUME_SPECS */ { if (S_ISREG(inode->i_mode)) { inode->i_fop = &generic_ro_fops; switch ( inode->u.isofs_i.i_file_format ) {#ifdef CONFIG_ZISOFS case isofs_file_compressed: inode->i_data.a_ops = &zisofs_aops; break;#endif default: inode->i_data.a_ops = &isofs_aops; break; } } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &isofs_dir_inode_operations; inode->i_fop = &isofs_dir_operations; } else if (S_ISLNK(inode->i_mode)) { inode->i_op = &page_symlink_inode_operations; inode->i_data.a_ops = &isofs_symlink_aops; } else /* XXX - parse_rock_ridge_inode() had already set i_rdev. */ init_special_inode(inode, inode->i_mode, kdev_t_to_nr(inode->i_rdev)); } out: if (tmpde) kfree(tmpde); if (bh) brelse(bh); return; out_badread: printk(KERN_WARNING "ISOFS: unable to read i-node block\n"); fail: make_bad_inode(inode); goto out;}#ifdef LEAK_CHECK#undef malloc#undef free_s#undef sb_bread#undef brelsevoid * leak_check_malloc(unsigned int size){ void * tmp; check_malloc++; tmp = kmalloc(size, GFP_KERNEL); return tmp;}void leak_check_free_s(void * obj, int size){ check_malloc--; return kfree(obj);}struct buffer_head * leak_check_bread(struct super_block *sb, int block){ check_bread++; return sb_bread(sb, block);}void leak_check_brelse(struct buffer_head * bh){ check_bread--; return brelse(bh);}#endifstatic DECLARE_FSTYPE_DEV(iso9660_fs_type, "iso9660", isofs_read_super);static int __init init_iso9660_fs(void){#ifdef CONFIG_ZISOFS int err; err = zisofs_init(); if ( err ) return err;#endif return register_filesystem(&iso9660_fs_type);}static void __exit exit_iso9660_fs(void){ unregister_filesystem(&iso9660_fs_type);#ifdef CONFIG_ZISOFS zisofs_cleanup();#endif}EXPORT_NO_SYMBOLS;module_init(init_iso9660_fs)module_exit(exit_iso9660_fs)MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -