📄 inode.c
字号:
/* * Set defaults, but the inode is still incomplete! * Note: get_new_inode() sets the following on a new inode: * i_sb = sb * i_no = ino * i_flags = sb->s_flags * i_state = 0 * clean_inode(): zero fills and sets * i_count = 1 * i_nlink = 1 * i_op = NULL; */ bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident); if (!bh) { printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed !bh\n", inode->i_ino); make_bad_inode(inode); return; } if (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE && ident != TAG_IDENT_USE) { printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed ident=%d\n", inode->i_ino, ident); brelse(bh); make_bad_inode(inode); return; } fe = (struct fileEntry *)bh->b_data; if (le16_to_cpu(fe->icbTag.strategyType) == 4096) { struct buffer_head *ibh = NULL, *nbh = NULL; struct indirectEntry *ie; ibh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 1, &ident); if (ident == TAG_IDENT_IE) { if (ibh) { kernel_lb_addr loc; ie = (struct indirectEntry *)ibh->b_data; loc = lelb_to_cpu(ie->indirectICB.extLocation); if (ie->indirectICB.extLength && (nbh = udf_read_ptagged(inode->i_sb, loc, 0, &ident))) { if (ident == TAG_IDENT_FE || ident == TAG_IDENT_EFE) { memcpy(&UDF_I_LOCATION(inode), &loc, sizeof(kernel_lb_addr)); brelse(bh); brelse(ibh); brelse(nbh); __udf_read_inode(inode); return; } else { brelse(nbh); brelse(ibh); } } else { brelse(ibh); } } } else { brelse(ibh); } } else if (le16_to_cpu(fe->icbTag.strategyType) != 4) { printk(KERN_ERR "udf: unsupported strategy type: %d\n", le16_to_cpu(fe->icbTag.strategyType)); brelse(bh); make_bad_inode(inode); return; } udf_fill_inode(inode, bh); brelse(bh);}static void udf_fill_inode(struct inode *inode, struct buffer_head *bh){ struct fileEntry *fe; struct extendedFileEntry *efe; time_t convtime; long convtime_usec; int offset; fe = (struct fileEntry *)bh->b_data; efe = (struct extendedFileEntry *)bh->b_data; if (le16_to_cpu(fe->icbTag.strategyType) == 4) UDF_I_STRAT4096(inode) = 0; else /* if (le16_to_cpu(fe->icbTag.strategyType) == 4096) */ UDF_I_STRAT4096(inode) = 1; UDF_I_ALLOCTYPE(inode) = le16_to_cpu(fe->icbTag.flags) & ICBTAG_FLAG_AD_MASK; UDF_I_UNIQUE(inode) = 0; UDF_I_LENEATTR(inode) = 0; UDF_I_LENEXTENTS(inode) = 0; UDF_I_LENALLOC(inode) = 0; UDF_I_NEXT_ALLOC_BLOCK(inode) = 0; UDF_I_NEXT_ALLOC_GOAL(inode) = 0; if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_EFE) { UDF_I_EFE(inode) = 1; UDF_I_USE(inode) = 0; if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry))) { make_bad_inode(inode); return; } memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct extendedFileEntry), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry)); } else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE) { UDF_I_EFE(inode) = 0; UDF_I_USE(inode) = 0; if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct fileEntry))) { make_bad_inode(inode); return; } memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct fileEntry), inode->i_sb->s_blocksize - sizeof(struct fileEntry)); } else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE) { UDF_I_EFE(inode) = 0; UDF_I_USE(inode) = 1; UDF_I_LENALLOC(inode) = le32_to_cpu(((struct unallocSpaceEntry *)bh->b_data)->lengthAllocDescs); if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry))) { make_bad_inode(inode); return; } memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct unallocSpaceEntry), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry)); return; } inode->i_uid = le32_to_cpu(fe->uid); if (inode->i_uid == -1 || UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_IGNORE) || UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_SET)) inode->i_uid = UDF_SB(inode->i_sb)->s_uid; inode->i_gid = le32_to_cpu(fe->gid); if (inode->i_gid == -1 || UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_IGNORE) || UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_SET)) inode->i_gid = UDF_SB(inode->i_sb)->s_gid; inode->i_nlink = le16_to_cpu(fe->fileLinkCount); if (!inode->i_nlink) inode->i_nlink = 1; inode->i_size = le64_to_cpu(fe->informationLength); UDF_I_LENEXTENTS(inode) = inode->i_size; inode->i_mode = udf_convert_permissions(fe); inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask; if (UDF_I_EFE(inode) == 0) { inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) << (inode->i_sb->s_blocksize_bits - 9); if (udf_stamp_to_time(&convtime, &convtime_usec, lets_to_cpu(fe->accessTime))) { inode->i_atime.tv_sec = convtime; inode->i_atime.tv_nsec = convtime_usec * 1000; } else { inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb); } if (udf_stamp_to_time(&convtime, &convtime_usec, lets_to_cpu(fe->modificationTime))) { inode->i_mtime.tv_sec = convtime; inode->i_mtime.tv_nsec = convtime_usec * 1000; } else { inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb); } if (udf_stamp_to_time(&convtime, &convtime_usec, lets_to_cpu(fe->attrTime))) { inode->i_ctime.tv_sec = convtime; inode->i_ctime.tv_nsec = convtime_usec * 1000; } else { inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb); } UDF_I_UNIQUE(inode) = le64_to_cpu(fe->uniqueID); UDF_I_LENEATTR(inode) = le32_to_cpu(fe->lengthExtendedAttr); UDF_I_LENALLOC(inode) = le32_to_cpu(fe->lengthAllocDescs); offset = sizeof(struct fileEntry) + UDF_I_LENEATTR(inode); } else { inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << (inode->i_sb->s_blocksize_bits - 9); if (udf_stamp_to_time(&convtime, &convtime_usec, lets_to_cpu(efe->accessTime))) { inode->i_atime.tv_sec = convtime; inode->i_atime.tv_nsec = convtime_usec * 1000; } else { inode->i_atime = UDF_SB_RECORDTIME(inode->i_sb); } if (udf_stamp_to_time(&convtime, &convtime_usec, lets_to_cpu(efe->modificationTime))) { inode->i_mtime.tv_sec = convtime; inode->i_mtime.tv_nsec = convtime_usec * 1000; } else { inode->i_mtime = UDF_SB_RECORDTIME(inode->i_sb); } if (udf_stamp_to_time(&convtime, &convtime_usec, lets_to_cpu(efe->createTime))) { UDF_I_CRTIME(inode).tv_sec = convtime; UDF_I_CRTIME(inode).tv_nsec = convtime_usec * 1000; } else { UDF_I_CRTIME(inode) = UDF_SB_RECORDTIME(inode->i_sb); } if (udf_stamp_to_time(&convtime, &convtime_usec, lets_to_cpu(efe->attrTime))) { inode->i_ctime.tv_sec = convtime; inode->i_ctime.tv_nsec = convtime_usec * 1000; } else { inode->i_ctime = UDF_SB_RECORDTIME(inode->i_sb); } UDF_I_UNIQUE(inode) = le64_to_cpu(efe->uniqueID); UDF_I_LENEATTR(inode) = le32_to_cpu(efe->lengthExtendedAttr); UDF_I_LENALLOC(inode) = le32_to_cpu(efe->lengthAllocDescs); offset = sizeof(struct extendedFileEntry) + UDF_I_LENEATTR(inode); } switch (fe->icbTag.fileType) { case ICBTAG_FILE_TYPE_DIRECTORY: inode->i_op = &udf_dir_inode_operations; inode->i_fop = &udf_dir_operations; inode->i_mode |= S_IFDIR; inc_nlink(inode); break; case ICBTAG_FILE_TYPE_REALTIME: case ICBTAG_FILE_TYPE_REGULAR: case ICBTAG_FILE_TYPE_UNDEF: if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB) inode->i_data.a_ops = &udf_adinicb_aops; else inode->i_data.a_ops = &udf_aops; inode->i_op = &udf_file_inode_operations; inode->i_fop = &udf_file_operations; inode->i_mode |= S_IFREG; break; case ICBTAG_FILE_TYPE_BLOCK: inode->i_mode |= S_IFBLK; break; case ICBTAG_FILE_TYPE_CHAR: inode->i_mode |= S_IFCHR; break; case ICBTAG_FILE_TYPE_FIFO: init_special_inode(inode, inode->i_mode | S_IFIFO, 0); break; case ICBTAG_FILE_TYPE_SOCKET: init_special_inode(inode, inode->i_mode | S_IFSOCK, 0); break; case ICBTAG_FILE_TYPE_SYMLINK: inode->i_data.a_ops = &udf_symlink_aops; inode->i_op = &page_symlink_inode_operations; inode->i_mode = S_IFLNK | S_IRWXUGO; break; default: printk(KERN_ERR "udf: udf_fill_inode(ino %ld) failed unknown file type=%d\n", inode->i_ino, fe->icbTag.fileType); make_bad_inode(inode); return; } if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { struct deviceSpec *dsea = (struct deviceSpec *)udf_get_extendedattr(inode, 12, 1); if (dsea) { init_special_inode(inode, inode->i_mode, MKDEV(le32_to_cpu(dsea->majorDeviceIdent), le32_to_cpu(dsea->minorDeviceIdent))); /* Developer ID ??? */ } else { make_bad_inode(inode); } }}static int udf_alloc_i_data(struct inode *inode, size_t size){ UDF_I_DATA(inode) = kmalloc(size, GFP_KERNEL); if (!UDF_I_DATA(inode)) { printk(KERN_ERR "udf:udf_alloc_i_data (ino %ld) no free memory\n", inode->i_ino); return -ENOMEM; } return 0;}static mode_t udf_convert_permissions(struct fileEntry *fe){ mode_t mode; uint32_t permissions; uint32_t flags; permissions = le32_to_cpu(fe->permissions); flags = le16_to_cpu(fe->icbTag.flags); mode = (( permissions ) & S_IRWXO) | (( permissions >> 2 ) & S_IRWXG) | (( permissions >> 4 ) & S_IRWXU) | (( flags & ICBTAG_FLAG_SETUID) ? S_ISUID : 0) | (( flags & ICBTAG_FLAG_SETGID) ? S_ISGID : 0) | (( flags & ICBTAG_FLAG_STICKY) ? S_ISVTX : 0); return mode;}/* * udf_write_inode * * PURPOSE * Write out the specified inode. * * DESCRIPTION * This routine is called whenever an inode is synced. * Currently this routine is just a placeholder. * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */int udf_write_inode(struct inode *inode, int sync){ int ret; lock_kernel(); ret = udf_update_inode(inode, sync); unlock_kernel(); return ret;}int udf_sync_inode(struct inode *inode){ return udf_update_inode(inode, 1);}static int udf_update_inode(struct inode *inode, int do_sync){ struct buffer_head *bh = NULL; struct fileEntry *fe; struct extendedFileEntry *efe; uint32_t udfperms; uint16_t icbflags; uint16_t crclen; int i; kernel_timestamp cpu_time; int err = 0; bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0)); if (!bh) { udf_debug("bread failure\n"); return -EIO; } memset(bh->b_data, 0x00, inode->i_sb->s_blocksize); fe = (struct fileEntry *)bh->b_data; efe = (struct extendedFileEntry *)bh->b_data; if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE) { struct unallocSpaceEntry *use = (struct unallocSpaceEntry *)bh->b_data; use->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode)); memcpy(bh->b_data + sizeof(struct unallocSpaceEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry)); crclen = sizeof(struct unallocSpaceEntry) + UDF_I_LENALLOC(inode) - sizeof(tag); use->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum); use->descTag.descCRCLength = cpu_to_le16(crclen); use->descTag.descCRC = cpu_to_le16(udf_crc((char *)use + sizeof(tag), crclen, 0)); use->descTag.tagChecksum = 0; for (i = 0; i < 16; i++) { if (i != 4) use->descTag.tagChecksum += ((uint8_t *)&(use->descTag))[i]; } mark_buffer_dirty(bh); brelse(bh); return err; } if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET)) fe->uid = cpu_to_le32(-1); else fe->uid = cpu_to_le32(inode->i_uid); if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_FORGET)) fe->gid = cpu_to_le32(-1); else fe->gid = cpu_to_le32(inode->i_gid); udfperms = ((inode->i_mode & S_IRWXO) ) | ((inode->i_mode & S_IRWXG) << 2) | ((inode->i_mode & S_IRWXU) << 4); udfperms |= (le32_to_cpu(fe->permissions) & (FE_PERM_O_DELETE | FE_PERM_O_CHATTR | FE_PERM_G_DELETE | FE_PERM_G_CHATTR | FE_PERM_U_DELETE | FE_PERM_U_CHATTR)); fe->permissions = cpu_to_le32(udfperms); if (S_ISDIR(inode->i_mode)) fe->fileLinkCount = cpu_to_le16(inode->i_nlink - 1); else fe->fileLinkCount = cpu_to_le16(inode->i_nlink); fe->informationLength = cpu_to_le64(inode->i_size); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { regid *eid; struct deviceSpec *dsea = (struct deviceSpec *)udf_get_extendedattr(inode, 12, 1); if (!dsea) { dsea = (struct deviceSpec *) udf_add_extendedattr(inode, sizeof(struct deviceSpec) + sizeof(regid), 12, 0x3); dsea->attrType = cpu_to_le32(12); dsea->attrSubtype = 1; dsea->attrLength = cpu_to_le32(sizeof(struct deviceSpec) + sizeof(regid)); dsea->impUseLength = cpu_to_le32(sizeof(regid)); } eid = (regid *)dsea->impUse; memset(eid, 0, sizeof(regid)); strcpy(eid->ident, UDF_ID_DEVELOPER); eid->identSuffix[0] = UDF_OS_CLASS_UNIX; eid->identSuffix[1] = UDF_OS_ID_LINUX; dsea->majorDeviceIdent = cpu_to_le32(imajor(inode)); dsea->minorDeviceIdent = cpu_to_le32(iminor(inode)); } if (UDF_I_EFE(inode) == 0) { memcpy(bh->b_data + sizeof(struct fileEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct fileEntry)); fe->logicalBlocksRecorded = cpu_to_le64( (inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >> (inode->i_sb->s_blocksize_bits - 9)); if (udf_time_to_stamp(&cpu_time, inode->i_atime)) fe->accessTime = cpu_to_lets(cpu_time); if (udf_time_to_stamp(&cpu_time, inode->i_mtime)) fe->modificationTime = cpu_to_lets(cpu_time); if (udf_time_to_stamp(&cpu_time, inode->i_ctime)) fe->attrTime = cpu_to_lets(cpu_time); memset(&(fe->impIdent), 0, sizeof(regid)); strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER); fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; fe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; fe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode)); fe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode)); fe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode)); fe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_FE); crclen = sizeof(struct fileEntry); } else { memcpy(bh->b_data + sizeof(struct extendedFileEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry)); efe->objectSize = cpu_to_le64(inode->i_size); efe->logicalBlocksRecorded = cpu_to_le64( (inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >> (inode->i_sb->s_blocksize_bits - 9)); if (UDF_I_CRTIME(inode).tv_sec > inode->i_atime.tv_sec || (UDF_I_CRTIME(inode).tv_sec == inode->i_atime.tv_sec && UDF_I_CRTIME(inode).tv_nsec > inode->i_atime.tv_nsec)) { UDF_I_CRTIME(inode) = inode->i_atime; } if (UDF_I_CRTIME(inode).tv_sec > inode->i_mtime.tv_sec || (UDF_I_CRTIME(inode).tv_sec == inode->i_mtime.tv_sec && UDF_I_CRTIME(inode).tv_nsec > inode->i_mtime.tv_nsec)) { UDF_I_CRTIME(inode) = inode->i_mtime; } if (UDF_I_CRTIME(inode).tv_sec > inode->i_ctime.tv_sec || (UDF_I_CRTIME(inode).tv_sec == inode->i_ctime.tv_sec && UDF_I_CRTIME(inode).tv_nsec > inode->i_ctime.tv_nsec)) { UDF_I_CRTIME(inode) = inode->i_ctime; } if (udf_time_to_stamp(&cpu_time, inode->i_atime)) efe->accessTime = cpu_to_lets(cpu_time); if (udf_time_to_stamp(&cpu_time, inode->i_mtime)) efe->modificationTime = cpu_to_lets(cpu_time); if (udf_time_to_stamp(&cpu_time, UDF_I_CRTIME(inode))) efe->createTime = cpu_to_lets(cpu_time); if (udf_time_to_stamp(&cpu_time, inode->i_ctime)) efe->attrTime = cpu_to_lets(cpu_time); memset(&(efe->impIdent), 0, sizeof(regid));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -