📄 namei.c
字号:
inode->i_ctime = dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb); mark_inode_dirty(dir);end_rmdir: if (fibh.sbh != fibh.ebh) brelse(fibh.ebh); brelse(fibh.sbh);out: unlock_kernel(); return retval;}static int udf_unlink(struct inode *dir, struct dentry *dentry){ int retval; struct inode *inode = dentry->d_inode; struct udf_fileident_bh fibh; struct fileIdentDesc *fi; struct fileIdentDesc cfi; kernel_lb_addr tloc; retval = -ENOENT; lock_kernel(); fi = udf_find_entry(dir, dentry, &fibh, &cfi); if (!fi) goto out; retval = -EIO; tloc = lelb_to_cpu(cfi.icb.extLocation); if (udf_get_lb_pblock(dir->i_sb, tloc, 0) != inode->i_ino) goto end_unlink; if (!inode->i_nlink) { udf_debug("Deleting nonexistent file (%lu), %d\n", inode->i_ino, inode->i_nlink); inode->i_nlink = 1; } retval = udf_delete_entry(dir, fi, &fibh, &cfi); if (retval) goto end_unlink; dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb); mark_inode_dirty(dir); inode_dec_link_count(inode); inode->i_ctime = dir->i_ctime; retval = 0;end_unlink: if (fibh.sbh != fibh.ebh) brelse(fibh.ebh); brelse(fibh.sbh);out: unlock_kernel(); return retval;}static int udf_symlink(struct inode *dir, struct dentry *dentry, const char *symname){ struct inode *inode; struct pathComponent *pc; char *compstart; struct udf_fileident_bh fibh; struct extent_position epos = {}; int eoffset, elen = 0; struct fileIdentDesc *fi; struct fileIdentDesc cfi; char *ea; int err; int block; char name[UDF_NAME_LEN]; int namelen; lock_kernel(); if (!(inode = udf_new_inode(dir, S_IFLNK, &err))) goto out; inode->i_mode = S_IFLNK | S_IRWXUGO; inode->i_data.a_ops = &udf_symlink_aops; inode->i_op = &page_symlink_inode_operations; if (UDF_I_ALLOCTYPE(inode) != ICBTAG_FLAG_AD_IN_ICB) { kernel_lb_addr eloc; uint32_t elen; block = udf_new_block(inode->i_sb, inode, UDF_I_LOCATION(inode).partitionReferenceNum, UDF_I_LOCATION(inode).logicalBlockNum, &err); if (!block) goto out_no_entry; epos.block = UDF_I_LOCATION(inode); epos.offset = udf_file_entry_alloc_offset(inode); epos.bh = NULL; eloc.logicalBlockNum = block; eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum; elen = inode->i_sb->s_blocksize; UDF_I_LENEXTENTS(inode) = elen; udf_add_aext(inode, &epos, eloc, elen, 0); brelse(epos.bh); block = udf_get_pblock(inode->i_sb, block, UDF_I_LOCATION(inode).partitionReferenceNum, 0); epos.bh = udf_tread(inode->i_sb, block); lock_buffer(epos.bh); memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize); set_buffer_uptodate(epos.bh); unlock_buffer(epos.bh); mark_buffer_dirty_inode(epos.bh, inode); ea = epos.bh->b_data + udf_ext0_offset(inode); } else { ea = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode); } eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode); pc = (struct pathComponent *)ea; if (*symname == '/') { do { symname++; } while (*symname == '/'); pc->componentType = 1; pc->lengthComponentIdent = 0; pc->componentFileVersionNum = 0; pc += sizeof(struct pathComponent); elen += sizeof(struct pathComponent); } err = -ENAMETOOLONG; while (*symname) { if (elen + sizeof(struct pathComponent) > eoffset) goto out_no_entry; pc = (struct pathComponent *)(ea + elen); compstart = (char *)symname; do { symname++; } while (*symname && *symname != '/'); pc->componentType = 5; pc->lengthComponentIdent = 0; pc->componentFileVersionNum = 0; if (compstart[0] == '.') { if ((symname - compstart) == 1) pc->componentType = 4; else if ((symname - compstart) == 2 && compstart[1] == '.') pc->componentType = 3; } if (pc->componentType == 5) { namelen = udf_put_filename(inode->i_sb, compstart, name, symname - compstart); if (!namelen) goto out_no_entry; if (elen + sizeof(struct pathComponent) + namelen > eoffset) goto out_no_entry; else pc->lengthComponentIdent = namelen; memcpy(pc->componentIdent, name, namelen); } elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; if (*symname) { do { symname++; } while (*symname == '/'); } } brelse(epos.bh); inode->i_size = elen; if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB) UDF_I_LENALLOC(inode) = inode->i_size; mark_inode_dirty(inode); if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) goto out_no_entry; cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode)); if (UDF_SB_LVIDBH(inode->i_sb)) { struct logicalVolHeaderDesc *lvhd; uint64_t uniqueID; lvhd = (struct logicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse); uniqueID = le64_to_cpu(lvhd->uniqueID); *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL); if (!(++uniqueID & 0x00000000FFFFFFFFUL)) uniqueID += 16; lvhd->uniqueID = cpu_to_le64(uniqueID); mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb)); } udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) { mark_inode_dirty(dir); } if (fibh.sbh != fibh.ebh) brelse(fibh.ebh); brelse(fibh.sbh); d_instantiate(dentry, inode); err = 0;out: unlock_kernel(); return err;out_no_entry: inode_dec_link_count(inode); iput(inode); goto out;}static int udf_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry){ struct inode *inode = old_dentry->d_inode; struct udf_fileident_bh fibh; struct fileIdentDesc cfi, *fi; int err; lock_kernel(); if (inode->i_nlink >= (256 << sizeof(inode->i_nlink)) - 1) { unlock_kernel(); return -EMLINK; } if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) { unlock_kernel(); return err; } cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode)); if (UDF_SB_LVIDBH(inode->i_sb)) { struct logicalVolHeaderDesc *lvhd; uint64_t uniqueID; lvhd = (struct logicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse); uniqueID = le64_to_cpu(lvhd->uniqueID); *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL); if (!(++uniqueID & 0x00000000FFFFFFFFUL)) uniqueID += 16; lvhd->uniqueID = cpu_to_le64(uniqueID); mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb)); } udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) { mark_inode_dirty(dir); } if (fibh.sbh != fibh.ebh) brelse(fibh.ebh); brelse(fibh.sbh); inc_nlink(inode); inode->i_ctime = current_fs_time(inode->i_sb); mark_inode_dirty(inode); atomic_inc(&inode->i_count); d_instantiate(dentry, inode); unlock_kernel(); return 0;}/* Anybody can rename anything with this: the permission checks are left to the * higher-level routines. */static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry){ struct inode *old_inode = old_dentry->d_inode; struct inode *new_inode = new_dentry->d_inode; struct udf_fileident_bh ofibh, nfibh; struct fileIdentDesc *ofi = NULL, *nfi = NULL, *dir_fi = NULL, ocfi, ncfi; struct buffer_head *dir_bh = NULL; int retval = -ENOENT; kernel_lb_addr tloc; lock_kernel(); if ((ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi))) { if (ofibh.sbh != ofibh.ebh) brelse(ofibh.ebh); brelse(ofibh.sbh); } tloc = lelb_to_cpu(ocfi.icb.extLocation); if (!ofi || udf_get_lb_pblock(old_dir->i_sb, tloc, 0) != old_inode->i_ino) goto end_rename; nfi = udf_find_entry(new_dir, new_dentry, &nfibh, &ncfi); if (nfi) { if (!new_inode) { if (nfibh.sbh != nfibh.ebh) brelse(nfibh.ebh); brelse(nfibh.sbh); nfi = NULL; } } if (S_ISDIR(old_inode->i_mode)) { uint32_t offset = udf_ext0_offset(old_inode); if (new_inode) { retval = -ENOTEMPTY; if (!empty_dir(new_inode)) goto end_rename; } retval = -EIO; if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB) { dir_fi = udf_get_fileident(UDF_I_DATA(old_inode) - (UDF_I_EFE(old_inode) ? sizeof(struct extendedFileEntry) : sizeof(struct fileEntry)), old_inode->i_sb->s_blocksize, &offset); } else { dir_bh = udf_bread(old_inode, 0, 0, &retval); if (!dir_bh) goto end_rename; dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset); } if (!dir_fi) goto end_rename; tloc = lelb_to_cpu(dir_fi->icb.extLocation); if (udf_get_lb_pblock(old_inode->i_sb, tloc, 0) != old_dir->i_ino) goto end_rename; retval = -EMLINK; if (!new_inode && new_dir->i_nlink >= (256 << sizeof(new_dir->i_nlink)) - 1) goto end_rename; } if (!nfi) { nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi, &retval); if (!nfi) goto end_rename; } /* * Like most other Unix systems, set the ctime for inodes on a * rename. */ old_inode->i_ctime = current_fs_time(old_inode->i_sb); mark_inode_dirty(old_inode); /* * ok, that's it */ ncfi.fileVersionNum = ocfi.fileVersionNum; ncfi.fileCharacteristics = ocfi.fileCharacteristics; memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(long_ad)); udf_write_fi(new_dir, &ncfi, nfi, &nfibh, NULL, NULL); /* The old fid may have moved - find it again */ ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi); udf_delete_entry(old_dir, ofi, &ofibh, &ocfi); if (new_inode) { new_inode->i_ctime = current_fs_time(new_inode->i_sb); inode_dec_link_count(new_inode); } old_dir->i_ctime = old_dir->i_mtime = current_fs_time(old_dir->i_sb); mark_inode_dirty(old_dir); if (dir_fi) { dir_fi->icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(new_dir)); udf_update_tag((char *)dir_fi, (sizeof(struct fileIdentDesc) + le16_to_cpu(dir_fi->lengthOfImpUse) + 3) & ~3); if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB) { mark_inode_dirty(old_inode); } else { mark_buffer_dirty_inode(dir_bh, old_inode); } inode_dec_link_count(old_dir); if (new_inode) { inode_dec_link_count(new_inode); } else { inc_nlink(new_dir); mark_inode_dirty(new_dir); } } if (ofi) { if (ofibh.sbh != ofibh.ebh) brelse(ofibh.ebh); brelse(ofibh.sbh); } retval = 0;end_rename: brelse(dir_bh); if (nfi) { if (nfibh.sbh != nfibh.ebh) brelse(nfibh.ebh); brelse(nfibh.sbh); } unlock_kernel(); return retval;}const struct inode_operations udf_dir_inode_operations = { .lookup = udf_lookup, .create = udf_create, .link = udf_link, .unlink = udf_unlink, .symlink = udf_symlink, .mkdir = udf_mkdir, .rmdir = udf_rmdir, .mknod = udf_mknod, .rename = udf_rename,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -