📄 dir.c
字号:
rlen, ufs_get_de_namlen(sb, de)); return (error_msg == NULL ? 1 : 0);}struct ufs_dir_entry *ufs_dotdot(struct inode *dir, struct buffer_head **p){ int err; struct buffer_head *bh = ufs_bread (dir, 0, 0, &err); struct ufs_dir_entry *res = NULL; if (bh) { res = (struct ufs_dir_entry *) bh->b_data; res = (struct ufs_dir_entry *)((char *)res + fs16_to_cpu(dir->i_sb, res->d_reclen)); } *p = bh; return res;}ino_t ufs_inode_by_name(struct inode * dir, struct dentry *dentry){ ino_t res = 0; struct ufs_dir_entry * de; struct buffer_head *bh; de = ufs_find_entry (dentry, &bh); if (de) { res = fs32_to_cpu(dir->i_sb, de->d_ino); brelse(bh); } return res;}void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, struct buffer_head *bh, struct inode *inode){ dir->i_version = ++event; de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino); mark_buffer_dirty(bh); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer(bh); } brelse (bh);}/* * ufs_add_entry() * * adds a file entry to the specified directory, using the same * semantics as ufs_find_entry(). It returns NULL if it failed. */int ufs_add_link(struct dentry *dentry, struct inode *inode){ struct super_block * sb; struct ufs_sb_private_info * uspi; unsigned long offset; unsigned fragoff; unsigned short rec_len; struct buffer_head * bh; struct ufs_dir_entry * de, * de1; struct inode *dir = dentry->d_parent->d_inode; const char *name = dentry->d_name.name; int namelen = dentry->d_name.len; int err; UFSD(("ENTER, name %s, namelen %u\n", name, namelen)) sb = dir->i_sb; uspi = sb->u.ufs_sb.s_uspi; if (!namelen) return -EINVAL; bh = ufs_bread (dir, 0, 0, &err); if (!bh) return err; rec_len = UFS_DIR_REC_LEN(namelen); offset = 0; de = (struct ufs_dir_entry *) bh->b_data; while (1) { if ((char *)de >= UFS_SECTOR_SIZE + bh->b_data) { fragoff = offset & ~uspi->s_fmask; if (fragoff != 0 && fragoff != UFS_SECTOR_SIZE) ufs_error (sb, "ufs_add_entry", "internal error" " fragoff %u", fragoff); if (!fragoff) { brelse (bh); bh = ufs_bread (dir, offset >> sb->s_blocksize_bits, 1, &err); if (!bh) return err; } if (dir->i_size <= offset) { if (dir->i_size == 0) { brelse(bh); return -ENOENT; } de = (struct ufs_dir_entry *) (bh->b_data + fragoff); de->d_ino = 0; de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE); ufs_set_de_namlen(sb, de, 0); dir->i_size = offset + UFS_SECTOR_SIZE; mark_inode_dirty(dir); } else { de = (struct ufs_dir_entry *) bh->b_data; } } if (!ufs_check_dir_entry ("ufs_add_entry", dir, de, bh, offset)) { brelse (bh); return -ENOENT; } if (ufs_match(sb, namelen, name, de)) { brelse (bh); return -EEXIST; } if (de->d_ino == 0 && fs16_to_cpu(sb, de->d_reclen) >= rec_len) break; if (fs16_to_cpu(sb, de->d_reclen) >= UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)) + rec_len) break; offset += fs16_to_cpu(sb, de->d_reclen); de = (struct ufs_dir_entry *) ((char *) de + fs16_to_cpu(sb, de->d_reclen)); } if (de->d_ino) { de1 = (struct ufs_dir_entry *) ((char *) de + UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de))); de1->d_reclen = cpu_to_fs16(sb, fs16_to_cpu(sb, de->d_reclen) - UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de))); de->d_reclen = cpu_to_fs16(sb, UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de))); de = de1; } de->d_ino = 0; ufs_set_de_namlen(sb, de, namelen); memcpy (de->d_name, name, namelen + 1); de->d_ino = cpu_to_fs32(sb, inode->i_ino); ufs_set_de_type(sb, de, inode->i_mode); mark_buffer_dirty(bh); if (IS_SYNC(dir)) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); } brelse (bh); dir->i_mtime = dir->i_ctime = CURRENT_TIME; dir->i_version = ++event; mark_inode_dirty(dir); UFSD(("EXIT\n")) return 0;}/* * ufs_delete_entry deletes a directory entry by merging it with the * previous entry. */int ufs_delete_entry (struct inode * inode, struct ufs_dir_entry * dir, struct buffer_head * bh ) { struct super_block * sb; struct ufs_dir_entry * de, * pde; unsigned i; UFSD(("ENTER\n")) sb = inode->i_sb; i = 0; pde = NULL; de = (struct ufs_dir_entry *) bh->b_data; UFSD(("ino %u, reclen %u, namlen %u, name %s\n", fs32_to_cpu(sb, de->d_ino), fs16to_cpu(sb, de->d_reclen), ufs_get_de_namlen(sb, de), de->d_name)) while (i < bh->b_size) { if (!ufs_check_dir_entry ("ufs_delete_entry", inode, de, bh, i)) { brelse(bh); return -EIO; } if (de == dir) { if (pde) fs16_add(sb, &pde->d_reclen, fs16_to_cpu(sb, dir->d_reclen)); dir->d_ino = 0; inode->i_version = ++event; inode->i_ctime = inode->i_mtime = CURRENT_TIME; mark_inode_dirty(inode); mark_buffer_dirty(bh); if (IS_SYNC(inode)) { ll_rw_block(WRITE, 1, &bh); wait_on_buffer(bh); } brelse(bh); UFSD(("EXIT\n")) return 0; } i += fs16_to_cpu(sb, de->d_reclen); if (i == UFS_SECTOR_SIZE) pde = NULL; else pde = de; de = (struct ufs_dir_entry *) ((char *) de + fs16_to_cpu(sb, de->d_reclen)); if (i == UFS_SECTOR_SIZE && de->d_reclen == 0) break; } UFSD(("EXIT\n")) brelse(bh); return -ENOENT;}int ufs_make_empty(struct inode * inode, struct inode *dir){ struct super_block * sb = dir->i_sb; struct buffer_head * dir_block; struct ufs_dir_entry * de; int err; dir_block = ufs_bread (inode, 0, 1, &err); if (!dir_block) return err; inode->i_blocks = sb->s_blocksize / UFS_SECTOR_SIZE; de = (struct ufs_dir_entry *) dir_block->b_data; de->d_ino = cpu_to_fs32(sb, inode->i_ino); ufs_set_de_type(sb, de, inode->i_mode); ufs_set_de_namlen(sb, de, 1); de->d_reclen = cpu_to_fs16(sb, UFS_DIR_REC_LEN(1)); strcpy (de->d_name, "."); de = (struct ufs_dir_entry *) ((char *)de + fs16_to_cpu(sb, de->d_reclen)); de->d_ino = cpu_to_fs32(sb, dir->i_ino); ufs_set_de_type(sb, de, dir->i_mode); de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1)); ufs_set_de_namlen(sb, de, 2); strcpy (de->d_name, ".."); mark_buffer_dirty(dir_block); brelse (dir_block); mark_inode_dirty(inode); return 0;}/* * routine to check that the specified directory is empty (for rmdir) */int ufs_empty_dir (struct inode * inode){ struct super_block * sb; unsigned long offset; struct buffer_head * bh; struct ufs_dir_entry * de, * de1; int err; sb = inode->i_sb; if (inode->i_size < UFS_DIR_REC_LEN(1) + UFS_DIR_REC_LEN(2) || !(bh = ufs_bread (inode, 0, 0, &err))) { ufs_warning (inode->i_sb, "empty_dir", "bad directory (dir #%lu) - no data block", inode->i_ino); return 1; } de = (struct ufs_dir_entry *) bh->b_data; de1 = (struct ufs_dir_entry *) ((char *)de + fs16_to_cpu(sb, de->d_reclen)); if (fs32_to_cpu(sb, de->d_ino) != inode->i_ino || de1->d_ino == 0 || strcmp (".", de->d_name) || strcmp ("..", de1->d_name)) { ufs_warning (inode->i_sb, "empty_dir", "bad directory (dir #%lu) - no `.' or `..'", inode->i_ino); return 1; } offset = fs16_to_cpu(sb, de->d_reclen) + fs16_to_cpu(sb, de1->d_reclen); de = (struct ufs_dir_entry *) ((char *)de1 + fs16_to_cpu(sb, de1->d_reclen)); while (offset < inode->i_size ) { if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) { brelse (bh); bh = ufs_bread (inode, offset >> sb->s_blocksize_bits, 1, &err); if (!bh) { ufs_error (sb, "empty_dir", "directory #%lu contains a hole at offset %lu", inode->i_ino, offset); offset += sb->s_blocksize; continue; } de = (struct ufs_dir_entry *) bh->b_data; } if (!ufs_check_dir_entry ("empty_dir", inode, de, bh, offset)) { brelse (bh); return 1; } if (de->d_ino) { brelse (bh); return 0; } offset += fs16_to_cpu(sb, de->d_reclen); de = (struct ufs_dir_entry *) ((char *)de + fs16_to_cpu(sb, de->d_reclen)); } brelse (bh); return 1;}struct file_operations ufs_dir_operations = { read: generic_read_dir, readdir: ufs_readdir, fsync: file_fsync,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -