1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * linux/fs/affs/amigaffs.c 4 * 5 * (c) 1996 Hans-Joachim Widmaier - Rewritten 6 * 7 * (C) 1993 Ray Burr - Amiga FFS filesystem. 8 * 9 * Please send bug reports to: hjw@zvw.de 10 */ 11 12 #include <linux/math64.h> 13 #include <linux/iversion.h> 14 #include "affs.h" 15 16 /* 17 * Functions for accessing Amiga-FFS structures. 18 */ 19 20 21 /* Insert a header block bh into the directory dir 22 * caller must hold AFFS_DIR->i_hash_lock! 23 */ 24 25 int 26 affs_insert_hash(struct inode *dir, struct buffer_head *bh) 27 { 28 struct super_block *sb = dir->i_sb; 29 struct buffer_head *dir_bh; 30 u32 ino, hash_ino; 31 int offset; 32 33 ino = bh->b_blocknr; 34 offset = affs_hash_name(sb, AFFS_TAIL(sb, bh)->name + 1, AFFS_TAIL(sb, bh)->name[0]); 35 36 pr_debug("%s(dir=%lu, ino=%d)\n", __func__, dir->i_ino, ino); 37 38 dir_bh = affs_bread(sb, dir->i_ino); 39 if (!dir_bh) 40 return -EIO; 41 42 hash_ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[offset]); 43 while (hash_ino) { 44 affs_brelse(dir_bh); 45 dir_bh = affs_bread(sb, hash_ino); 46 if (!dir_bh) 47 return -EIO; 48 hash_ino = be32_to_cpu(AFFS_TAIL(sb, dir_bh)->hash_chain); 49 } 50 AFFS_TAIL(sb, bh)->parent = cpu_to_be32(dir->i_ino); 51 AFFS_TAIL(sb, bh)->hash_chain = 0; 52 affs_fix_checksum(sb, bh); 53 54 if (dir->i_ino == dir_bh->b_blocknr) 55 AFFS_HEAD(dir_bh)->table[offset] = cpu_to_be32(ino); 56 else 57 AFFS_TAIL(sb, dir_bh)->hash_chain = cpu_to_be32(ino); 58 59 affs_adjust_checksum(dir_bh, ino); 60 mark_buffer_dirty_inode(dir_bh, dir); 61 affs_brelse(dir_bh); 62 63 inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); 64 inode_inc_iversion(dir); 65 mark_inode_dirty(dir); 66 67 return 0; 68 } 69 70 /* Remove a header block from its directory. 71 * caller must hold AFFS_DIR->i_hash_lock! 72 */ 73 74 int 75 affs_remove_hash(struct inode *dir, struct buffer_head *rem_bh) 76 { 77 struct super_block *sb; 78 struct buffer_head *bh; 79 u32 rem_ino, hash_ino; 80 __be32 ino; 81 int offset, retval; 82 83 sb = dir->i_sb; 84 rem_ino = rem_bh->b_blocknr; 85 offset = affs_hash_name(sb, AFFS_TAIL(sb, rem_bh)->name+1, AFFS_TAIL(sb, rem_bh)->name[0]); 86 pr_debug("%s(dir=%lu, ino=%d, hashval=%d)\n", __func__, dir->i_ino, 87 rem_ino, offset); 88 89 bh = affs_bread(sb, dir->i_ino); 90 if (!bh) 91 return -EIO; 92 93 retval = -ENOENT; 94 hash_ino = be32_to_cpu(AFFS_HEAD(bh)->table[offset]); 95 while (hash_ino) { 96 if (hash_ino == rem_ino) { 97 ino = AFFS_TAIL(sb, rem_bh)->hash_chain; 98 if (dir->i_ino == bh->b_blocknr) 99 AFFS_HEAD(bh)->table[offset] = ino; 100 else 101 AFFS_TAIL(sb, bh)->hash_chain = ino; 102 affs_adjust_checksum(bh, be32_to_cpu(ino) - hash_ino); 103 mark_buffer_dirty_inode(bh, dir); 104 AFFS_TAIL(sb, rem_bh)->parent = 0; 105 retval = 0; 106 break; 107 } 108 affs_brelse(bh); 109 bh = affs_bread(sb, hash_ino); 110 if (!bh) 111 return -EIO; 112 hash_ino = be32_to_cpu(AFFS_TAIL(sb, bh)->hash_chain); 113 } 114 115 affs_brelse(bh); 116 117 inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); 118 inode_inc_iversion(dir); 119 mark_inode_dirty(dir); 120 121 return retval; 122 } 123 124 static void 125 affs_fix_dcache(struct inode *inode, u32 entry_ino) 126 { 127 struct dentry *dentry; 128 spin_lock(&inode->i_lock); 129 hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) { 130 if (entry_ino == (u32)(long)dentry->d_fsdata) { 131 dentry->d_fsdata = (void *)inode->i_ino; 132 break; 133 } 134 } 135 spin_unlock(&inode->i_lock); 136 } 137 138 139 /* Remove header from link chain */ 140 141 static int 142 affs_remove_link(struct dentry *dentry) 143 { 144 struct inode *dir, *inode = d_inode(dentry); 145 struct super_block *sb = inode->i_sb; 146 struct buffer_head *bh, *link_bh = NULL; 147 u32 link_ino, ino; 148 int retval; 149 150 pr_debug("%s(key=%ld)\n", __func__, inode->i_ino); 151 retval = -EIO; 152 bh = affs_bread(sb, inode->i_ino); 153 if (!bh) 154 goto done; 155 156 link_ino = (u32)(long)dentry->d_fsdata; 157 if (inode->i_ino == link_ino) { 158 /* we can't remove the head of the link, as its blocknr is still used as ino, 159 * so we remove the block of the first link instead. 160 */ 161 link_ino = be32_to_cpu(AFFS_TAIL(sb, bh)->link_chain); 162 link_bh = affs_bread(sb, link_ino); 163 if (!link_bh) 164 goto done; 165 166 dir = affs_iget(sb, be32_to_cpu(AFFS_TAIL(sb, link_bh)->parent)); 167 if (IS_ERR(dir)) { 168 retval = PTR_ERR(dir); 169 goto done; 170 } 171 172 affs_lock_dir(dir); 173 /* 174 * if there's a dentry for that block, make it 175 * refer to inode itself. 176 */ 177 affs_fix_dcache(inode, link_ino); 178 retval = affs_remove_hash(dir, link_bh); 179 if (retval) { 180 affs_unlock_dir(dir); 181 goto done; 182 } 183 mark_buffer_dirty_inode(link_bh, inode); 184 185 memcpy(AFFS_TAIL(sb, bh)->name, AFFS_TAIL(sb, link_bh)->name, 32); 186 retval = affs_insert_hash(dir, bh); 187 if (retval) { 188 affs_unlock_dir(dir); 189 goto done; 190 } 191 mark_buffer_dirty_inode(bh, inode); 192 193 affs_unlock_dir(dir); 194 iput(dir); 195 } else { 196 link_bh = affs_bread(sb, link_ino); 197 if (!link_bh) 198 goto done; 199 } 200 201 while ((ino = be32_to_cpu(AFFS_TAIL(sb, bh)->link_chain)) != 0) { 202 if (ino == link_ino) { 203 __be32 ino2 = AFFS_TAIL(sb, link_bh)->link_chain; 204 AFFS_TAIL(sb, bh)->link_chain = ino2; 205 affs_adjust_checksum(bh, be32_to_cpu(ino2) - link_ino); 206 mark_buffer_dirty_inode(bh, inode); 207 retval = 0; 208 /* Fix the link count, if bh is a normal header block without links */ 209 switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) { 210 case ST_LINKDIR: 211 case ST_LINKFILE: 212 break; 213 default: 214 if (!AFFS_TAIL(sb, bh)->link_chain) 215 set_nlink(inode, 1); 216 } 217 affs_free_block(sb, link_ino); 218 goto done; 219 } 220 affs_brelse(bh); 221 bh = affs_bread(sb, ino); 222 if (!bh) 223 goto done; 224 } 225 retval = -ENOENT; 226 done: 227 affs_brelse(link_bh); 228 affs_brelse(bh); 229 return retval; 230 } 231 232 233 static int 234 affs_empty_dir(struct inode *inode) 235 { 236 struct super_block *sb = inode->i_sb; 237 struct buffer_head *bh; 238 int retval, size; 239 240 retval = -EIO; 241 bh = affs_bread(sb, inode->i_ino); 242 if (!bh) 243 goto done; 244 245 retval = -ENOTEMPTY; 246 for (size = AFFS_SB(sb)->s_hashsize - 1; size >= 0; size--) 247 if (AFFS_HEAD(bh)->table[size]) 248 goto not_empty; 249 retval = 0; 250 not_empty: 251 affs_brelse(bh); 252 done: 253 return retval; 254 } 255 256 257 /* Remove a filesystem object. If the object to be removed has 258 * links to it, one of the links must be changed to inherit 259 * the file or directory. As above, any inode will do. 260 * The buffer will not be freed. If the header is a link, the 261 * block will be marked as free. 262 * This function returns a negative error number in case of 263 * an error, else 0 if the inode is to be deleted or 1 if not. 264 */ 265 266 int 267 affs_remove_header(struct dentry *dentry) 268 { 269 struct super_block *sb; 270 struct inode *inode, *dir; 271 struct buffer_head *bh = NULL; 272 int retval; 273 274 dir = d_inode(dentry->d_parent); 275 sb = dir->i_sb; 276 277 retval = -ENOENT; 278 inode = d_inode(dentry); 279 if (!inode) 280 goto done; 281 282 pr_debug("%s(key=%ld)\n", __func__, inode->i_ino); 283 retval = -EIO; 284 bh = affs_bread(sb, (u32)(long)dentry->d_fsdata); 285 if (!bh) 286 goto done; 287 288 affs_lock_link(inode); 289 affs_lock_dir(dir); 290 switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) { 291 case ST_USERDIR: 292 /* if we ever want to support links to dirs 293 * i_hash_lock of the inode must only be 294 * taken after some checks 295 */ 296 affs_lock_dir(inode); 297 retval = affs_empty_dir(inode); 298 affs_unlock_dir(inode); 299 if (retval) 300 goto done_unlock; 301 break; 302 default: 303 break; 304 } 305 306 retval = affs_remove_hash(dir, bh); 307 if (retval) 308 goto done_unlock; 309 mark_buffer_dirty_inode(bh, inode); 310 311 affs_unlock_dir(dir); 312 313 if (inode->i_nlink > 1) 314 retval = affs_remove_link(dentry); 315 else 316 clear_nlink(inode); 317 affs_unlock_link(inode); 318 inode_set_ctime_current(inode); 319 mark_inode_dirty(inode); 320 321 done: 322 affs_brelse(bh); 323 return retval; 324 325 done_unlock: 326 affs_unlock_dir(dir); 327 affs_unlock_link(inode); 328 goto done; 329 } 330 331 /* Checksum a block, do various consistency checks and optionally return 332 the blocks type number. DATA points to the block. If their pointers 333 are non-null, *PTYPE and *STYPE are set to the primary and secondary 334 block types respectively, *HASHSIZE is set to the size of the hashtable 335 (which lets us calculate the block size). 336 Returns non-zero if the block is not consistent. */ 337 338 u32 339 affs_checksum_block(struct super_block *sb, struct buffer_head *bh) 340 { 341 __be32 *ptr = (__be32 *)bh->b_data; 342 u32 sum; 343 int bsize; 344 345 sum = 0; 346 for (bsize = sb->s_blocksize / sizeof(__be32); bsize > 0; bsize--) 347 sum += be32_to_cpu(*ptr++); 348 return sum; 349 } 350 351 /* 352 * Calculate the checksum of a disk block and store it 353 * at the indicated position. 354 */ 355 356 void 357 affs_fix_checksum(struct super_block *sb, struct buffer_head *bh) 358 { 359 int cnt = sb->s_blocksize / sizeof(__be32); 360 __be32 *ptr = (__be32 *)bh->b_data; 361 u32 checksum; 362 __be32 *checksumptr; 363 364 checksumptr = ptr + 5; 365 *checksumptr = 0; 366 for (checksum = 0; cnt > 0; ptr++, cnt--) 367 checksum += be32_to_cpu(*ptr); 368 *checksumptr = cpu_to_be32(-checksum); 369 } 370 371 void 372 affs_secs_to_datestamp(time64_t secs, struct affs_date *ds) 373 { 374 u32 days; 375 u32 minute; 376 s32 rem; 377 378 secs -= sys_tz.tz_minuteswest * 60 + AFFS_EPOCH_DELTA; 379 if (secs < 0) 380 secs = 0; 381 days = div_s64_rem(secs, 86400, &rem); 382 minute = rem / 60; 383 rem -= minute * 60; 384 385 ds->days = cpu_to_be32(days); 386 ds->mins = cpu_to_be32(minute); 387 ds->ticks = cpu_to_be32(rem * 50); 388 } 389 390 umode_t 391 affs_prot_to_mode(u32 prot) 392 { 393 umode_t mode = 0; 394 395 if (!(prot & FIBF_NOWRITE)) 396 mode |= 0200; 397 if (!(prot & FIBF_NOREAD)) 398 mode |= 0400; 399 if (!(prot & FIBF_NOEXECUTE)) 400 mode |= 0100; 401 if (prot & FIBF_GRP_WRITE) 402 mode |= 0020; 403 if (prot & FIBF_GRP_READ) 404 mode |= 0040; 405 if (prot & FIBF_GRP_EXECUTE) 406 mode |= 0010; 407 if (prot & FIBF_OTR_WRITE) 408 mode |= 0002; 409 if (prot & FIBF_OTR_READ) 410 mode |= 0004; 411 if (prot & FIBF_OTR_EXECUTE) 412 mode |= 0001; 413 414 return mode; 415 } 416 417 void 418 affs_mode_to_prot(struct inode *inode) 419 { 420 u32 prot = AFFS_I(inode)->i_protect; 421 umode_t mode = inode->i_mode; 422 423 /* 424 * First, clear all RWED bits for owner, group, other. 425 * Then, recalculate them afresh. 426 * 427 * We'll always clear the delete-inhibit bit for the owner, as that is 428 * the classic single-user mode AmigaOS protection bit and we need to 429 * stay compatible with all scenarios. 430 * 431 * Since multi-user AmigaOS is an extension, we'll only set the 432 * delete-allow bit if any of the other bits in the same user class 433 * (group/other) are used. 434 */ 435 prot &= ~(FIBF_NOEXECUTE | FIBF_NOREAD 436 | FIBF_NOWRITE | FIBF_NODELETE 437 | FIBF_GRP_EXECUTE | FIBF_GRP_READ 438 | FIBF_GRP_WRITE | FIBF_GRP_DELETE 439 | FIBF_OTR_EXECUTE | FIBF_OTR_READ 440 | FIBF_OTR_WRITE | FIBF_OTR_DELETE); 441 442 /* Classic single-user AmigaOS flags. These are inverted. */ 443 if (!(mode & 0100)) 444 prot |= FIBF_NOEXECUTE; 445 if (!(mode & 0400)) 446 prot |= FIBF_NOREAD; 447 if (!(mode & 0200)) 448 prot |= FIBF_NOWRITE; 449 450 /* Multi-user extended flags. Not inverted. */ 451 if (mode & 0010) 452 prot |= FIBF_GRP_EXECUTE; 453 if (mode & 0040) 454 prot |= FIBF_GRP_READ; 455 if (mode & 0020) 456 prot |= FIBF_GRP_WRITE; 457 if (mode & 0070) 458 prot |= FIBF_GRP_DELETE; 459 460 if (mode & 0001) 461 prot |= FIBF_OTR_EXECUTE; 462 if (mode & 0004) 463 prot |= FIBF_OTR_READ; 464 if (mode & 0002) 465 prot |= FIBF_OTR_WRITE; 466 if (mode & 0007) 467 prot |= FIBF_OTR_DELETE; 468 469 AFFS_I(inode)->i_protect = prot; 470 } 471 472 void 473 affs_error(struct super_block *sb, const char *function, const char *fmt, ...) 474 { 475 struct va_format vaf; 476 va_list args; 477 478 va_start(args, fmt); 479 vaf.fmt = fmt; 480 vaf.va = &args; 481 pr_crit("error (device %s): %s(): %pV\n", sb->s_id, function, &vaf); 482 if (!sb_rdonly(sb)) 483 pr_warn("Remounting filesystem read-only\n"); 484 sb->s_flags |= SB_RDONLY; 485 va_end(args); 486 } 487 488 void 489 affs_warning(struct super_block *sb, const char *function, const char *fmt, ...) 490 { 491 struct va_format vaf; 492 va_list args; 493 494 va_start(args, fmt); 495 vaf.fmt = fmt; 496 vaf.va = &args; 497 pr_warn("(device %s): %s(): %pV\n", sb->s_id, function, &vaf); 498 va_end(args); 499 } 500 501 bool 502 affs_nofilenametruncate(const struct dentry *dentry) 503 { 504 return affs_test_opt(AFFS_SB(dentry->d_sb)->s_flags, SF_NO_TRUNCATE); 505 } 506 507 /* Check if the name is valid for a affs object. */ 508 509 int 510 affs_check_name(const unsigned char *name, int len, bool notruncate) 511 { 512 int i; 513 514 if (len > AFFSNAMEMAX) { 515 if (notruncate) 516 return -ENAMETOOLONG; 517 len = AFFSNAMEMAX; 518 } 519 for (i = 0; i < len; i++) { 520 if (name[i] < ' ' || name[i] == ':' 521 || (name[i] > 0x7e && name[i] < 0xa0)) 522 return -EINVAL; 523 } 524 525 return 0; 526 } 527 528 /* This function copies name to bstr, with at most 30 529 * characters length. The bstr will be prepended by 530 * a length byte. 531 * NOTE: The name will must be already checked by 532 * affs_check_name()! 533 */ 534 535 int 536 affs_copy_name(unsigned char *bstr, struct dentry *dentry) 537 { 538 u32 len = min(dentry->d_name.len, AFFSNAMEMAX); 539 540 *bstr++ = len; 541 memcpy(bstr, dentry->d_name.name, len); 542 return len; 543 } 544
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.