📄 fs.c
字号:
at = ntfs_find_attr(ino, vol->at_index_allocation, "$I30"); inode->i_size = at ? at->size : 0; inode->i_op = &ntfs_dir_inode_operations; inode->i_fop = &ntfs_dir_operations; inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; } else { inode->i_op = &ntfs_inode_operations; inode->i_fop = &ntfs_file_operations; inode->i_mode = S_IFREG | S_IRUGO; }#ifdef CONFIG_NTFS_RW if (!data || !(data->flags & (ATTR_IS_COMPRESSED | ATTR_IS_ENCRYPTED))) inode->i_mode |= S_IWUGO;#endif inode->i_mode &= ~vol->umask; return;sys_file_error: ntfs_error("Critical error. Tried to call ntfs_read_inode() before we " "have completed read_super() or VFS error.\n"); // FIXME: Should we panic() at this stage?}#ifdef CONFIG_NTFS_RWstatic void ntfs_write_inode(struct inode *ino, int unused){ lock_kernel(); ntfs_debug(DEBUG_LINUX, "ntfs_write_inode 0x%x\n", ino->i_ino); ntfs_update_inode(NTFS_LINO2NINO(ino)); unlock_kernel();}#endifstatic void _ntfs_clear_inode(struct inode *inode){ ntfs_inode *ino; ntfs_volume *vol; lock_kernel(); ntfs_debug(DEBUG_OTHER, "_ntfs_clear_inode 0x%x\n", inode->i_ino); vol = NTFS_INO2VOL(inode); if (!vol) ntfs_error("_ntfs_clear_inode: vol = NTFS_INO2VOL(inode) is " "NULL.\n"); switch (inode->i_ino) { case FILE_Mft: if (vol->mft_ino && ((vol->ino_flags & 1) == 0)) { ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode)); ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode)); vol->mft_ino = ino; vol->ino_flags |= 1; goto unl_out; } break; case FILE_MftMirr: if (vol->mftmirr && ((vol->ino_flags & 2) == 0)) { ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode)); ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode)); vol->mftmirr = ino; vol->ino_flags |= 2; goto unl_out; } break; case FILE_BitMap: if (vol->bitmap && ((vol->ino_flags & 4) == 0)) { ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode)); ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode)); vol->bitmap = ino; vol->ino_flags |= 4; goto unl_out; } break; default: /* Nothing. Just clear the inode and exit. */ } ntfs_clear_inode(&inode->u.ntfs_i);unl_out: unlock_kernel(); return;}/* Called when umounting a filesystem by do_umount() in fs/super.c. */static void ntfs_put_super(struct super_block *sb){ ntfs_volume *vol; ntfs_debug(DEBUG_OTHER, "ntfs_put_super\n"); vol = NTFS_SB2VOL(sb); ntfs_release_volume(vol); if (vol->nls_map) unload_nls(vol->nls_map); ntfs_debug(DEBUG_OTHER, "ntfs_put_super: done\n");}/* Called by the kernel when asking for stats. */static int ntfs_statfs(struct super_block *sb, struct statfs *sf){ struct inode *mft; ntfs_volume *vol; __s64 size; int error; ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n"); vol = NTFS_SB2VOL(sb); sf->f_type = NTFS_SUPER_MAGIC; sf->f_bsize = vol->cluster_size; error = ntfs_get_volumesize(NTFS_SB2VOL(sb), &size); if (error) return error; sf->f_blocks = size; /* Volumesize is in clusters. */ size = (__s64)ntfs_get_free_cluster_count(vol->bitmap); /* Just say zero if the call failed. */ if (size < 0LL) size = 0; sf->f_bfree = sf->f_bavail = size; ntfs_debug(DEBUG_OTHER, "ntfs_statfs: calling mft = iget(sb, " "FILE_Mft)\n"); mft = iget(sb, FILE_Mft); ntfs_debug(DEBUG_OTHER, "ntfs_statfs: iget(sb, FILE_Mft) returned " "0x%x\n", mft); if (!mft) return -EIO; sf->f_files = mft->i_size >> vol->mft_record_size_bits; ntfs_debug(DEBUG_OTHER, "ntfs_statfs: calling iput(mft)\n"); iput(mft); /* Should be read from volume. */ sf->f_namelen = 255; return 0;}/* Called when remounting a filesystem by do_remount_sb() in fs/super.c. */static int ntfs_remount_fs(struct super_block *sb, int *flags, char *options){ if (!parse_options(NTFS_SB2VOL(sb), options)) return -EINVAL; return 0;}/* Define the super block operation that are implemented */static struct super_operations ntfs_super_operations = { read_inode: ntfs_read_inode,#ifdef CONFIG_NTFS_RW write_inode: ntfs_write_inode,#endif put_super: ntfs_put_super, statfs: ntfs_statfs, remount_fs: ntfs_remount_fs, clear_inode: _ntfs_clear_inode,};/** * is_boot_sector_ntfs - check an NTFS boot sector for validity * @b: buffer containing bootsector to check * * Check whether @b contains a valid NTFS boot sector. * Return 1 if @b is a valid NTFS bootsector or 0 if not. */static int is_boot_sector_ntfs(ntfs_u8 *b){ ntfs_u32 i; /* FIXME: We don't use checksumming yet as NT4(SP6a) doesn't either... * But we might as well have the code ready to do it. (AIA) */#if 0 /* Calculate the checksum. */ if (b < b + 0x50) { ntfs_u32 *u; ntfs_u32 *bi = (ntfs_u32 *)(b + 0x50); for (u = bi, i = 0; u < bi; ++u) i += NTFS_GETU32(*u); }#endif /* Check magic is "NTFS " */ if (b[3] != 0x4e) goto not_ntfs; if (b[4] != 0x54) goto not_ntfs; if (b[5] != 0x46) goto not_ntfs; if (b[6] != 0x53) goto not_ntfs; for (i = 7; i < 0xb; ++i) if (b[i] != 0x20) goto not_ntfs; /* Check bytes per sector value is between 512 and 4096. */ if (b[0xb] != 0) goto not_ntfs; if (b[0xc] > 0x10) goto not_ntfs; /* Check sectors per cluster value is valid. */ switch (b[0xd]) { case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: break; default: goto not_ntfs; } /* Check reserved sectors value and four other fields are zero. */ for (i = 0xe; i < 0x15; ++i) if (b[i] != 0) goto not_ntfs; if (b[0x16] != 0) goto not_ntfs; if (b[0x17] != 0) goto not_ntfs; for (i = 0x20; i < 0x24; ++i) if (b[i] != 0) goto not_ntfs; /* Check clusters per file record segment value is valid. */ if (b[0x40] < 0xe1 || b[0x40] > 0xf7) { switch (b[0x40]) { case 1: case 2: case 4: case 8: case 16: case 32: case 64: break; default: goto not_ntfs; } } /* Check clusters per index block value is valid. */ if (b[0x44] < 0xe1 || b[0x44] > 0xf7) { switch (b[0x44]) { case 1: case 2: case 4: case 8: case 16: case 32: case 64: break; default: goto not_ntfs; } } return 1;not_ntfs: return 0;}/* Called to mount a filesystem by read_super() in fs/super.c. * Return a super block, the main structure of a filesystem. * * NOTE : Don't store a pointer to an option, as the page containing the * options is freed after ntfs_read_super() returns. * * NOTE : A context switch can happen in kernel code only if the code blocks * (= calls schedule() in kernel/sched.c). */struct super_block *ntfs_read_super(struct super_block *sb, void *options, int silent){ ntfs_volume *vol; struct buffer_head *bh; int i, to_read, blocksize; ntfs_debug(DEBUG_OTHER, "ntfs_read_super\n"); vol = NTFS_SB2VOL(sb); init_ntfs_super_block(vol); if (!parse_options(vol, (char*)options)) goto ntfs_read_super_vol; blocksize = get_hardsect_size(sb->s_dev); if (blocksize < 512) blocksize = 512; if (set_blocksize(sb->s_dev, blocksize) < 0) { ntfs_error("Unable to set blocksize %d.\n", blocksize); goto ntfs_read_super_vol; } sb->s_blocksize = blocksize; /* Read the super block (boot block). */ if (!(bh = sb_bread(sb, 0))) { ntfs_error("Reading super block failed\n"); goto ntfs_read_super_unl; } ntfs_debug(DEBUG_OTHER, "Done reading boot block\n"); /* Check for valid 'NTFS' boot sector. */ if (!is_boot_sector_ntfs(bh->b_data)) { ntfs_debug(DEBUG_OTHER, "Not a NTFS volume\n"); bforget(bh); goto ntfs_read_super_unl; } ntfs_debug(DEBUG_OTHER, "Going to init volume\n"); if (ntfs_init_volume(vol, bh->b_data) < 0) { ntfs_debug(DEBUG_OTHER, "Init volume failed.\n"); bforget(bh); goto ntfs_read_super_unl; } ntfs_debug(DEBUG_OTHER, "$Mft at cluster 0x%lx\n", vol->mft_lcn); brelse(bh); NTFS_SB(vol) = sb; if (vol->cluster_size > PAGE_SIZE) { ntfs_error("Partition cluster size is not supported yet (it " "is > max kernel blocksize).\n"); goto ntfs_read_super_unl; } ntfs_debug(DEBUG_OTHER, "Done to init volume\n"); /* Inform the kernel that a device block is a NTFS cluster. */ sb->s_blocksize = vol->cluster_size; sb->s_blocksize_bits = vol->cluster_size_bits; if (blocksize != vol->cluster_size && set_blocksize(sb->s_dev, sb->s_blocksize) < 0) { ntfs_error("Cluster size too small for device.\n"); goto ntfs_read_super_unl; } ntfs_debug(DEBUG_OTHER, "set_blocksize\n"); /* Allocate an MFT record (MFT record can be smaller than a cluster). */ i = vol->cluster_size; if (i < vol->mft_record_size) i = vol->mft_record_size; if (!(vol->mft = ntfs_malloc(i))) goto ntfs_read_super_unl; /* Read at least the MFT record for $Mft. */ to_read = vol->mft_clusters_per_record; if (to_read < 1) to_read = 1; for (i = 0; i < to_read; i++) { if (!(bh = sb_bread(sb, vol->mft_lcn + i))) { ntfs_error("Could not read $Mft record 0\n"); goto ntfs_read_super_mft; } ntfs_memcpy(vol->mft + ((__s64)i << vol->cluster_size_bits), bh->b_data, vol->cluster_size); brelse(bh); ntfs_debug(DEBUG_OTHER, "Read cluster 0x%x\n", vol->mft_lcn + i); } /* Check and fixup this MFT record */ if (!ntfs_check_mft_record(vol, vol->mft)){ ntfs_error("Invalid $Mft record 0\n"); goto ntfs_read_super_mft; } /* Inform the kernel about which super operations are available. */ sb->s_op = &ntfs_super_operations; sb->s_magic = NTFS_SUPER_MAGIC; sb->s_maxbytes = ~0ULL >> 1; ntfs_debug(DEBUG_OTHER, "Reading special files\n"); if (ntfs_load_special_files(vol)) { ntfs_error("Error loading special files\n"); goto ntfs_read_super_mft; } ntfs_debug(DEBUG_OTHER, "Getting RootDir\n"); /* Get the root directory. */ if (!(sb->s_root = d_alloc_root(iget(sb, FILE_root)))) { ntfs_error("Could not get root dir inode\n"); goto ntfs_read_super_mft; }ntfs_read_super_ret: ntfs_debug(DEBUG_OTHER, "read_super: done\n"); return sb;ntfs_read_super_mft: ntfs_free(vol->mft);ntfs_read_super_unl:ntfs_read_super_vol: sb = NULL; goto ntfs_read_super_ret;}/* Define the filesystem */static DECLARE_FSTYPE_DEV(ntfs_fs_type, "ntfs", ntfs_read_super);static int __init init_ntfs_fs(void){ /* Comment this if you trust klogd. There are reasons not to trust it */#if defined(DEBUG) && !defined(MODULE) console_verbose();#endif printk(KERN_NOTICE "NTFS driver v" NTFS_VERSION " [Flags: R/"#ifdef CONFIG_NTFS_RW "W"#else "O"#endif#ifdef DEBUG " DEBUG"#endif#ifdef MODULE " MODULE"#endif "]\n"); SYSCTL(1); ntfs_debug(DEBUG_OTHER, "registering %s\n", ntfs_fs_type.name); /* Add this filesystem to the kernel table of filesystems. */ return register_filesystem(&ntfs_fs_type);}static void __exit exit_ntfs_fs(void){ SYSCTL(0); ntfs_debug(DEBUG_OTHER, "unregistering %s\n", ntfs_fs_type.name); unregister_filesystem(&ntfs_fs_type);}EXPORT_NO_SYMBOLS;/* * Not strictly true. The driver was written originally by Martin von L鰓is. * I am just maintaining and rewriting it. */MODULE_AUTHOR("Anton Altaparmakov <aia21@cus.cam.ac.uk>");MODULE_DESCRIPTION("Linux NTFS driver");MODULE_LICENSE("GPL");#ifdef DEBUGMODULE_PARM(ntdebug, "i");MODULE_PARM_DESC(ntdebug, "Debug level");#endifmodule_init(init_ntfs_fs)module_exit(exit_ntfs_fs)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -