📄 inode.c
字号:
strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER); efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; efe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; efe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode)); efe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode)); efe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode)); efe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EFE); crclen = sizeof(struct extendedFileEntry); } if (UDF_I_STRAT4096(inode)) { fe->icbTag.strategyType = cpu_to_le16(4096); fe->icbTag.strategyParameter = cpu_to_le16(1); fe->icbTag.numEntries = cpu_to_le16(2); } else { fe->icbTag.strategyType = cpu_to_le16(4); fe->icbTag.numEntries = cpu_to_le16(1); } if (S_ISDIR(inode->i_mode)) fe->icbTag.fileType = ICBTAG_FILE_TYPE_DIRECTORY; else if (S_ISREG(inode->i_mode)) fe->icbTag.fileType = ICBTAG_FILE_TYPE_REGULAR; else if (S_ISLNK(inode->i_mode)) fe->icbTag.fileType = ICBTAG_FILE_TYPE_SYMLINK; else if (S_ISBLK(inode->i_mode)) fe->icbTag.fileType = ICBTAG_FILE_TYPE_BLOCK; else if (S_ISCHR(inode->i_mode)) fe->icbTag.fileType = ICBTAG_FILE_TYPE_CHAR; else if (S_ISFIFO(inode->i_mode)) fe->icbTag.fileType = ICBTAG_FILE_TYPE_FIFO; else if (S_ISSOCK(inode->i_mode)) fe->icbTag.fileType = ICBTAG_FILE_TYPE_SOCKET; icbflags = UDF_I_ALLOCTYPE(inode) | ((inode->i_mode & S_ISUID) ? ICBTAG_FLAG_SETUID : 0) | ((inode->i_mode & S_ISGID) ? ICBTAG_FLAG_SETGID : 0) | ((inode->i_mode & S_ISVTX) ? ICBTAG_FLAG_STICKY : 0) | (le16_to_cpu(fe->icbTag.flags) & ~(ICBTAG_FLAG_AD_MASK | ICBTAG_FLAG_SETUID | ICBTAG_FLAG_SETGID | ICBTAG_FLAG_STICKY)); fe->icbTag.flags = cpu_to_le16(icbflags); if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200) fe->descTag.descVersion = cpu_to_le16(3); else fe->descTag.descVersion = cpu_to_le16(2); fe->descTag.tagSerialNum = cpu_to_le16(UDF_SB_SERIALNUM(inode->i_sb)); fe->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum); crclen += UDF_I_LENEATTR(inode) + UDF_I_LENALLOC(inode) - sizeof(tag); fe->descTag.descCRCLength = cpu_to_le16(crclen); fe->descTag.descCRC = cpu_to_le16(udf_crc((char *)fe + sizeof(tag), crclen, 0)); fe->descTag.tagChecksum = 0; for (i = 0; i < 16; i++) { if (i != 4) fe->descTag.tagChecksum += ((uint8_t *)&(fe->descTag))[i]; } /* write the data blocks */ mark_buffer_dirty(bh); if (do_sync) { sync_dirty_buffer(bh); if (buffer_req(bh) && !buffer_uptodate(bh)) { printk("IO error syncing udf inode [%s:%08lx]\n", inode->i_sb->s_id, inode->i_ino); err = -EIO; } } brelse(bh); return err;}struct inode *udf_iget(struct super_block *sb, kernel_lb_addr ino){ unsigned long block = udf_get_lb_pblock(sb, ino, 0); struct inode *inode = iget_locked(sb, block); if (!inode) return NULL; if (inode->i_state & I_NEW) { memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(kernel_lb_addr)); __udf_read_inode(inode); unlock_new_inode(inode); } if (is_bad_inode(inode)) goto out_iput; if (ino.logicalBlockNum >= UDF_SB_PARTLEN(sb, ino.partitionReferenceNum)) { udf_debug("block=%d, partition=%d out of range\n", ino.logicalBlockNum, ino.partitionReferenceNum); make_bad_inode(inode); goto out_iput; } return inode; out_iput: iput(inode); return NULL;}int8_t udf_add_aext(struct inode * inode, struct extent_position * epos, kernel_lb_addr eloc, uint32_t elen, int inc){ int adsize; short_ad *sad = NULL; long_ad *lad = NULL; struct allocExtDesc *aed; int8_t etype; uint8_t *ptr; if (!epos->bh) ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode); else ptr = epos->bh->b_data + epos->offset; if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT) adsize = sizeof(short_ad); else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG) adsize = sizeof(long_ad); else return -1; if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize) { char *sptr, *dptr; struct buffer_head *nbh; int err, loffset; kernel_lb_addr obloc = epos->block; if (!(epos->block.logicalBlockNum = udf_new_block(inode->i_sb, NULL, obloc.partitionReferenceNum, obloc.logicalBlockNum, &err))) { return -1; } if (!(nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb, epos->block, 0)))) { return -1; } lock_buffer(nbh); memset(nbh->b_data, 0x00, inode->i_sb->s_blocksize); set_buffer_uptodate(nbh); unlock_buffer(nbh); mark_buffer_dirty_inode(nbh, inode); aed = (struct allocExtDesc *)(nbh->b_data); if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT)) aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum); if (epos->offset + adsize > inode->i_sb->s_blocksize) { loffset = epos->offset; aed->lengthAllocDescs = cpu_to_le32(adsize); sptr = ptr - adsize; dptr = nbh->b_data + sizeof(struct allocExtDesc); memcpy(dptr, sptr, adsize); epos->offset = sizeof(struct allocExtDesc) + adsize; } else { loffset = epos->offset + adsize; aed->lengthAllocDescs = cpu_to_le32(0); sptr = ptr; epos->offset = sizeof(struct allocExtDesc); if (epos->bh) { aed = (struct allocExtDesc *)epos->bh->b_data; aed->lengthAllocDescs = cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize); } else { UDF_I_LENALLOC(inode) += adsize; mark_inode_dirty(inode); } } if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200) udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1, epos->block.logicalBlockNum, sizeof(tag)); else udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1, epos->block.logicalBlockNum, sizeof(tag)); switch (UDF_I_ALLOCTYPE(inode)) { case ICBTAG_FLAG_AD_SHORT: sad = (short_ad *)sptr; sad->extLength = cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS | inode->i_sb->s_blocksize); sad->extPosition = cpu_to_le32(epos->block.logicalBlockNum); break; case ICBTAG_FLAG_AD_LONG: lad = (long_ad *)sptr; lad->extLength = cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS | inode->i_sb->s_blocksize); lad->extLocation = cpu_to_lelb(epos->block); memset(lad->impUse, 0x00, sizeof(lad->impUse)); break; } if (epos->bh) { if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) udf_update_tag(epos->bh->b_data, loffset); else udf_update_tag(epos->bh->b_data, sizeof(struct allocExtDesc)); mark_buffer_dirty_inode(epos->bh, inode); brelse(epos->bh); } else { mark_inode_dirty(inode); } epos->bh = nbh; } etype = udf_write_aext(inode, epos, eloc, elen, inc); if (!epos->bh) { UDF_I_LENALLOC(inode) += adsize; mark_inode_dirty(inode); } else { aed = (struct allocExtDesc *)epos->bh->b_data; aed->lengthAllocDescs = cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize); if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) udf_update_tag(epos->bh->b_data, epos->offset + (inc ? 0 : adsize)); else udf_update_tag(epos->bh->b_data, sizeof(struct allocExtDesc)); mark_buffer_dirty_inode(epos->bh, inode); } return etype;}int8_t udf_write_aext(struct inode * inode, struct extent_position * epos, kernel_lb_addr eloc, uint32_t elen, int inc){ int adsize; uint8_t *ptr; short_ad *sad; long_ad *lad; if (!epos->bh) ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode); else ptr = epos->bh->b_data + epos->offset; switch (UDF_I_ALLOCTYPE(inode)) { case ICBTAG_FLAG_AD_SHORT: sad = (short_ad *)ptr; sad->extLength = cpu_to_le32(elen); sad->extPosition = cpu_to_le32(eloc.logicalBlockNum); adsize = sizeof(short_ad); break; case ICBTAG_FLAG_AD_LONG: lad = (long_ad *)ptr; lad->extLength = cpu_to_le32(elen); lad->extLocation = cpu_to_lelb(eloc); memset(lad->impUse, 0x00, sizeof(lad->impUse)); adsize = sizeof(long_ad); break; default: return -1; } if (epos->bh) { if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) { struct allocExtDesc *aed = (struct allocExtDesc *)epos->bh->b_data; udf_update_tag(epos->bh->b_data, le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct allocExtDesc)); } mark_buffer_dirty_inode(epos->bh, inode); } else { mark_inode_dirty(inode); } if (inc) epos->offset += adsize; return (elen >> 30);}int8_t udf_next_aext(struct inode * inode, struct extent_position * epos, kernel_lb_addr * eloc, uint32_t * elen, int inc){ int8_t etype; while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) { epos->block = *eloc; epos->offset = sizeof(struct allocExtDesc); brelse(epos->bh); if (!(epos->bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, epos->block, 0)))) { udf_debug("reading block %d failed!\n", udf_get_lb_pblock(inode->i_sb, epos->block, 0)); return -1; } } return etype;}int8_t udf_current_aext(struct inode * inode, struct extent_position * epos, kernel_lb_addr * eloc, uint32_t * elen, int inc){ int alen; int8_t etype; uint8_t *ptr; short_ad *sad; long_ad *lad; if (!epos->bh) { if (!epos->offset) epos->offset = udf_file_entry_alloc_offset(inode); ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode); alen = udf_file_entry_alloc_offset(inode) + UDF_I_LENALLOC(inode); } else { if (!epos->offset) epos->offset = sizeof(struct allocExtDesc); ptr = epos->bh->b_data + epos->offset; alen = sizeof(struct allocExtDesc) + le32_to_cpu(((struct allocExtDesc *)epos->bh->b_data)->lengthAllocDescs); } switch (UDF_I_ALLOCTYPE(inode)) { case ICBTAG_FLAG_AD_SHORT: if (!(sad = udf_get_fileshortad(ptr, alen, &epos->offset, inc))) return -1; etype = le32_to_cpu(sad->extLength) >> 30; eloc->logicalBlockNum = le32_to_cpu(sad->extPosition); eloc->partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum; *elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK; break; case ICBTAG_FLAG_AD_LONG: if (!(lad = udf_get_filelongad(ptr, alen, &epos->offset, inc))) return -1; etype = le32_to_cpu(lad->extLength) >> 30; *eloc = lelb_to_cpu(lad->extLocation); *elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK; break; default: udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode)); return -1; } return etype;}static int8_t udf_insert_aext(struct inode *inode, struct extent_position epos, kernel_lb_addr neloc, uint32_t nelen){ kernel_lb_addr oeloc; uint32_t oelen; int8_t etype; if (epos.bh) get_bh(epos.bh); while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1) { udf_write_aext(inode, &epos, neloc, nelen, 1); neloc = oeloc; nelen = (etype << 30) | oelen; } udf_add_aext(inode, &epos, neloc, nelen, 1); brelse(epos.bh); return (nelen >> 30);}int8_t udf_delete_aext(struct inode * inode, struct extent_position epos, kernel_lb_addr eloc, uint32_t elen){ struct extent_position oepos; int adsize; int8_t etype; struct allocExtDesc *aed; if (epos.bh) { get_bh(epos.bh); get_bh(epos.bh); } if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT) adsize = sizeof(short_ad); else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG) adsize = sizeof(long_ad); else adsize = 0; oepos = epos; if (udf_next_aext(inode, &epos, &eloc, &elen, 1) == -1) return -1; while ((etype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) { udf_write_aext(inode, &oepos, eloc, (etype << 30) | elen, 1); if (oepos.bh != epos.bh) { oepos.block = epos.block; brelse(oepos.bh); get_bh(epos.bh); oepos.bh = epos.bh; oepos.offset = epos.offset - adsize; } } memset(&eloc, 0x00, sizeof(kernel_lb_addr)); elen = 0; if (epos.bh != oepos.bh) { udf_free_blocks(inode->i_sb, inode, epos.block, 0, 1); udf_write_aext(inode, &oepos, eloc, elen, 1); udf_write_aext(inode, &oepos, eloc, elen, 1); if (!oepos.bh) { UDF_I_LENALLOC(inode) -= (adsize * 2); mark_inode_dirty(inode); } else { aed = (struct allocExtDesc *)oepos.bh->b_data; aed->lengthAllocDescs = cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - (2 * adsize)); if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) udf_update_tag(oepos.bh->b_data, oepos.offset - (2 * adsize)); else udf_update_tag(oepos.bh->b_data, sizeof(struct allocExtDesc)); mark_buffer_dirty_inode(oepos.bh, inode); } } else { udf_write_aext(inode, &oepos, eloc, elen, 1); if (!oepos.bh) { UDF_I_LENALLOC(inode) -= adsize; mark_inode_dirty(inode); } else { aed = (struct allocExtDesc *)oepos.bh->b_data; aed->lengthAllocDescs = cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - adsize); if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) udf_update_tag(oepos.bh->b_data, epos.offset - adsize); else udf_update_tag(oepos.bh->b_data, sizeof(struct allocExtDesc)); mark_buffer_dirty_inode(oepos.bh, inode); } } brelse(epos.bh); brelse(oepos.bh); return (elen >> 30);}int8_t inode_bmap(struct inode * inode, sector_t block, struct extent_position * pos, kernel_lb_addr * eloc, uint32_t * elen, sector_t * offset){ loff_t lbcount = 0, bcount = (loff_t) block << inode->i_sb->s_blocksize_bits; int8_t etype; if (block < 0) { printk(KERN_ERR "udf: inode_bmap: block < 0\n"); return -1; } pos->offset = 0; pos->block = UDF_I_LOCATION(inode); pos->bh = NULL; *elen = 0; do { if ((etype = udf_next_aext(inode, pos, eloc, elen, 1)) == -1) { *offset = (bcount - lbcount) >> inode->i_sb->s_blocksize_bits; UDF_I_LENEXTENTS(inode) = lbcount; return -1; } lbcount += *elen; } while (lbcount <= bcount); *offset = (bcount + *elen - lbcount) >> inode->i_sb->s_blocksize_bits; return etype;}long udf_block_map(struct inode *inode, sector_t block){ kernel_lb_addr eloc; uint32_t elen; sector_t offset; struct extent_position epos = {}; int ret; lock_kernel(); if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) ret = udf_get_lb_pblock(inode->i_sb, eloc, offset); else ret = 0; unlock_kernel(); brelse(epos.bh); if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV)) return udf_fixed_to_variable(ret); else return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -