📄 namei.c
字号:
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) { block = UDF_I_LOCATION(dir).logicalBlockNum; fi = (struct fileIdentDesc *)(UDF_I_DATA(dir) + fibh->soffset - udf_ext0_offset(dir) + UDF_I_LENEATTR(dir)); } else { block = eloc.logicalBlockNum + ((elen - 1) >> dir->i_sb->s_blocksize_bits); fi = (struct fileIdentDesc *)(fibh->sbh->b_data + fibh->soffset); } } else { fibh->soffset = fibh->eoffset - sb->s_blocksize; fibh->eoffset += nfidlen - sb->s_blocksize; if (fibh->sbh != fibh->ebh) { udf_release_data(fibh->sbh); fibh->sbh = fibh->ebh; } block = eloc.logicalBlockNum + ((elen - 1) >> dir->i_sb->s_blocksize_bits); if (!(fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err))) { udf_release_data(bh); udf_release_data(fibh->sbh); return NULL; } if (!(fibh->soffset)) { if (udf_next_aext(dir, &bloc, &extoffset, &eloc, &elen, &bh, 1) == (EXT_RECORDED_ALLOCATED >> 30)) { block = eloc.logicalBlockNum + ((elen - 1) >> dir->i_sb->s_blocksize_bits); } else block ++; udf_release_data(fibh->sbh); fibh->sbh = fibh->ebh; fi = (struct fileIdentDesc *)(fibh->sbh->b_data); } else { fi = (struct fileIdentDesc *) (fibh->sbh->b_data + sb->s_blocksize + fibh->soffset); } } memset(cfi, 0, sizeof(struct fileIdentDesc)); if (UDF_SB_UDFREV(sb) >= 0x0200) udf_new_tag((char *)cfi, TAG_IDENT_FID, 3, 1, block, sizeof(tag)); else udf_new_tag((char *)cfi, TAG_IDENT_FID, 2, 1, block, sizeof(tag)); cfi->fileVersionNum = cpu_to_le16(1); cfi->lengthFileIdent = namelen; cfi->lengthOfImpUse = cpu_to_le16(0); if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) { udf_release_data(bh); dir->i_size += nfidlen; if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) UDF_I_LENALLOC(dir) += nfidlen;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14) dir->i_version = ++event;#else dir->i_version = ++global_event;#endif mark_inode_dirty(dir); return fi; } else { udf_release_data(bh); if (fibh->sbh != fibh->ebh) udf_release_data(fibh->ebh); udf_release_data(fibh->sbh); *err = -EIO; return NULL; }}static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi, struct udf_fileident_bh *fibh, struct fileIdentDesc *cfi){ cfi->fileCharacteristics |= FID_FILE_CHAR_DELETED; if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT)) memset(&(cfi->icb), 0x00, sizeof(long_ad)); return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL);}int udf_create(struct inode *dir, struct dentry *dentry, int mode){ struct udf_fileident_bh fibh; struct inode *inode; struct fileIdentDesc cfi, *fi; int err; inode = udf_new_inode(dir, mode, &err); if (!inode) return err; if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB) inode->i_op = &udf_file_inode_operations_adinicb; else inode->i_op = &udf_file_inode_operations; inode->i_mode = mode; mark_inode_dirty(inode); if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) { inode->i_nlink --; mark_inode_dirty(inode); iput(inode); return err; } cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode)); *(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL); udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) { mark_inode_dirty(dir);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14) dir->i_version = ++event;#else dir->i_version = ++global_event;#endif } if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); udf_release_data(fibh.sbh); d_instantiate(dentry, inode); return 0;}int udf_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev){ struct inode * inode; struct udf_fileident_bh fibh; int err; struct fileIdentDesc cfi, *fi;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6) err = -ENAMETOOLONG; if (dentry->d_name.len >= UDF_NAME_LEN) goto out;#endif err = -EIO; inode = udf_new_inode(dir, mode, &err); if (!inode) goto out; inode->i_uid = current->fsuid; inode->i_mode = mode; inode->i_op = NULL; if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) { inode->i_nlink --; mark_inode_dirty(inode); iput(inode); return err; } cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode)); *(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL); udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) { mark_inode_dirty(dir);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14) dir->i_version = ++event;#else dir->i_version = ++global_event;#endif } if (S_ISREG(inode->i_mode)) { if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB) inode->i_op = &udf_file_inode_operations_adinicb; else inode->i_op = &udf_file_inode_operations; } else if (S_ISCHR(inode->i_mode)) { inode->i_op = &chrdev_inode_operations; } else if (S_ISBLK(inode->i_mode)) { inode->i_op = &blkdev_inode_operations; } else if (S_ISFIFO(inode->i_mode)) { init_fifo(inode); } if (S_ISBLK(mode) || S_ISCHR(mode)) inode->i_rdev = to_kdev_t(rdev); mark_inode_dirty(inode); if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); udf_release_data(fibh.sbh); d_instantiate(dentry, inode); err = 0;out: return err;}int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode){ struct inode * inode; struct udf_fileident_bh fibh; int err; struct fileIdentDesc cfi, *fi;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6) err = -ENAMETOOLONG; if (dentry->d_name.len >= UDF_NAME_LEN) goto out;#endif err = -EMLINK; if (dir->i_nlink >= (256<<sizeof(dir->i_nlink))-1) goto out; err = -EIO; inode = udf_new_inode(dir, S_IFDIR, &err); if (!inode) goto out; inode->i_op = &udf_dir_inode_operations; if (!(fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err))) { inode->i_nlink--; mark_inode_dirty(inode); iput(inode); goto out; } inode->i_nlink = 2; cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(dir)); *(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = cpu_to_le32(UDF_I_UNIQUE(dir) & 0x00000000FFFFFFFFUL); cfi.fileCharacteristics = FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT; udf_write_fi(inode, &cfi, fi, &fibh, NULL, NULL); udf_release_data(fibh.sbh); inode->i_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask); if (dir->i_mode & S_ISGID) inode->i_mode |= S_ISGID; mark_inode_dirty(inode); if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) { inode->i_nlink = 0; mark_inode_dirty(inode); iput(inode); goto out; } cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode)); *(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL); cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY; udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14) dir->i_version = ++event;#else dir->i_version = ++global_event;#endif dir->i_nlink++; mark_inode_dirty(dir); d_instantiate(dentry, inode); if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); udf_release_data(fibh.sbh); err = 0;out: return err;}static int empty_dir(struct inode *dir){ struct fileIdentDesc *fi, cfi; struct udf_fileident_bh fibh; loff_t f_pos; int size = (udf_ext0_offset(dir) + dir->i_size) >> 2; int block; lb_addr bloc, eloc; uint32_t extoffset, elen, offset; struct buffer_head *bh = NULL; f_pos = (udf_ext0_offset(dir) >> 2); fibh.soffset = fibh.eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2; if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) fibh.sbh = fibh.ebh = NULL; else if (inode_bmap(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30)) { offset >>= dir->i_sb->s_blocksize_bits; block = udf_get_lb_pblock(dir->i_sb, eloc, offset); if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT) extoffset -= sizeof(short_ad); else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG) extoffset -= sizeof(long_ad); } else offset = 0; if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) { udf_release_data(bh); return 0; } } else { udf_release_data(bh); return 0; } while ( (f_pos < size) ) { fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh); if (!fi) { if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); udf_release_data(fibh.sbh); udf_release_data(bh); return 0; } if (cfi.lengthFileIdent && (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0) { if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); udf_release_data(fibh.sbh); udf_release_data(bh); return 0; } } if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); udf_release_data(fibh.sbh); udf_release_data(bh); return 1;}int udf_rmdir(struct inode * dir, struct dentry * dentry){ int retval; struct inode * inode = dentry->d_inode; struct udf_fileident_bh fibh; struct fileIdentDesc *fi, cfi;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6) retval = -ENAMETOOLONG; if (dentry->d_name.len >= UDF_NAME_LEN) goto out;#endif retval = -ENOENT; fi = udf_find_entry(dir, dentry, &fibh, &cfi); if (!fi) goto out; DQUOT_INIT(inode); retval = -EIO; if (udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0) != inode->i_ino) goto end_rmdir;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6) if (!empty_dir(inode)) retval = -ENOTEMPTY; else if (udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0) != inode->i_ino) { retval = -ENOENT; } else { retval = udf_delete_entry(dir, fi, &fibh, &cfi); dir->i_version = ++event; }#else retval = -ENOTEMPTY; if (!empty_dir(inode)) goto end_rmdir; retval = udf_delete_entry(dir, fi, &fibh, &cfi);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14) dir->i_version = ++event;#else dir->i_version = ++global_event;#endif#endif if (retval) goto end_rmdir; if (inode->i_nlink != 2) udf_warning(inode->i_sb, "udf_rmdir", "empty directory has nlink != 2 (%d)", inode->i_nlink);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,14) inode->i_version = ++event;#else inode->i_version = ++global_event;#endif inode->i_nlink = 0; inode->i_size = 0; mark_inode_dirty(inode); dir->i_nlink --; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; UDF_I_UCTIME(inode) = UDF_I_UCTIME(dir) = UDF_I_UMTIME(dir) = CURRENT_UTIME; mark_inode_dirty(dir); d_delete(dentry);end_rmdir: if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); udf_release_data(fibh.sbh);out: return retval;}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;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,6) retval = -ENAMETOOLONG; if (dentry->d_name.len >= UDF_NAME_LEN) goto out;#endif retval = -ENOENT; fi = udf_find_entry(dir, dentry, &fibh, &cfi); if (!fi) goto out; DQUOT_INIT(inode); retval = -EIO; if (udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 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_TIME; UDF_I_UCTIME(dir) = UDF_I_UMTIME(dir) = CURRENT_UTIME; mark_inode_dirty(dir); inode->i_nlink--; mark_inode_dirty(inode); inode->i_ctime = dir->i_ctime; retval = 0; d_delete(dentry); /* This also frees the inode */end_unlink: if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); udf_release_data(fibh.sbh);out: return retval;}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 buffer_head *bh = NULL; int eoffset, elen = 0; struct fileIdentDesc *fi; struct fileIdentDesc cfi; char *ea; int err; int block; char name[UDF_NAME_LEN]; int namelen; if (!(inode = udf_new_inode(dir, S_IFLNK, &err))) goto out; inode->i_mode = S_IFLNK | S_IRWXUGO; inode->i_op = &udf_symlink_inode_operations; if (UDF_I_ALLOCTYPE(inode) != ICBTAG_FLAG_AD_IN_ICB) { struct buffer_head *bh = NULL; lb_addr bloc, eloc; uint32_t elen, extoffset; 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; bloc = UDF_I_LOCATION(inode); eloc.logicalBlockNum = block; eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum; elen = inode->i_sb->s_blocksize; UDF_I_LENEXTENTS(inode) = elen; extoffset = udf_file_entry_alloc_offset(inode); udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 0); udf_release_data(bh); inode->i_blocks = inode->i_sb->s_blocksize / 512; block = udf_get_pblock(inode->i_sb, block, UDF_I_LOCATION(inode).partitionReferenceNum, 0); bh = udf_tread(inode->i_sb, block); ea = 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 == '/')
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -