1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * linux/fs/hfsplus/inode.c 4 * 5 * Copyright (C) 2001 6 * Brad Boyer (flar@allandria.com) 7 * (C) 2003 Ardis Technologies <roman@ardistech.com> 8 * 9 * Inode handling routines 10 */ 11 12 #include <linux/blkdev.h> 13 #include <linux/mm.h> 14 #include <linux/fs.h> 15 #include <linux/pagemap.h> 16 #include <linux/mpage.h> 17 #include <linux/sched.h> 18 #include <linux/cred.h> 19 #include <linux/uio.h> 20 #include <linux/fileattr.h> 21 22 #include "hfsplus_fs.h" 23 #include "hfsplus_raw.h" 24 #include "xattr.h" 25 26 static int hfsplus_read_folio(struct file *file, struct folio *folio) 27 { 28 return block_read_full_folio(folio, hfsplus_get_block); 29 } 30 31 static void hfsplus_write_failed(struct address_space *mapping, loff_t to) 32 { 33 struct inode *inode = mapping->host; 34 35 if (to > inode->i_size) { 36 truncate_pagecache(inode, inode->i_size); 37 hfsplus_file_truncate(inode); 38 } 39 } 40 41 int hfsplus_write_begin(const struct kiocb *iocb, 42 struct address_space *mapping, loff_t pos, 43 unsigned len, struct folio **foliop, 44 void **fsdata) 45 { 46 struct inode *inode = mapping->host; 47 struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); 48 loff_t total_capacity; 49 int ret; 50 51 total_capacity = (loff_t)sbi->total_blocks << sbi->alloc_blksz_shift; 52 53 if (pos >= total_capacity) 54 return -EFBIG; 55 56 ret = cont_write_begin(iocb, mapping, pos, len, foliop, fsdata, 57 hfsplus_get_block, 58 &HFSPLUS_I(inode)->phys_size); 59 if (unlikely(ret)) 60 hfsplus_write_failed(mapping, pos + len); 61 62 return ret; 63 } 64 65 static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block) 66 { 67 return generic_block_bmap(mapping, block, hfsplus_get_block); 68 } 69 70 static bool hfsplus_release_folio(struct folio *folio, gfp_t mask) 71 { 72 struct inode *inode = folio->mapping->host; 73 struct super_block *sb = inode->i_sb; 74 struct hfs_btree *tree; 75 struct hfs_bnode *node; 76 u32 nidx; 77 int i; 78 bool res = true; 79 80 switch (inode->i_ino) { 81 case HFSPLUS_EXT_CNID: 82 tree = HFSPLUS_SB(sb)->ext_tree; 83 break; 84 case HFSPLUS_CAT_CNID: 85 tree = HFSPLUS_SB(sb)->cat_tree; 86 break; 87 case HFSPLUS_ATTR_CNID: 88 tree = HFSPLUS_SB(sb)->attr_tree; 89 break; 90 default: 91 BUG(); 92 return false; 93 } 94 if (!tree) 95 return false; 96 if (tree->node_size >= PAGE_SIZE) { 97 nidx = folio->index >> 98 (tree->node_size_shift - PAGE_SHIFT); 99 spin_lock(&tree->hash_lock); 100 node = hfs_bnode_findhash(tree, nidx); 101 if (!node) 102 ; 103 else if (atomic_read(&node->refcnt)) 104 res = false; 105 if (res && node) { 106 hfs_bnode_unhash(node); 107 hfs_bnode_free(node); 108 } 109 spin_unlock(&tree->hash_lock); 110 } else { 111 nidx = folio->index << 112 (PAGE_SHIFT - tree->node_size_shift); 113 i = 1 << (PAGE_SHIFT - tree->node_size_shift); 114 spin_lock(&tree->hash_lock); 115 do { 116 node = hfs_bnode_findhash(tree, nidx++); 117 if (!node) 118 continue; 119 if (atomic_read(&node->refcnt)) { 120 res = false; 121 break; 122 } 123 hfs_bnode_unhash(node); 124 hfs_bnode_free(node); 125 } while (--i && nidx < tree->node_count); 126 spin_unlock(&tree->hash_lock); 127 } 128 return res ? try_to_free_buffers(folio) : false; 129 } 130 131 static ssize_t hfsplus_direct_IO(struct kiocb *iocb, struct iov_iter *iter) 132 { 133 struct file *file = iocb->ki_filp; 134 struct address_space *mapping = file->f_mapping; 135 struct inode *inode = mapping->host; 136 loff_t isize; 137 size_t count = iov_iter_count(iter); 138 loff_t end = iocb->ki_pos + count; 139 ssize_t ret; 140 141 /* 142 * The hfsplus_get_block() only allows creating the next sequential block. 143 * For direct writes beyond EOF, expand the file first. 144 */ 145 if (iov_iter_rw(iter) == WRITE && iocb->ki_pos > i_size_read(inode)) { 146 loff_t start_off, end_off; 147 loff_t start_page, end_page; 148 149 isize = i_size_read(inode); 150 151 /* 152 * Wait for any in-flight DIO on this inode to finish before 153 * calling generic_cont_expand_simple(). 154 */ 155 inode_dio_wait(inode); 156 157 ret = generic_cont_expand_simple(inode, iocb->ki_pos); 158 if (ret) 159 return ret; 160 161 start_off = isize; 162 end_off = (end > 0) ? end - 1 : end; 163 164 ret = filemap_write_and_wait_range(mapping, start_off, end_off); 165 if (ret) 166 return ret; 167 168 start_page = start_off >> PAGE_SHIFT; 169 end_page = end_off >> PAGE_SHIFT; 170 171 invalidate_inode_pages2_range(mapping, start_page, end_page); 172 } 173 174 ret = blockdev_direct_IO(iocb, inode, iter, hfsplus_get_block); 175 176 /* 177 * In case of error extending write may have instantiated a few 178 * blocks outside i_size. Trim these off again. 179 */ 180 if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) { 181 isize = i_size_read(inode); 182 183 if (end > isize) 184 hfsplus_write_failed(mapping, end); 185 } 186 187 return ret; 188 } 189 190 static int hfsplus_writepages(struct address_space *mapping, 191 struct writeback_control *wbc) 192 { 193 return mpage_writepages(mapping, wbc, hfsplus_get_block); 194 } 195 196 const struct address_space_operations hfsplus_btree_aops = { 197 .dirty_folio = block_dirty_folio, 198 .invalidate_folio = block_invalidate_folio, 199 .read_folio = hfsplus_read_folio, 200 .writepages = hfsplus_writepages, 201 .write_begin = hfsplus_write_begin, 202 .write_end = generic_write_end, 203 .migrate_folio = buffer_migrate_folio, 204 .bmap = hfsplus_bmap, 205 .release_folio = hfsplus_release_folio, 206 }; 207 208 const struct address_space_operations hfsplus_aops = { 209 .dirty_folio = block_dirty_folio, 210 .invalidate_folio = block_invalidate_folio, 211 .read_folio = hfsplus_read_folio, 212 .write_begin = hfsplus_write_begin, 213 .write_end = generic_write_end, 214 .bmap = hfsplus_bmap, 215 .direct_IO = hfsplus_direct_IO, 216 .writepages = hfsplus_writepages, 217 .migrate_folio = buffer_migrate_folio, 218 }; 219 220 const struct dentry_operations hfsplus_dentry_operations = { 221 .d_hash = hfsplus_hash_dentry, 222 .d_compare = hfsplus_compare_dentry, 223 }; 224 225 static int hfsplus_get_perms(struct inode *inode, 226 struct hfsplus_perm *perms, int dir) 227 { 228 struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); 229 u16 mode; 230 231 mode = be16_to_cpu(perms->mode); 232 if (dir) { 233 if (mode && !S_ISDIR(mode)) 234 goto bad_type; 235 } else if (mode) { 236 switch (mode & S_IFMT) { 237 case S_IFREG: 238 case S_IFLNK: 239 case S_IFCHR: 240 case S_IFBLK: 241 case S_IFIFO: 242 case S_IFSOCK: 243 break; 244 default: 245 goto bad_type; 246 } 247 } 248 249 i_uid_write(inode, be32_to_cpu(perms->owner)); 250 if ((test_bit(HFSPLUS_SB_UID, &sbi->flags)) || (!i_uid_read(inode) && !mode)) 251 inode->i_uid = sbi->uid; 252 253 i_gid_write(inode, be32_to_cpu(perms->group)); 254 if ((test_bit(HFSPLUS_SB_GID, &sbi->flags)) || (!i_gid_read(inode) && !mode)) 255 inode->i_gid = sbi->gid; 256 257 if (dir) { 258 mode = mode ? (mode & S_IALLUGO) : (S_IRWXUGO & ~(sbi->umask)); 259 mode |= S_IFDIR; 260 } else if (!mode) 261 mode = S_IFREG | ((S_IRUGO|S_IWUGO) & ~(sbi->umask)); 262 inode->i_mode = mode; 263 264 HFSPLUS_I(inode)->userflags = perms->userflags; 265 if (perms->rootflags & HFSPLUS_FLG_IMMUTABLE) 266 inode->i_flags |= S_IMMUTABLE; 267 else 268 inode->i_flags &= ~S_IMMUTABLE; 269 if (perms->rootflags & HFSPLUS_FLG_APPEND) 270 inode->i_flags |= S_APPEND; 271 else 272 inode->i_flags &= ~S_APPEND; 273 return 0; 274 bad_type: 275 pr_err("invalid file type 0%04o for inode %llu\n", mode, inode->i_ino); 276 return -EIO; 277 } 278 279 static int hfsplus_file_open(struct inode *inode, struct file *file) 280 { 281 if (HFSPLUS_IS_RSRC(inode)) 282 inode = HFSPLUS_I(inode)->rsrc_inode; 283 if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) 284 return -EOVERFLOW; 285 atomic_inc(&HFSPLUS_I(inode)->opencnt); 286 return 0; 287 } 288 289 static int hfsplus_file_release(struct inode *inode, struct file *file) 290 { 291 struct super_block *sb = inode->i_sb; 292 293 if (HFSPLUS_IS_RSRC(inode)) 294 inode = HFSPLUS_I(inode)->rsrc_inode; 295 if (atomic_dec_and_test(&HFSPLUS_I(inode)->opencnt)) { 296 inode_lock(inode); 297 hfsplus_file_truncate(inode); 298 if (inode->i_flags & S_DEAD) { 299 hfsplus_delete_cat(inode->i_ino, 300 HFSPLUS_SB(sb)->hidden_dir, NULL); 301 hfsplus_delete_inode(inode); 302 } 303 inode_unlock(inode); 304 } 305 return 0; 306 } 307 308 static int hfsplus_setattr(struct mnt_idmap *idmap, 309 struct dentry *dentry, struct iattr *attr) 310 { 311 struct inode *inode = d_inode(dentry); 312 int error; 313 314 error = setattr_prepare(&nop_mnt_idmap, dentry, attr); 315 if (error) 316 return error; 317 318 if ((attr->ia_valid & ATTR_SIZE) && 319 attr->ia_size != i_size_read(inode)) { 320 inode_dio_wait(inode); 321 if (attr->ia_size > inode->i_size) { 322 error = generic_cont_expand_simple(inode, 323 attr->ia_size); 324 if (error) 325 return error; 326 } 327 truncate_setsize(inode, attr->ia_size); 328 hfsplus_file_truncate(inode); 329 inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); 330 } 331 332 setattr_copy(&nop_mnt_idmap, inode, attr); 333 mark_inode_dirty(inode); 334 335 return 0; 336 } 337 338 int hfsplus_getattr(struct mnt_idmap *idmap, const struct path *path, 339 struct kstat *stat, u32 request_mask, 340 unsigned int query_flags) 341 { 342 struct inode *inode = d_inode(path->dentry); 343 struct hfsplus_inode_info *hip = HFSPLUS_I(inode); 344 345 if (request_mask & STATX_BTIME) { 346 stat->result_mask |= STATX_BTIME; 347 stat->btime = hfsp_mt2ut(hip->create_date); 348 } 349 350 if (inode->i_flags & S_APPEND) 351 stat->attributes |= STATX_ATTR_APPEND; 352 if (inode->i_flags & S_IMMUTABLE) 353 stat->attributes |= STATX_ATTR_IMMUTABLE; 354 if (hip->userflags & HFSPLUS_FLG_NODUMP) 355 stat->attributes |= STATX_ATTR_NODUMP; 356 357 stat->attributes_mask |= STATX_ATTR_APPEND | STATX_ATTR_IMMUTABLE | 358 STATX_ATTR_NODUMP; 359 360 generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat); 361 return 0; 362 } 363 364 int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end, 365 int datasync) 366 { 367 struct inode *inode = file->f_mapping->host; 368 struct hfsplus_inode_info *hip = HFSPLUS_I(inode); 369 struct super_block *sb = inode->i_sb; 370 struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); 371 struct hfsplus_vh *vhdr = sbi->s_vhdr; 372 int error = 0, error2; 373 374 hfs_dbg("inode->i_ino %llu, start %llu, end %llu\n", 375 inode->i_ino, start, end); 376 377 error = file_write_and_wait_range(file, start, end); 378 if (error) 379 return error; 380 inode_lock(inode); 381 382 /* 383 * Sync inode metadata into the catalog and extent trees. 384 */ 385 sync_inode_metadata(inode, 1); 386 387 /* 388 * And explicitly write out the btrees. 389 */ 390 if (test_and_clear_bit(HFSPLUS_I_CAT_DIRTY, 391 &HFSPLUS_I(HFSPLUS_CAT_TREE_I(sb))->flags)) { 392 clear_bit(HFSPLUS_I_CAT_DIRTY, &hip->flags); 393 error = filemap_write_and_wait(sbi->cat_tree->inode->i_mapping); 394 } 395 396 if (test_and_clear_bit(HFSPLUS_I_EXT_DIRTY, 397 &HFSPLUS_I(HFSPLUS_EXT_TREE_I(sb))->flags)) { 398 clear_bit(HFSPLUS_I_EXT_DIRTY, &hip->flags); 399 error2 = 400 filemap_write_and_wait(sbi->ext_tree->inode->i_mapping); 401 if (!error) 402 error = error2; 403 } 404 405 if (sbi->attr_tree) { 406 if (test_and_clear_bit(HFSPLUS_I_ATTR_DIRTY, 407 &HFSPLUS_I(HFSPLUS_ATTR_TREE_I(sb))->flags)) { 408 clear_bit(HFSPLUS_I_ATTR_DIRTY, &hip->flags); 409 error2 = 410 filemap_write_and_wait( 411 sbi->attr_tree->inode->i_mapping); 412 if (!error) 413 error = error2; 414 } 415 } else { 416 if (test_and_clear_bit(HFSPLUS_I_ATTR_DIRTY, &hip->flags)) 417 pr_err("sync non-existent attributes tree\n"); 418 } 419 420 if (test_and_clear_bit(HFSPLUS_I_ALLOC_DIRTY, 421 &HFSPLUS_I(sbi->alloc_file)->flags)) { 422 clear_bit(HFSPLUS_I_ALLOC_DIRTY, &hip->flags); 423 error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping); 424 if (!error) 425 error = error2; 426 } 427 428 mutex_lock(&sbi->vh_mutex); 429 hfsplus_prepare_volume_header_for_commit(vhdr); 430 mutex_unlock(&sbi->vh_mutex); 431 432 error2 = hfsplus_commit_superblock(inode->i_sb); 433 if (!error) 434 error = error2; 435 436 if (!test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags)) 437 blkdev_issue_flush(inode->i_sb->s_bdev); 438 439 inode_unlock(inode); 440 441 return error; 442 } 443 444 static const struct inode_operations hfsplus_file_inode_operations = { 445 .setattr = hfsplus_setattr, 446 .getattr = hfsplus_getattr, 447 .listxattr = hfsplus_listxattr, 448 .fileattr_get = hfsplus_fileattr_get, 449 .fileattr_set = hfsplus_fileattr_set, 450 }; 451 452 static const struct inode_operations hfsplus_symlink_inode_operations = { 453 .get_link = page_get_link, 454 .setattr = hfsplus_setattr, 455 .getattr = hfsplus_getattr, 456 .listxattr = hfsplus_listxattr, 457 }; 458 459 static const struct inode_operations hfsplus_special_inode_operations = { 460 .setattr = hfsplus_setattr, 461 .getattr = hfsplus_getattr, 462 .listxattr = hfsplus_listxattr, 463 }; 464 465 static const struct file_operations hfsplus_file_operations = { 466 .llseek = generic_file_llseek, 467 .read_iter = generic_file_read_iter, 468 .write_iter = generic_file_write_iter, 469 .mmap_prepare = generic_file_mmap_prepare, 470 .splice_read = filemap_splice_read, 471 .splice_write = iter_file_splice_write, 472 .fsync = hfsplus_file_fsync, 473 .open = hfsplus_file_open, 474 .release = hfsplus_file_release, 475 .unlocked_ioctl = hfsplus_ioctl, 476 }; 477 478 struct inode *hfsplus_new_inode(struct super_block *sb, struct inode *dir, 479 umode_t mode) 480 { 481 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 482 struct inode *inode = new_inode(sb); 483 struct hfsplus_inode_info *hip; 484 485 if (!inode) 486 return NULL; 487 488 inode->i_ino = sbi->next_cnid++; 489 inode_init_owner(&nop_mnt_idmap, inode, dir, mode); 490 set_nlink(inode, 1); 491 simple_inode_init_ts(inode); 492 493 hip = HFSPLUS_I(inode); 494 mutex_init(&hip->extents_lock); 495 atomic_set(&hip->opencnt, 0); 496 hip->extent_state = 0; 497 hip->flags = 0; 498 hip->userflags = 0; 499 hip->subfolders = 0; 500 memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec)); 501 memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); 502 hip->alloc_blocks = 0; 503 hip->first_blocks = 0; 504 hip->cached_start = 0; 505 hip->cached_blocks = 0; 506 hip->phys_size = 0; 507 hip->fs_blocks = 0; 508 hip->rsrc_inode = NULL; 509 if (S_ISDIR(inode->i_mode)) { 510 inode->i_size = 2; 511 sbi->folder_count++; 512 inode->i_op = &hfsplus_dir_inode_operations; 513 inode->i_fop = &hfsplus_dir_operations; 514 } else if (S_ISREG(inode->i_mode)) { 515 sbi->file_count++; 516 inode->i_op = &hfsplus_file_inode_operations; 517 inode->i_fop = &hfsplus_file_operations; 518 inode->i_mapping->a_ops = &hfsplus_aops; 519 hip->clump_blocks = sbi->data_clump_blocks; 520 } else if (S_ISLNK(inode->i_mode)) { 521 sbi->file_count++; 522 inode->i_op = &hfsplus_symlink_inode_operations; 523 inode_nohighmem(inode); 524 inode->i_mapping->a_ops = &hfsplus_aops; 525 hip->clump_blocks = 1; 526 } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || 527 S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { 528 sbi->file_count++; 529 inode->i_op = &hfsplus_special_inode_operations; 530 } else 531 sbi->file_count++; 532 533 insert_inode_hash(inode); 534 mark_inode_dirty(inode); 535 hfsplus_mark_mdb_dirty(sb); 536 537 return inode; 538 } 539 540 void hfsplus_delete_inode(struct inode *inode) 541 { 542 struct super_block *sb = inode->i_sb; 543 544 if (S_ISDIR(inode->i_mode)) { 545 HFSPLUS_SB(sb)->folder_count--; 546 hfsplus_mark_mdb_dirty(sb); 547 return; 548 } 549 HFSPLUS_SB(sb)->file_count--; 550 if (S_ISREG(inode->i_mode)) { 551 if (!inode->i_nlink) { 552 inode->i_size = 0; 553 hfsplus_file_truncate(inode); 554 } 555 } else if (S_ISLNK(inode->i_mode)) { 556 inode->i_size = 0; 557 hfsplus_file_truncate(inode); 558 } 559 hfsplus_mark_mdb_dirty(sb); 560 } 561 562 void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork) 563 { 564 struct super_block *sb = inode->i_sb; 565 struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); 566 struct hfsplus_inode_info *hip = HFSPLUS_I(inode); 567 u32 count; 568 int i; 569 570 memcpy(&hip->first_extents, &fork->extents, sizeof(hfsplus_extent_rec)); 571 for (count = 0, i = 0; i < 8; i++) 572 count += be32_to_cpu(fork->extents[i].block_count); 573 hip->first_blocks = count; 574 memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec)); 575 hip->cached_start = 0; 576 hip->cached_blocks = 0; 577 578 hip->alloc_blocks = be32_to_cpu(fork->total_blocks); 579 hip->phys_size = inode->i_size = be64_to_cpu(fork->total_size); 580 hip->fs_blocks = 581 (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits; 582 inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits); 583 hip->clump_blocks = 584 be32_to_cpu(fork->clump_size) >> sbi->alloc_blksz_shift; 585 if (!hip->clump_blocks) { 586 hip->clump_blocks = HFSPLUS_IS_RSRC(inode) ? 587 sbi->rsrc_clump_blocks : 588 sbi->data_clump_blocks; 589 } 590 } 591 592 void hfsplus_inode_write_fork(struct inode *inode, 593 struct hfsplus_fork_raw *fork) 594 { 595 memcpy(&fork->extents, &HFSPLUS_I(inode)->first_extents, 596 sizeof(hfsplus_extent_rec)); 597 fork->total_size = cpu_to_be64(inode->i_size); 598 fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode)->alloc_blocks); 599 } 600 601 int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd) 602 { 603 hfsplus_cat_entry entry; 604 int res = 0; 605 u16 type; 606 607 type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset); 608 609 HFSPLUS_I(inode)->linkid = 0; 610 if (type == HFSPLUS_FOLDER) { 611 struct hfsplus_cat_folder *folder = &entry.folder; 612 613 if (fd->entrylength < sizeof(struct hfsplus_cat_folder)) { 614 pr_err("bad catalog folder entry\n"); 615 res = -EIO; 616 goto out; 617 } 618 hfs_bnode_read(fd->bnode, &entry, fd->entryoffset, 619 sizeof(struct hfsplus_cat_folder)); 620 res = hfsplus_get_perms(inode, &folder->permissions, 1); 621 if (res) 622 goto out; 623 set_nlink(inode, 1); 624 inode->i_size = 2 + be32_to_cpu(folder->valence); 625 inode_set_atime_to_ts(inode, hfsp_mt2ut(folder->access_date)); 626 inode_set_mtime_to_ts(inode, 627 hfsp_mt2ut(folder->content_mod_date)); 628 inode_set_ctime_to_ts(inode, 629 hfsp_mt2ut(folder->attribute_mod_date)); 630 HFSPLUS_I(inode)->create_date = folder->create_date; 631 HFSPLUS_I(inode)->fs_blocks = 0; 632 if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) { 633 HFSPLUS_I(inode)->subfolders = 634 be32_to_cpu(folder->subfolders); 635 } 636 inode->i_op = &hfsplus_dir_inode_operations; 637 inode->i_fop = &hfsplus_dir_operations; 638 } else if (type == HFSPLUS_FILE) { 639 struct hfsplus_cat_file *file = &entry.file; 640 641 if (fd->entrylength < sizeof(struct hfsplus_cat_file)) { 642 pr_err("bad catalog file entry\n"); 643 res = -EIO; 644 goto out; 645 } 646 hfs_bnode_read(fd->bnode, &entry, fd->entryoffset, 647 sizeof(struct hfsplus_cat_file)); 648 649 hfsplus_inode_read_fork(inode, HFSPLUS_IS_RSRC(inode) ? 650 &file->rsrc_fork : &file->data_fork); 651 res = hfsplus_get_perms(inode, &file->permissions, 0); 652 if (res) 653 goto out; 654 set_nlink(inode, 1); 655 if (S_ISREG(inode->i_mode)) { 656 if (file->permissions.dev) 657 set_nlink(inode, 658 be32_to_cpu(file->permissions.dev)); 659 inode->i_op = &hfsplus_file_inode_operations; 660 inode->i_fop = &hfsplus_file_operations; 661 inode->i_mapping->a_ops = &hfsplus_aops; 662 } else if (S_ISLNK(inode->i_mode)) { 663 inode->i_op = &hfsplus_symlink_inode_operations; 664 inode_nohighmem(inode); 665 inode->i_mapping->a_ops = &hfsplus_aops; 666 } else { 667 inode->i_op = &hfsplus_special_inode_operations; 668 init_special_inode(inode, inode->i_mode, 669 be32_to_cpu(file->permissions.dev)); 670 } 671 inode_set_atime_to_ts(inode, hfsp_mt2ut(file->access_date)); 672 inode_set_mtime_to_ts(inode, 673 hfsp_mt2ut(file->content_mod_date)); 674 inode_set_ctime_to_ts(inode, 675 hfsp_mt2ut(file->attribute_mod_date)); 676 HFSPLUS_I(inode)->create_date = file->create_date; 677 } else { 678 pr_err("bad catalog entry used to create inode\n"); 679 res = -EIO; 680 } 681 out: 682 return res; 683 } 684 685 int hfsplus_cat_write_inode(struct inode *inode) 686 { 687 struct inode *main_inode = inode; 688 struct hfs_btree *tree = HFSPLUS_SB(inode->i_sb)->cat_tree; 689 struct hfs_find_data fd; 690 hfsplus_cat_entry entry; 691 int res = 0; 692 693 hfs_dbg("inode->i_ino %llu\n", inode->i_ino); 694 695 if (HFSPLUS_IS_RSRC(inode)) 696 main_inode = HFSPLUS_I(inode)->rsrc_inode; 697 698 if (!main_inode->i_nlink) 699 return 0; 700 701 if (hfs_find_init(tree, &fd)) 702 /* panic? */ 703 return -EIO; 704 705 if (hfsplus_find_cat(main_inode->i_sb, main_inode->i_ino, &fd)) 706 /* panic? */ 707 goto out; 708 709 if (S_ISDIR(main_inode->i_mode)) { 710 struct hfsplus_cat_folder *folder = &entry.folder; 711 712 if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) { 713 pr_err("bad catalog folder entry\n"); 714 res = -EIO; 715 goto out; 716 } 717 hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, 718 sizeof(struct hfsplus_cat_folder)); 719 /* simple node checks? */ 720 hfsplus_cat_set_perms(inode, &folder->permissions); 721 folder->access_date = hfsp_ut2mt(inode_get_atime(inode)); 722 folder->content_mod_date = hfsp_ut2mt(inode_get_mtime(inode)); 723 folder->attribute_mod_date = hfsp_ut2mt(inode_get_ctime(inode)); 724 folder->valence = cpu_to_be32(inode->i_size - 2); 725 if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) { 726 folder->subfolders = 727 cpu_to_be32(HFSPLUS_I(inode)->subfolders); 728 } 729 hfs_bnode_write(fd.bnode, &entry, fd.entryoffset, 730 sizeof(struct hfsplus_cat_folder)); 731 } else if (HFSPLUS_IS_RSRC(inode)) { 732 struct hfsplus_cat_file *file = &entry.file; 733 hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, 734 sizeof(struct hfsplus_cat_file)); 735 hfsplus_inode_write_fork(inode, &file->rsrc_fork); 736 hfs_bnode_write(fd.bnode, &entry, fd.entryoffset, 737 sizeof(struct hfsplus_cat_file)); 738 } else { 739 struct hfsplus_cat_file *file = &entry.file; 740 741 if (fd.entrylength < sizeof(struct hfsplus_cat_file)) { 742 pr_err("bad catalog file entry\n"); 743 res = -EIO; 744 goto out; 745 } 746 hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, 747 sizeof(struct hfsplus_cat_file)); 748 hfsplus_inode_write_fork(inode, &file->data_fork); 749 hfsplus_cat_set_perms(inode, &file->permissions); 750 if (HFSPLUS_FLG_IMMUTABLE & 751 (file->permissions.rootflags | 752 file->permissions.userflags)) 753 file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED); 754 else 755 file->flags &= cpu_to_be16(~HFSPLUS_FILE_LOCKED); 756 file->access_date = hfsp_ut2mt(inode_get_atime(inode)); 757 file->content_mod_date = hfsp_ut2mt(inode_get_mtime(inode)); 758 file->attribute_mod_date = hfsp_ut2mt(inode_get_ctime(inode)); 759 hfs_bnode_write(fd.bnode, &entry, fd.entryoffset, 760 sizeof(struct hfsplus_cat_file)); 761 } 762 763 res = hfs_btree_write(tree); 764 if (res) { 765 pr_err("b-tree write err: %d, ino %llu\n", 766 res, inode->i_ino); 767 goto out; 768 } 769 770 set_bit(HFSPLUS_I_CAT_DIRTY, 771 &HFSPLUS_I(HFSPLUS_CAT_TREE_I(inode->i_sb))->flags); 772 set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags); 773 out: 774 hfs_find_exit(&fd); 775 776 return res; 777 } 778 779 int hfsplus_fileattr_get(struct dentry *dentry, struct file_kattr *fa) 780 { 781 struct inode *inode = d_inode(dentry); 782 struct hfsplus_inode_info *hip = HFSPLUS_I(inode); 783 struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); 784 unsigned int flags = 0; 785 786 if (inode->i_flags & S_IMMUTABLE) 787 flags |= FS_IMMUTABLE_FL; 788 if (inode->i_flags & S_APPEND) 789 flags |= FS_APPEND_FL; 790 if (hip->userflags & HFSPLUS_FLG_NODUMP) 791 flags |= FS_NODUMP_FL; 792 if (test_bit(HFSPLUS_SB_CASEFOLD, &sbi->flags)) 793 flags |= FS_CASEFOLD_FL; 794 795 fileattr_fill_flags(fa, flags); 796 797 return 0; 798 } 799 800 int hfsplus_fileattr_set(struct mnt_idmap *idmap, 801 struct dentry *dentry, struct file_kattr *fa) 802 { 803 struct inode *inode = d_inode(dentry); 804 struct hfsplus_inode_info *hip = HFSPLUS_I(inode); 805 struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); 806 unsigned int allowed = FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL; 807 unsigned int new_fl = 0; 808 809 if (fileattr_has_fsx(fa)) 810 return -EOPNOTSUPP; 811 812 /* 813 * FS_CASEFOLD_FL reflects HFSPLUS_SB_CASEFOLD, a mount-time 814 * property. Accept it as a no-op so chattr's RMW round-trip 815 * succeeds; reject any attempt to enable it on a volume that 816 * was not formatted case-insensitive. 817 */ 818 if (test_bit(HFSPLUS_SB_CASEFOLD, &sbi->flags)) 819 allowed |= FS_CASEFOLD_FL; 820 821 /* don't silently ignore unsupported ext2 flags */ 822 if (fa->flags & ~allowed) 823 return -EOPNOTSUPP; 824 825 if (fa->flags & FS_IMMUTABLE_FL) 826 new_fl |= S_IMMUTABLE; 827 828 if (fa->flags & FS_APPEND_FL) 829 new_fl |= S_APPEND; 830 831 inode_set_flags(inode, new_fl, S_IMMUTABLE | S_APPEND); 832 833 if (fa->flags & FS_NODUMP_FL) 834 hip->userflags |= HFSPLUS_FLG_NODUMP; 835 else 836 hip->userflags &= ~HFSPLUS_FLG_NODUMP; 837 838 inode_set_ctime_current(inode); 839 mark_inode_dirty(inode); 840 841 return 0; 842 } 843