1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * fs/bfs/dir.c 4 * BFS directory operations. 5 * Copyright (C) 1999-2018 Tigran Aivazian <aivazian.tigran@gmail.com> 6 * Made endianness-clean by Andrew Stribblehill <ads@wompom.org> 2005 7 */ 8 9 #include <linux/time.h> 10 #include <linux/string.h> 11 #include <linux/fs.h> 12 #include <linux/buffer_head.h> 13 #include <linux/sched.h> 14 #include "bfs.h" 15 16 #undef DEBUG 17 18 #ifdef DEBUG 19 #define dprintf(x...) printf(x) 20 #else 21 #define dprintf(x...) 22 #endif 23 24 static int bfs_add_entry(struct inode *dir, const struct qstr *child, int ino); 25 static struct buffer_head *bfs_find_entry(struct inode *dir, 26 const struct qstr *child, 27 struct bfs_dirent **res_dir); 28 29 static int bfs_readdir(struct file *f, struct dir_context *ctx) 30 { 31 struct inode *dir = file_inode(f); 32 struct buffer_head *bh; 33 struct bfs_dirent *de; 34 unsigned int offset; 35 int block; 36 37 if (ctx->pos & (BFS_DIRENT_SIZE - 1)) { 38 printf("Bad f_pos=%08lx for %s:%08lx\n", 39 (unsigned long)ctx->pos, 40 dir->i_sb->s_id, dir->i_ino); 41 return -EINVAL; 42 } 43 44 while (ctx->pos < dir->i_size) { 45 offset = ctx->pos & (BFS_BSIZE - 1); 46 block = BFS_I(dir)->i_sblock + (ctx->pos >> BFS_BSIZE_BITS); 47 bh = sb_bread(dir->i_sb, block); 48 if (!bh) { 49 ctx->pos += BFS_BSIZE - offset; 50 continue; 51 } 52 do { 53 de = (struct bfs_dirent *)(bh->b_data + offset); 54 if (de->ino) { 55 int size = strnlen(de->name, BFS_NAMELEN); 56 if (!dir_emit(ctx, de->name, size, 57 le16_to_cpu(de->ino), 58 DT_UNKNOWN)) { 59 brelse(bh); 60 return 0; 61 } 62 } 63 offset += BFS_DIRENT_SIZE; 64 ctx->pos += BFS_DIRENT_SIZE; 65 } while ((offset < BFS_BSIZE) && (ctx->pos < dir->i_size)); 66 brelse(bh); 67 } 68 return 0; 69 } 70 71 const struct file_operations bfs_dir_operations = { 72 .read = generic_read_dir, 73 .iterate_shared = bfs_readdir, 74 .fsync = generic_file_fsync, 75 .llseek = generic_file_llseek, 76 }; 77 78 static int bfs_create(struct mnt_idmap *idmap, struct inode *dir, 79 struct dentry *dentry, umode_t mode, bool excl) 80 { 81 int err; 82 struct inode *inode; 83 struct super_block *s = dir->i_sb; 84 struct bfs_sb_info *info = BFS_SB(s); 85 unsigned long ino; 86 87 inode = new_inode(s); 88 if (!inode) 89 return -ENOMEM; 90 mutex_lock(&info->bfs_lock); 91 ino = find_first_zero_bit(info->si_imap, info->si_lasti + 1); 92 if (ino > info->si_lasti) { 93 mutex_unlock(&info->bfs_lock); 94 iput(inode); 95 return -ENOSPC; 96 } 97 set_bit(ino, info->si_imap); 98 info->si_freei--; 99 inode_init_owner(&nop_mnt_idmap, inode, dir, mode); 100 simple_inode_init_ts(inode); 101 inode->i_blocks = 0; 102 inode->i_op = &bfs_file_inops; 103 inode->i_fop = &bfs_file_operations; 104 inode->i_mapping->a_ops = &bfs_aops; 105 inode->i_ino = ino; 106 BFS_I(inode)->i_dsk_ino = ino; 107 BFS_I(inode)->i_sblock = 0; 108 BFS_I(inode)->i_eblock = 0; 109 insert_inode_hash(inode); 110 mark_inode_dirty(inode); 111 bfs_dump_imap("create", s); 112 113 err = bfs_add_entry(dir, &dentry->d_name, inode->i_ino); 114 if (err) { 115 inode_dec_link_count(inode); 116 mutex_unlock(&info->bfs_lock); 117 iput(inode); 118 return err; 119 } 120 mutex_unlock(&info->bfs_lock); 121 d_instantiate(dentry, inode); 122 return 0; 123 } 124 125 static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry, 126 unsigned int flags) 127 { 128 struct inode *inode = NULL; 129 struct buffer_head *bh; 130 struct bfs_dirent *de; 131 struct bfs_sb_info *info = BFS_SB(dir->i_sb); 132 133 if (dentry->d_name.len > BFS_NAMELEN) 134 return ERR_PTR(-ENAMETOOLONG); 135 136 mutex_lock(&info->bfs_lock); 137 bh = bfs_find_entry(dir, &dentry->d_name, &de); 138 if (bh) { 139 unsigned long ino = (unsigned long)le16_to_cpu(de->ino); 140 brelse(bh); 141 inode = bfs_iget(dir->i_sb, ino); 142 } 143 mutex_unlock(&info->bfs_lock); 144 return d_splice_alias(inode, dentry); 145 } 146 147 static int bfs_link(struct dentry *old, struct inode *dir, 148 struct dentry *new) 149 { 150 struct inode *inode = d_inode(old); 151 struct bfs_sb_info *info = BFS_SB(inode->i_sb); 152 int err; 153 154 mutex_lock(&info->bfs_lock); 155 err = bfs_add_entry(dir, &new->d_name, inode->i_ino); 156 if (err) { 157 mutex_unlock(&info->bfs_lock); 158 return err; 159 } 160 inc_nlink(inode); 161 inode_set_ctime_current(inode); 162 mark_inode_dirty(inode); 163 ihold(inode); 164 d_instantiate(new, inode); 165 mutex_unlock(&info->bfs_lock); 166 return 0; 167 } 168 169 static int bfs_unlink(struct inode *dir, struct dentry *dentry) 170 { 171 int error = -ENOENT; 172 struct inode *inode = d_inode(dentry); 173 struct buffer_head *bh; 174 struct bfs_dirent *de; 175 struct bfs_sb_info *info = BFS_SB(inode->i_sb); 176 177 mutex_lock(&info->bfs_lock); 178 bh = bfs_find_entry(dir, &dentry->d_name, &de); 179 if (!bh || (le16_to_cpu(de->ino) != inode->i_ino)) 180 goto out_brelse; 181 182 if (!inode->i_nlink) { 183 printf("unlinking non-existent file %s:%lu (nlink=%d)\n", 184 inode->i_sb->s_id, inode->i_ino, 185 inode->i_nlink); 186 set_nlink(inode, 1); 187 } 188 de->ino = 0; 189 mark_buffer_dirty_inode(bh, dir); 190 inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); 191 mark_inode_dirty(dir); 192 inode_set_ctime_to_ts(inode, inode_get_ctime(dir)); 193 inode_dec_link_count(inode); 194 error = 0; 195 196 out_brelse: 197 brelse(bh); 198 mutex_unlock(&info->bfs_lock); 199 return error; 200 } 201 202 static int bfs_rename(struct mnt_idmap *idmap, struct inode *old_dir, 203 struct dentry *old_dentry, struct inode *new_dir, 204 struct dentry *new_dentry, unsigned int flags) 205 { 206 struct inode *old_inode, *new_inode; 207 struct buffer_head *old_bh, *new_bh; 208 struct bfs_dirent *old_de, *new_de; 209 struct bfs_sb_info *info; 210 int error = -ENOENT; 211 212 if (flags & ~RENAME_NOREPLACE) 213 return -EINVAL; 214 215 old_bh = new_bh = NULL; 216 old_inode = d_inode(old_dentry); 217 if (S_ISDIR(old_inode->i_mode)) 218 return -EINVAL; 219 220 info = BFS_SB(old_inode->i_sb); 221 222 mutex_lock(&info->bfs_lock); 223 old_bh = bfs_find_entry(old_dir, &old_dentry->d_name, &old_de); 224 225 if (!old_bh || (le16_to_cpu(old_de->ino) != old_inode->i_ino)) 226 goto end_rename; 227 228 error = -EPERM; 229 new_inode = d_inode(new_dentry); 230 new_bh = bfs_find_entry(new_dir, &new_dentry->d_name, &new_de); 231 232 if (new_bh && !new_inode) { 233 brelse(new_bh); 234 new_bh = NULL; 235 } 236 if (!new_bh) { 237 error = bfs_add_entry(new_dir, &new_dentry->d_name, 238 old_inode->i_ino); 239 if (error) 240 goto end_rename; 241 } 242 old_de->ino = 0; 243 inode_set_mtime_to_ts(old_dir, inode_set_ctime_current(old_dir)); 244 mark_inode_dirty(old_dir); 245 if (new_inode) { 246 inode_set_ctime_current(new_inode); 247 inode_dec_link_count(new_inode); 248 } 249 mark_buffer_dirty_inode(old_bh, old_dir); 250 error = 0; 251 252 end_rename: 253 mutex_unlock(&info->bfs_lock); 254 brelse(old_bh); 255 brelse(new_bh); 256 return error; 257 } 258 259 const struct inode_operations bfs_dir_inops = { 260 .create = bfs_create, 261 .lookup = bfs_lookup, 262 .link = bfs_link, 263 .unlink = bfs_unlink, 264 .rename = bfs_rename, 265 }; 266 267 static int bfs_add_entry(struct inode *dir, const struct qstr *child, int ino) 268 { 269 const unsigned char *name = child->name; 270 int namelen = child->len; 271 struct buffer_head *bh; 272 struct bfs_dirent *de; 273 int block, sblock, eblock, off, pos; 274 int i; 275 276 dprintf("name=%s, namelen=%d\n", name, namelen); 277 278 if (!namelen) 279 return -ENOENT; 280 if (namelen > BFS_NAMELEN) 281 return -ENAMETOOLONG; 282 283 sblock = BFS_I(dir)->i_sblock; 284 eblock = BFS_I(dir)->i_eblock; 285 for (block = sblock; block <= eblock; block++) { 286 bh = sb_bread(dir->i_sb, block); 287 if (!bh) 288 return -EIO; 289 for (off = 0; off < BFS_BSIZE; off += BFS_DIRENT_SIZE) { 290 de = (struct bfs_dirent *)(bh->b_data + off); 291 if (!de->ino) { 292 pos = (block - sblock) * BFS_BSIZE + off; 293 if (pos >= dir->i_size) { 294 dir->i_size += BFS_DIRENT_SIZE; 295 inode_set_ctime_current(dir); 296 } 297 inode_set_mtime_to_ts(dir, 298 inode_set_ctime_current(dir)); 299 mark_inode_dirty(dir); 300 de->ino = cpu_to_le16((u16)ino); 301 for (i = 0; i < BFS_NAMELEN; i++) 302 de->name[i] = 303 (i < namelen) ? name[i] : 0; 304 mark_buffer_dirty_inode(bh, dir); 305 brelse(bh); 306 return 0; 307 } 308 } 309 brelse(bh); 310 } 311 return -ENOSPC; 312 } 313 314 static inline int bfs_namecmp(int len, const unsigned char *name, 315 const char *buffer) 316 { 317 if ((len < BFS_NAMELEN) && buffer[len]) 318 return 0; 319 return !memcmp(name, buffer, len); 320 } 321 322 static struct buffer_head *bfs_find_entry(struct inode *dir, 323 const struct qstr *child, 324 struct bfs_dirent **res_dir) 325 { 326 unsigned long block = 0, offset = 0; 327 struct buffer_head *bh = NULL; 328 struct bfs_dirent *de; 329 const unsigned char *name = child->name; 330 int namelen = child->len; 331 332 *res_dir = NULL; 333 if (namelen > BFS_NAMELEN) 334 return NULL; 335 336 while (block * BFS_BSIZE + offset < dir->i_size) { 337 if (!bh) { 338 bh = sb_bread(dir->i_sb, BFS_I(dir)->i_sblock + block); 339 if (!bh) { 340 block++; 341 continue; 342 } 343 } 344 de = (struct bfs_dirent *)(bh->b_data + offset); 345 offset += BFS_DIRENT_SIZE; 346 if (le16_to_cpu(de->ino) && 347 bfs_namecmp(namelen, name, de->name)) { 348 *res_dir = de; 349 return bh; 350 } 351 if (offset < bh->b_size) 352 continue; 353 brelse(bh); 354 bh = NULL; 355 offset = 0; 356 block++; 357 } 358 brelse(bh); 359 return NULL; 360 } 361