1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * linux/fs/affs/namei.c 4 * 5 * (c) 1996 Hans-Joachim Widmaier - Rewritten 6 * 7 * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem. 8 * 9 * (C) 1991 Linus Torvalds - minix filesystem 10 */ 11 12 #include "affs.h" 13 #include <linux/exportfs.h> 14 15 typedef int (*toupper_t)(int); 16 17 /* Simple toupper() for DOS\1 */ 18 19 static int 20 affs_toupper(int ch) 21 { 22 return ch >= 'a' && ch <= 'z' ? ch -= ('a' - 'A') : ch; 23 } 24 25 /* International toupper() for DOS\3 ("international") */ 26 27 static int 28 affs_intl_toupper(int ch) 29 { 30 return (ch >= 'a' && ch <= 'z') || (ch >= 0xE0 31 && ch <= 0xFE && ch != 0xF7) ? 32 ch - ('a' - 'A') : ch; 33 } 34 35 static inline toupper_t 36 affs_get_toupper(struct super_block *sb) 37 { 38 return affs_test_opt(AFFS_SB(sb)->s_flags, SF_INTL) ? 39 affs_intl_toupper : affs_toupper; 40 } 41 42 /* 43 * Note: the dentry argument is the parent dentry. 44 */ 45 static inline int 46 __affs_hash_dentry(const struct dentry *dentry, struct qstr *qstr, toupper_t toupper, bool notruncate) 47 { 48 const u8 *name = qstr->name; 49 unsigned long hash; 50 int retval; 51 u32 len; 52 53 retval = affs_check_name(qstr->name, qstr->len, notruncate); 54 if (retval) 55 return retval; 56 57 hash = init_name_hash(dentry); 58 len = min(qstr->len, AFFSNAMEMAX); 59 for (; len > 0; name++, len--) 60 hash = partial_name_hash(toupper(*name), hash); 61 qstr->hash = end_name_hash(hash); 62 63 return 0; 64 } 65 66 static int 67 affs_hash_dentry(const struct dentry *dentry, struct qstr *qstr) 68 { 69 return __affs_hash_dentry(dentry, qstr, affs_toupper, 70 affs_nofilenametruncate(dentry)); 71 72 } 73 74 static int 75 affs_intl_hash_dentry(const struct dentry *dentry, struct qstr *qstr) 76 { 77 return __affs_hash_dentry(dentry, qstr, affs_intl_toupper, 78 affs_nofilenametruncate(dentry)); 79 80 } 81 82 static inline int __affs_compare_dentry(unsigned int len, 83 const char *str, const struct qstr *name, toupper_t toupper, 84 bool notruncate) 85 { 86 const u8 *aname = str; 87 const u8 *bname = name->name; 88 89 /* 90 * 'str' is the name of an already existing dentry, so the name 91 * must be valid. 'name' must be validated first. 92 */ 93 94 if (affs_check_name(name->name, name->len, notruncate)) 95 return 1; 96 97 /* 98 * If the names are longer than the allowed 30 chars, 99 * the excess is ignored, so their length may differ. 100 */ 101 if (len >= AFFSNAMEMAX) { 102 if (name->len < AFFSNAMEMAX) 103 return 1; 104 len = AFFSNAMEMAX; 105 } else if (len != name->len) 106 return 1; 107 108 for (; len > 0; len--) 109 if (toupper(*aname++) != toupper(*bname++)) 110 return 1; 111 112 return 0; 113 } 114 115 static int 116 affs_compare_dentry(const struct dentry *dentry, 117 unsigned int len, const char *str, const struct qstr *name) 118 { 119 120 return __affs_compare_dentry(len, str, name, affs_toupper, 121 affs_nofilenametruncate(dentry)); 122 } 123 124 static int 125 affs_intl_compare_dentry(const struct dentry *dentry, 126 unsigned int len, const char *str, const struct qstr *name) 127 { 128 return __affs_compare_dentry(len, str, name, affs_intl_toupper, 129 affs_nofilenametruncate(dentry)); 130 131 } 132 133 /* 134 * NOTE! unlike strncmp, affs_match returns 1 for success, 0 for failure. 135 */ 136 137 static inline int 138 affs_match(struct dentry *dentry, const u8 *name2, toupper_t toupper) 139 { 140 const u8 *name = dentry->d_name.name; 141 int len = dentry->d_name.len; 142 143 if (len >= AFFSNAMEMAX) { 144 if (*name2 < AFFSNAMEMAX) 145 return 0; 146 len = AFFSNAMEMAX; 147 } else if (len != *name2) 148 return 0; 149 150 for (name2++; len > 0; len--) 151 if (toupper(*name++) != toupper(*name2++)) 152 return 0; 153 return 1; 154 } 155 156 int 157 affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len) 158 { 159 toupper_t toupper = affs_get_toupper(sb); 160 u32 hash; 161 162 hash = len = min(len, AFFSNAMEMAX); 163 for (; len > 0; len--) 164 hash = (hash * 13 + toupper(*name++)) & 0x7ff; 165 166 return hash % AFFS_SB(sb)->s_hashsize; 167 } 168 169 static struct buffer_head * 170 affs_find_entry(struct inode *dir, struct dentry *dentry) 171 { 172 struct super_block *sb = dir->i_sb; 173 struct buffer_head *bh; 174 toupper_t toupper = affs_get_toupper(sb); 175 u32 key; 176 177 pr_debug("%s(\"%pd\")\n", __func__, dentry); 178 179 bh = affs_bread(sb, dir->i_ino); 180 if (!bh) 181 return ERR_PTR(-EIO); 182 183 key = be32_to_cpu(AFFS_HEAD(bh)->table[affs_hash_name(sb, dentry->d_name.name, dentry->d_name.len)]); 184 185 for (;;) { 186 affs_brelse(bh); 187 if (key == 0) 188 return NULL; 189 bh = affs_bread(sb, key); 190 if (!bh) 191 return ERR_PTR(-EIO); 192 if (affs_match(dentry, AFFS_TAIL(sb, bh)->name, toupper)) 193 return bh; 194 key = be32_to_cpu(AFFS_TAIL(sb, bh)->hash_chain); 195 } 196 } 197 198 struct dentry * 199 affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) 200 { 201 struct super_block *sb = dir->i_sb; 202 struct buffer_head *bh; 203 struct inode *inode = NULL; 204 205 pr_debug("%s(\"%pd\")\n", __func__, dentry); 206 207 affs_lock_dir(dir); 208 bh = affs_find_entry(dir, dentry); 209 affs_unlock_dir(dir); 210 if (IS_ERR(bh)) 211 return ERR_CAST(bh); 212 if (bh) { 213 u32 ino = bh->b_blocknr; 214 215 /* store the real header ino in d_fsdata for faster lookups */ 216 dentry->d_fsdata = (void *)(long)ino; 217 switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) { 218 //link to dirs disabled 219 //case ST_LINKDIR: 220 case ST_LINKFILE: 221 ino = be32_to_cpu(AFFS_TAIL(sb, bh)->original); 222 } 223 affs_brelse(bh); 224 inode = affs_iget(sb, ino); 225 if (IS_ERR(inode)) 226 return ERR_CAST(inode); 227 } 228 d_add(dentry, inode); 229 return NULL; 230 } 231 232 int 233 affs_unlink(struct inode *dir, struct dentry *dentry) 234 { 235 pr_debug("%s(dir=%lu, %lu \"%pd\")\n", __func__, dir->i_ino, 236 d_inode(dentry)->i_ino, dentry); 237 238 return affs_remove_header(dentry); 239 } 240 241 int 242 affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) 243 { 244 struct super_block *sb = dir->i_sb; 245 struct inode *inode; 246 int error; 247 248 pr_debug("%s(%lu,\"%pd\",0%ho)\n", 249 __func__, dir->i_ino, dentry, mode); 250 251 inode = affs_new_inode(dir); 252 if (!inode) 253 return -ENOSPC; 254 255 inode->i_mode = mode; 256 affs_mode_to_prot(inode); 257 mark_inode_dirty(inode); 258 259 inode->i_op = &affs_file_inode_operations; 260 inode->i_fop = &affs_file_operations; 261 inode->i_mapping->a_ops = affs_test_opt(AFFS_SB(sb)->s_flags, SF_OFS) ? 262 &affs_aops_ofs : &affs_aops; 263 error = affs_add_entry(dir, inode, dentry, ST_FILE); 264 if (error) { 265 clear_nlink(inode); 266 iput(inode); 267 return error; 268 } 269 return 0; 270 } 271 272 int 273 affs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 274 { 275 struct inode *inode; 276 int error; 277 278 pr_debug("%s(%lu,\"%pd\",0%ho)\n", 279 __func__, dir->i_ino, dentry, mode); 280 281 inode = affs_new_inode(dir); 282 if (!inode) 283 return -ENOSPC; 284 285 inode->i_mode = S_IFDIR | mode; 286 affs_mode_to_prot(inode); 287 288 inode->i_op = &affs_dir_inode_operations; 289 inode->i_fop = &affs_dir_operations; 290 291 error = affs_add_entry(dir, inode, dentry, ST_USERDIR); 292 if (error) { 293 clear_nlink(inode); 294 mark_inode_dirty(inode); 295 iput(inode); 296 return error; 297 } 298 return 0; 299 } 300 301 int 302 affs_rmdir(struct inode *dir, struct dentry *dentry) 303 { 304 pr_debug("%s(dir=%lu, %lu \"%pd\")\n", __func__, dir->i_ino, 305 d_inode(dentry)->i_ino, dentry); 306 307 return affs_remove_header(dentry); 308 } 309 310 int 311 affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) 312 { 313 struct super_block *sb = dir->i_sb; 314 struct buffer_head *bh; 315 struct inode *inode; 316 char *p; 317 int i, maxlen, error; 318 char c, lc; 319 320 pr_debug("%s(%lu,\"%pd\" -> \"%s\")\n", 321 __func__, dir->i_ino, dentry, symname); 322 323 maxlen = AFFS_SB(sb)->s_hashsize * sizeof(u32) - 1; 324 inode = affs_new_inode(dir); 325 if (!inode) 326 return -ENOSPC; 327 328 inode->i_op = &affs_symlink_inode_operations; 329 inode_nohighmem(inode); 330 inode->i_data.a_ops = &affs_symlink_aops; 331 inode->i_mode = S_IFLNK | 0777; 332 affs_mode_to_prot(inode); 333 334 error = -EIO; 335 bh = affs_bread(sb, inode->i_ino); 336 if (!bh) 337 goto err; 338 i = 0; 339 p = (char *)AFFS_HEAD(bh)->table; 340 lc = '/'; 341 if (*symname == '/') { 342 struct affs_sb_info *sbi = AFFS_SB(sb); 343 while (*symname == '/') 344 symname++; 345 spin_lock(&sbi->symlink_lock); 346 while (sbi->s_volume[i]) /* Cannot overflow */ 347 *p++ = sbi->s_volume[i++]; 348 spin_unlock(&sbi->symlink_lock); 349 } 350 while (i < maxlen && (c = *symname++)) { 351 if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') { 352 *p++ = '/'; 353 i++; 354 symname += 2; 355 lc = '/'; 356 } else if (c == '.' && lc == '/' && *symname == '/') { 357 symname++; 358 lc = '/'; 359 } else { 360 *p++ = c; 361 lc = c; 362 i++; 363 } 364 if (lc == '/') 365 while (*symname == '/') 366 symname++; 367 } 368 *p = 0; 369 inode->i_size = i + 1; 370 mark_buffer_dirty_inode(bh, inode); 371 affs_brelse(bh); 372 mark_inode_dirty(inode); 373 374 error = affs_add_entry(dir, inode, dentry, ST_SOFTLINK); 375 if (error) 376 goto err; 377 378 return 0; 379 380 err: 381 clear_nlink(inode); 382 mark_inode_dirty(inode); 383 iput(inode); 384 return error; 385 } 386 387 int 388 affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) 389 { 390 struct inode *inode = d_inode(old_dentry); 391 392 pr_debug("%s(%lu, %lu, \"%pd\")\n", __func__, inode->i_ino, dir->i_ino, 393 dentry); 394 395 return affs_add_entry(dir, inode, dentry, ST_LINKFILE); 396 } 397 398 static int 399 affs_rename(struct inode *old_dir, struct dentry *old_dentry, 400 struct inode *new_dir, struct dentry *new_dentry) 401 { 402 struct super_block *sb = old_dir->i_sb; 403 struct buffer_head *bh = NULL; 404 int retval; 405 406 retval = affs_check_name(new_dentry->d_name.name, 407 new_dentry->d_name.len, 408 affs_nofilenametruncate(old_dentry)); 409 410 if (retval) 411 return retval; 412 413 /* Unlink destination if it already exists */ 414 if (d_really_is_positive(new_dentry)) { 415 retval = affs_remove_header(new_dentry); 416 if (retval) 417 return retval; 418 } 419 420 bh = affs_bread(sb, d_inode(old_dentry)->i_ino); 421 if (!bh) 422 return -EIO; 423 424 /* Remove header from its parent directory. */ 425 affs_lock_dir(old_dir); 426 retval = affs_remove_hash(old_dir, bh); 427 affs_unlock_dir(old_dir); 428 if (retval) 429 goto done; 430 431 /* And insert it into the new directory with the new name. */ 432 affs_copy_name(AFFS_TAIL(sb, bh)->name, new_dentry); 433 affs_fix_checksum(sb, bh); 434 affs_lock_dir(new_dir); 435 retval = affs_insert_hash(new_dir, bh); 436 affs_unlock_dir(new_dir); 437 /* TODO: move it back to old_dir, if error? */ 438 439 done: 440 mark_buffer_dirty_inode(bh, retval ? old_dir : new_dir); 441 affs_brelse(bh); 442 return retval; 443 } 444 445 static int 446 affs_xrename(struct inode *old_dir, struct dentry *old_dentry, 447 struct inode *new_dir, struct dentry *new_dentry) 448 { 449 450 struct super_block *sb = old_dir->i_sb; 451 struct buffer_head *bh_old = NULL; 452 struct buffer_head *bh_new = NULL; 453 int retval; 454 455 bh_old = affs_bread(sb, d_inode(old_dentry)->i_ino); 456 if (!bh_old) 457 return -EIO; 458 459 bh_new = affs_bread(sb, d_inode(new_dentry)->i_ino); 460 if (!bh_new) 461 return -EIO; 462 463 /* Remove old header from its parent directory. */ 464 affs_lock_dir(old_dir); 465 retval = affs_remove_hash(old_dir, bh_old); 466 affs_unlock_dir(old_dir); 467 if (retval) 468 goto done; 469 470 /* Remove new header from its parent directory. */ 471 affs_lock_dir(new_dir); 472 retval = affs_remove_hash(new_dir, bh_new); 473 affs_unlock_dir(new_dir); 474 if (retval) 475 goto done; 476 477 /* Insert old into the new directory with the new name. */ 478 affs_copy_name(AFFS_TAIL(sb, bh_old)->name, new_dentry); 479 affs_fix_checksum(sb, bh_old); 480 affs_lock_dir(new_dir); 481 retval = affs_insert_hash(new_dir, bh_old); 482 affs_unlock_dir(new_dir); 483 484 /* Insert new into the old directory with the old name. */ 485 affs_copy_name(AFFS_TAIL(sb, bh_new)->name, old_dentry); 486 affs_fix_checksum(sb, bh_new); 487 affs_lock_dir(old_dir); 488 retval = affs_insert_hash(old_dir, bh_new); 489 affs_unlock_dir(old_dir); 490 done: 491 mark_buffer_dirty_inode(bh_old, new_dir); 492 mark_buffer_dirty_inode(bh_new, old_dir); 493 affs_brelse(bh_old); 494 affs_brelse(bh_new); 495 return retval; 496 } 497 498 int affs_rename2(struct inode *old_dir, struct dentry *old_dentry, 499 struct inode *new_dir, struct dentry *new_dentry, 500 unsigned int flags) 501 { 502 503 if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) 504 return -EINVAL; 505 506 pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__, 507 old_dir->i_ino, old_dentry, new_dir->i_ino, new_dentry); 508 509 if (flags & RENAME_EXCHANGE) 510 return affs_xrename(old_dir, old_dentry, new_dir, new_dentry); 511 512 return affs_rename(old_dir, old_dentry, new_dir, new_dentry); 513 } 514 515 static struct dentry *affs_get_parent(struct dentry *child) 516 { 517 struct inode *parent; 518 struct buffer_head *bh; 519 520 bh = affs_bread(child->d_sb, d_inode(child)->i_ino); 521 if (!bh) 522 return ERR_PTR(-EIO); 523 524 parent = affs_iget(child->d_sb, 525 be32_to_cpu(AFFS_TAIL(child->d_sb, bh)->parent)); 526 brelse(bh); 527 if (IS_ERR(parent)) 528 return ERR_CAST(parent); 529 530 return d_obtain_alias(parent); 531 } 532 533 static struct inode *affs_nfs_get_inode(struct super_block *sb, u64 ino, 534 u32 generation) 535 { 536 struct inode *inode; 537 538 if (!affs_validblock(sb, ino)) 539 return ERR_PTR(-ESTALE); 540 541 inode = affs_iget(sb, ino); 542 if (IS_ERR(inode)) 543 return ERR_CAST(inode); 544 545 return inode; 546 } 547 548 static struct dentry *affs_fh_to_dentry(struct super_block *sb, struct fid *fid, 549 int fh_len, int fh_type) 550 { 551 return generic_fh_to_dentry(sb, fid, fh_len, fh_type, 552 affs_nfs_get_inode); 553 } 554 555 static struct dentry *affs_fh_to_parent(struct super_block *sb, struct fid *fid, 556 int fh_len, int fh_type) 557 { 558 return generic_fh_to_parent(sb, fid, fh_len, fh_type, 559 affs_nfs_get_inode); 560 } 561 562 const struct export_operations affs_export_ops = { 563 .fh_to_dentry = affs_fh_to_dentry, 564 .fh_to_parent = affs_fh_to_parent, 565 .get_parent = affs_get_parent, 566 }; 567 568 const struct dentry_operations affs_dentry_operations = { 569 .d_hash = affs_hash_dentry, 570 .d_compare = affs_compare_dentry, 571 }; 572 573 const struct dentry_operations affs_intl_dentry_operations = { 574 .d_hash = affs_intl_hash_dentry, 575 .d_compare = affs_intl_compare_dentry, 576 }; 577