b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * linux/fs/hfsplus/inode.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * Copyright (C) 2001
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) * Brad Boyer (flar@allandria.com)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) * (C) 2003 Ardis Technologies <roman@ardistech.com>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) * Inode handling routines
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11)
34a2d313c51f4 (Christoph Hellwig 2010-11-23 14:38:21 +0100 12) #include <linux/blkdev.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13) #include <linux/mm.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) #include <linux/fs.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 15) #include <linux/pagemap.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 16) #include <linux/mpage.h>
e8edc6e03a5c8 (Alexey Dobriyan 2007-05-21 01:22:52 +0400 17) #include <linux/sched.h>
5b825c3af1d8a (Ingo Molnar 2017-02-02 17:54:15 +0100 18) #include <linux/cred.h>
e2e40f2c1ed43 (Christoph Hellwig 2015-02-22 08:58:50 -0800 19) #include <linux/uio.h>
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 20) #include <linux/fileattr.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 21)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 22) #include "hfsplus_fs.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 23) #include "hfsplus_raw.h"
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800 24) #include "xattr.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 25)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 26) static int hfsplus_readpage(struct file *file, struct page *page)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 27) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 28) return block_read_full_page(page, hfsplus_get_block);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 29) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 30)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 31) static int hfsplus_writepage(struct page *page, struct writeback_control *wbc)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 32) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 33) return block_write_full_page(page, hfsplus_get_block, wbc);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 34) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 35)
d506848567b52 (Marco Stornelli 2012-12-15 11:55:07 +0100 36) static void hfsplus_write_failed(struct address_space *mapping, loff_t to)
d506848567b52 (Marco Stornelli 2012-12-15 11:55:07 +0100 37) {
d506848567b52 (Marco Stornelli 2012-12-15 11:55:07 +0100 38) struct inode *inode = mapping->host;
d506848567b52 (Marco Stornelli 2012-12-15 11:55:07 +0100 39)
d506848567b52 (Marco Stornelli 2012-12-15 11:55:07 +0100 40) if (to > inode->i_size) {
7caef26767c17 (Kirill A. Shutemov 2013-09-12 15:13:56 -0700 41) truncate_pagecache(inode, inode->i_size);
d506848567b52 (Marco Stornelli 2012-12-15 11:55:07 +0100 42) hfsplus_file_truncate(inode);
d506848567b52 (Marco Stornelli 2012-12-15 11:55:07 +0100 43) }
d506848567b52 (Marco Stornelli 2012-12-15 11:55:07 +0100 44) }
d506848567b52 (Marco Stornelli 2012-12-15 11:55:07 +0100 45)
7c0efc627738c (Nicholas Piggin 2007-10-16 01:25:09 -0700 46) static int hfsplus_write_begin(struct file *file, struct address_space *mapping,
7c0efc627738c (Nicholas Piggin 2007-10-16 01:25:09 -0700 47) loff_t pos, unsigned len, unsigned flags,
7c0efc627738c (Nicholas Piggin 2007-10-16 01:25:09 -0700 48) struct page **pagep, void **fsdata)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 49) {
282dc17884988 (Christoph Hellwig 2010-06-04 11:29:55 +0200 50) int ret;
282dc17884988 (Christoph Hellwig 2010-06-04 11:29:55 +0200 51)
7c0efc627738c (Nicholas Piggin 2007-10-16 01:25:09 -0700 52) *pagep = NULL;
282dc17884988 (Christoph Hellwig 2010-06-04 11:29:55 +0200 53) ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
7c0efc627738c (Nicholas Piggin 2007-10-16 01:25:09 -0700 54) hfsplus_get_block,
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 55) &HFSPLUS_I(mapping->host)->phys_size);
d506848567b52 (Marco Stornelli 2012-12-15 11:55:07 +0100 56) if (unlikely(ret))
d506848567b52 (Marco Stornelli 2012-12-15 11:55:07 +0100 57) hfsplus_write_failed(mapping, pos + len);
282dc17884988 (Christoph Hellwig 2010-06-04 11:29:55 +0200 58)
282dc17884988 (Christoph Hellwig 2010-06-04 11:29:55 +0200 59) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 60) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 61)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 62) static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 63) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 64) return generic_block_bmap(mapping, block, hfsplus_get_block);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 65) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 66)
27496a8c67bef (Al Viro 2005-10-21 03:20:48 -0400 67) static int hfsplus_releasepage(struct page *page, gfp_t mask)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 68) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 69) struct inode *inode = page->mapping->host;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 70) struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 71) struct hfs_btree *tree;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 72) struct hfs_bnode *node;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 73) u32 nidx;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 74) int i, res = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 75)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 76) switch (inode->i_ino) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 77) case HFSPLUS_EXT_CNID:
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 78) tree = HFSPLUS_SB(sb)->ext_tree;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 79) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 80) case HFSPLUS_CAT_CNID:
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 81) tree = HFSPLUS_SB(sb)->cat_tree;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 82) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 83) case HFSPLUS_ATTR_CNID:
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 84) tree = HFSPLUS_SB(sb)->attr_tree;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 85) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 86) default:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 87) BUG();
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 88) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 89) }
706322496b3a5 (Eric Sesterhenn 2008-05-12 14:02:21 -0700 90) if (!tree)
706322496b3a5 (Eric Sesterhenn 2008-05-12 14:02:21 -0700 91) return 0;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 92) if (tree->node_size >= PAGE_SIZE) {
2753cc281c9a0 (Anton Salikhmetov 2010-12-16 18:08:38 +0200 93) nidx = page->index >>
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 94) (tree->node_size_shift - PAGE_SHIFT);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 95) spin_lock(&tree->hash_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 96) node = hfs_bnode_findhash(tree, nidx);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 97) if (!node)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 98) ;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 99) else if (atomic_read(&node->refcnt))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 100) res = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 101) if (res && node) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 102) hfs_bnode_unhash(node);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 103) hfs_bnode_free(node);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 104) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 105) spin_unlock(&tree->hash_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 106) } else {
2753cc281c9a0 (Anton Salikhmetov 2010-12-16 18:08:38 +0200 107) nidx = page->index <<
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 108) (PAGE_SHIFT - tree->node_size_shift);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 109) i = 1 << (PAGE_SHIFT - tree->node_size_shift);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 110) spin_lock(&tree->hash_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 111) do {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 112) node = hfs_bnode_findhash(tree, nidx++);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 113) if (!node)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 114) continue;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 115) if (atomic_read(&node->refcnt)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 116) res = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 117) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 118) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 119) hfs_bnode_unhash(node);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 120) hfs_bnode_free(node);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 121) } while (--i && nidx < tree->node_count);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 122) spin_unlock(&tree->hash_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 123) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 124) return res ? try_to_free_buffers(page) : 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 125) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 126)
c8b8e32d700fe (Christoph Hellwig 2016-04-07 08:51:58 -0700 127) static ssize_t hfsplus_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 128) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 129) struct file *file = iocb->ki_filp;
d506848567b52 (Marco Stornelli 2012-12-15 11:55:07 +0100 130) struct address_space *mapping = file->f_mapping;
93c76a3d437ff (Al Viro 2015-12-04 23:45:44 -0500 131) struct inode *inode = mapping->host;
a6cbcd4a4a85e (Al Viro 2014-03-04 22:38:00 -0500 132) size_t count = iov_iter_count(iter);
eafdc7d190a94 (Christoph Hellwig 2010-06-04 11:29:53 +0200 133) ssize_t ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 134)
c8b8e32d700fe (Christoph Hellwig 2016-04-07 08:51:58 -0700 135) ret = blockdev_direct_IO(iocb, inode, iter, hfsplus_get_block);
eafdc7d190a94 (Christoph Hellwig 2010-06-04 11:29:53 +0200 136)
eafdc7d190a94 (Christoph Hellwig 2010-06-04 11:29:53 +0200 137) /*
eafdc7d190a94 (Christoph Hellwig 2010-06-04 11:29:53 +0200 138) * In case of error extending write may have instantiated a few
eafdc7d190a94 (Christoph Hellwig 2010-06-04 11:29:53 +0200 139) * blocks outside i_size. Trim these off again.
eafdc7d190a94 (Christoph Hellwig 2010-06-04 11:29:53 +0200 140) */
6f67376318abe (Omar Sandoval 2015-03-16 04:33:52 -0700 141) if (unlikely(iov_iter_rw(iter) == WRITE && ret < 0)) {
eafdc7d190a94 (Christoph Hellwig 2010-06-04 11:29:53 +0200 142) loff_t isize = i_size_read(inode);
c8b8e32d700fe (Christoph Hellwig 2016-04-07 08:51:58 -0700 143) loff_t end = iocb->ki_pos + count;
eafdc7d190a94 (Christoph Hellwig 2010-06-04 11:29:53 +0200 144)
eafdc7d190a94 (Christoph Hellwig 2010-06-04 11:29:53 +0200 145) if (end > isize)
d506848567b52 (Marco Stornelli 2012-12-15 11:55:07 +0100 146) hfsplus_write_failed(mapping, end);
eafdc7d190a94 (Christoph Hellwig 2010-06-04 11:29:53 +0200 147) }
eafdc7d190a94 (Christoph Hellwig 2010-06-04 11:29:53 +0200 148)
eafdc7d190a94 (Christoph Hellwig 2010-06-04 11:29:53 +0200 149) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 150) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 151)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 152) static int hfsplus_writepages(struct address_space *mapping,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 153) struct writeback_control *wbc)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 154) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 155) return mpage_writepages(mapping, wbc, hfsplus_get_block);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 156) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 157)
f5e54d6e53a20 (Christoph Hellwig 2006-06-28 04:26:44 -0700 158) const struct address_space_operations hfsplus_btree_aops = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 159) .readpage = hfsplus_readpage,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 160) .writepage = hfsplus_writepage,
7c0efc627738c (Nicholas Piggin 2007-10-16 01:25:09 -0700 161) .write_begin = hfsplus_write_begin,
7c0efc627738c (Nicholas Piggin 2007-10-16 01:25:09 -0700 162) .write_end = generic_write_end,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 163) .bmap = hfsplus_bmap,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 164) .releasepage = hfsplus_releasepage,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 165) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 166)
f5e54d6e53a20 (Christoph Hellwig 2006-06-28 04:26:44 -0700 167) const struct address_space_operations hfsplus_aops = {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 168) .readpage = hfsplus_readpage,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 169) .writepage = hfsplus_writepage,
7c0efc627738c (Nicholas Piggin 2007-10-16 01:25:09 -0700 170) .write_begin = hfsplus_write_begin,
7c0efc627738c (Nicholas Piggin 2007-10-16 01:25:09 -0700 171) .write_end = generic_write_end,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 172) .bmap = hfsplus_bmap,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 173) .direct_IO = hfsplus_direct_IO,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 174) .writepages = hfsplus_writepages,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 175) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 176)
e16404ed0f3f3 (Al Viro 2009-02-20 05:55:13 +0000 177) const struct dentry_operations hfsplus_dentry_operations = {
d45bce8faf555 (Duane Griffin 2007-07-15 23:41:23 -0700 178) .d_hash = hfsplus_hash_dentry,
d45bce8faf555 (Duane Griffin 2007-07-15 23:41:23 -0700 179) .d_compare = hfsplus_compare_dentry,
d45bce8faf555 (Duane Griffin 2007-07-15 23:41:23 -0700 180) };
d45bce8faf555 (Duane Griffin 2007-07-15 23:41:23 -0700 181)
2753cc281c9a0 (Anton Salikhmetov 2010-12-16 18:08:38 +0200 182) static void hfsplus_get_perms(struct inode *inode,
2753cc281c9a0 (Anton Salikhmetov 2010-12-16 18:08:38 +0200 183) struct hfsplus_perm *perms, int dir)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 184) {
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 185) struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 186) u16 mode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 187)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 188) mode = be16_to_cpu(perms->mode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 189)
16525e3f146fb (Eric W. Biederman 2012-02-07 16:27:17 -0800 190) i_uid_write(inode, be32_to_cpu(perms->owner));
16525e3f146fb (Eric W. Biederman 2012-02-07 16:27:17 -0800 191) if (!i_uid_read(inode) && !mode)
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 192) inode->i_uid = sbi->uid;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 193)
16525e3f146fb (Eric W. Biederman 2012-02-07 16:27:17 -0800 194) i_gid_write(inode, be32_to_cpu(perms->group));
16525e3f146fb (Eric W. Biederman 2012-02-07 16:27:17 -0800 195) if (!i_gid_read(inode) && !mode)
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 196) inode->i_gid = sbi->gid;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 197)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 198) if (dir) {
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 199) mode = mode ? (mode & S_IALLUGO) : (S_IRWXUGO & ~(sbi->umask));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 200) mode |= S_IFDIR;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 201) } else if (!mode)
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 202) mode = S_IFREG | ((S_IRUGO|S_IWUGO) & ~(sbi->umask));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 203) inode->i_mode = mode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 204)
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 205) HFSPLUS_I(inode)->userflags = perms->userflags;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 206) if (perms->rootflags & HFSPLUS_FLG_IMMUTABLE)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 207) inode->i_flags |= S_IMMUTABLE;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 208) else
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 209) inode->i_flags &= ~S_IMMUTABLE;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 210) if (perms->rootflags & HFSPLUS_FLG_APPEND)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 211) inode->i_flags |= S_APPEND;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 212) else
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 213) inode->i_flags &= ~S_APPEND;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 214) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 215)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 216) static int hfsplus_file_open(struct inode *inode, struct file *file)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 217) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 218) if (HFSPLUS_IS_RSRC(inode))
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 219) inode = HFSPLUS_I(inode)->rsrc_inode;
6e7152944426b (Alan Cox 2008-10-18 20:28:01 -0700 220) if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
6e7152944426b (Alan Cox 2008-10-18 20:28:01 -0700 221) return -EOVERFLOW;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 222) atomic_inc(&HFSPLUS_I(inode)->opencnt);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 223) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 224) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 225)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 226) static int hfsplus_file_release(struct inode *inode, struct file *file)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 227) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 228) struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 229)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 230) if (HFSPLUS_IS_RSRC(inode))
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 231) inode = HFSPLUS_I(inode)->rsrc_inode;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 232) if (atomic_dec_and_test(&HFSPLUS_I(inode)->opencnt)) {
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 233) inode_lock(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 234) hfsplus_file_truncate(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 235) if (inode->i_flags & S_DEAD) {
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 236) hfsplus_delete_cat(inode->i_ino,
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 237) HFSPLUS_SB(sb)->hidden_dir, NULL);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 238) hfsplus_delete_inode(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 239) }
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 240) inode_unlock(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 241) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 242) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 243) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 244)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 245) static int hfsplus_setattr(struct user_namespace *mnt_userns,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 246) struct dentry *dentry, struct iattr *attr)
d39aae9ec447d (Christoph Hellwig 2010-06-04 11:29:59 +0200 247) {
2b0143b5c986b (David Howells 2015-03-17 22:25:59 +0000 248) struct inode *inode = d_inode(dentry);
d39aae9ec447d (Christoph Hellwig 2010-06-04 11:29:59 +0200 249) int error;
d39aae9ec447d (Christoph Hellwig 2010-06-04 11:29:59 +0200 250)
2f221d6f7b881 (Christian Brauner 2021-01-21 14:19:26 +0100 251) error = setattr_prepare(&init_user_ns, dentry, attr);
d39aae9ec447d (Christoph Hellwig 2010-06-04 11:29:59 +0200 252) if (error)
d39aae9ec447d (Christoph Hellwig 2010-06-04 11:29:59 +0200 253) return error;
1025774ce411f (Christoph Hellwig 2010-06-04 11:30:02 +0200 254)
1025774ce411f (Christoph Hellwig 2010-06-04 11:30:02 +0200 255) if ((attr->ia_valid & ATTR_SIZE) &&
1025774ce411f (Christoph Hellwig 2010-06-04 11:30:02 +0200 256) attr->ia_size != i_size_read(inode)) {
562c72aa57c36 (Christoph Hellwig 2011-06-24 14:29:45 -0400 257) inode_dio_wait(inode);
059a704c43ea8 (Sergei Antonov 2015-04-16 12:47:15 -0700 258) if (attr->ia_size > inode->i_size) {
059a704c43ea8 (Sergei Antonov 2015-04-16 12:47:15 -0700 259) error = generic_cont_expand_simple(inode,
059a704c43ea8 (Sergei Antonov 2015-04-16 12:47:15 -0700 260) attr->ia_size);
059a704c43ea8 (Sergei Antonov 2015-04-16 12:47:15 -0700 261) if (error)
059a704c43ea8 (Sergei Antonov 2015-04-16 12:47:15 -0700 262) return error;
059a704c43ea8 (Sergei Antonov 2015-04-16 12:47:15 -0700 263) }
d506848567b52 (Marco Stornelli 2012-12-15 11:55:07 +0100 264) truncate_setsize(inode, attr->ia_size);
d506848567b52 (Marco Stornelli 2012-12-15 11:55:07 +0100 265) hfsplus_file_truncate(inode);
dc8844aada735 (Ernesto A. Fernández 2018-10-30 15:06:27 -0700 266) inode->i_mtime = inode->i_ctime = current_time(inode);
1025774ce411f (Christoph Hellwig 2010-06-04 11:30:02 +0200 267) }
1025774ce411f (Christoph Hellwig 2010-06-04 11:30:02 +0200 268)
2f221d6f7b881 (Christian Brauner 2021-01-21 14:19:26 +0100 269) setattr_copy(&init_user_ns, inode, attr);
1025774ce411f (Christoph Hellwig 2010-06-04 11:30:02 +0200 270) mark_inode_dirty(inode);
b4c1107cc9626 (Vyacheslav Dubeyko 2013-09-11 14:24:30 -0700 271)
1025774ce411f (Christoph Hellwig 2010-06-04 11:30:02 +0200 272) return 0;
d39aae9ec447d (Christoph Hellwig 2010-06-04 11:29:59 +0200 273) }
d39aae9ec447d (Christoph Hellwig 2010-06-04 11:29:59 +0200 274)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 275) int hfsplus_getattr(struct user_namespace *mnt_userns, const struct path *path,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 276) struct kstat *stat, u32 request_mask,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 277) unsigned int query_flags)
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 278) {
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 279) struct inode *inode = d_inode(path->dentry);
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 280) struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 281)
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 282) if (inode->i_flags & S_APPEND)
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 283) stat->attributes |= STATX_ATTR_APPEND;
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 284) if (inode->i_flags & S_IMMUTABLE)
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 285) stat->attributes |= STATX_ATTR_IMMUTABLE;
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 286) if (hip->userflags & HFSPLUS_FLG_NODUMP)
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 287) stat->attributes |= STATX_ATTR_NODUMP;
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 288)
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 289) stat->attributes_mask |= STATX_ATTR_APPEND | STATX_ATTR_IMMUTABLE |
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 290) STATX_ATTR_NODUMP;
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 291)
0d56a4518d5ea (Christian Brauner 2021-01-21 14:19:30 +0100 292) generic_fillattr(&init_user_ns, inode, stat);
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 293) return 0;
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 294) }
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 295)
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 296) int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 297) int datasync)
b5fc510c48f63 (Al Viro 2010-07-04 12:24:09 +0400 298) {
281469766bdde (Christoph Hellwig 2010-11-23 14:38:06 +0100 299) struct inode *inode = file->f_mapping->host;
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 300) struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
281469766bdde (Christoph Hellwig 2010-11-23 14:38:06 +0100 301) struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 302) int error = 0, error2;
b5fc510c48f63 (Al Viro 2010-07-04 12:24:09 +0400 303)
3b49c9a1e984b (Jeff Layton 2017-07-07 15:20:52 -0400 304) error = file_write_and_wait_range(file, start, end);
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 305) if (error)
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 306) return error;
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 307) inode_lock(inode);
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 308)
281469766bdde (Christoph Hellwig 2010-11-23 14:38:06 +0100 309) /*
281469766bdde (Christoph Hellwig 2010-11-23 14:38:06 +0100 310) * Sync inode metadata into the catalog and extent trees.
281469766bdde (Christoph Hellwig 2010-11-23 14:38:06 +0100 311) */
281469766bdde (Christoph Hellwig 2010-11-23 14:38:06 +0100 312) sync_inode_metadata(inode, 1);
281469766bdde (Christoph Hellwig 2010-11-23 14:38:06 +0100 313)
281469766bdde (Christoph Hellwig 2010-11-23 14:38:06 +0100 314) /*
281469766bdde (Christoph Hellwig 2010-11-23 14:38:06 +0100 315) * And explicitly write out the btrees.
281469766bdde (Christoph Hellwig 2010-11-23 14:38:06 +0100 316) */
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 317) if (test_and_clear_bit(HFSPLUS_I_CAT_DIRTY, &hip->flags))
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 318) error = filemap_write_and_wait(sbi->cat_tree->inode->i_mapping);
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 319)
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 320) if (test_and_clear_bit(HFSPLUS_I_EXT_DIRTY, &hip->flags)) {
2753cc281c9a0 (Anton Salikhmetov 2010-12-16 18:08:38 +0200 321) error2 =
2753cc281c9a0 (Anton Salikhmetov 2010-12-16 18:08:38 +0200 322) filemap_write_and_wait(sbi->ext_tree->inode->i_mapping);
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 323) if (!error)
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 324) error = error2;
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 325) }
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 326)
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800 327) if (test_and_clear_bit(HFSPLUS_I_ATTR_DIRTY, &hip->flags)) {
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800 328) if (sbi->attr_tree) {
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800 329) error2 =
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800 330) filemap_write_and_wait(
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800 331) sbi->attr_tree->inode->i_mapping);
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800 332) if (!error)
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800 333) error = error2;
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800 334) } else {
d614267329f2b (Joe Perches 2013-04-30 15:27:55 -0700 335) pr_err("sync non-existent attributes tree\n");
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800 336) }
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800 337) }
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800 338)
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 339) if (test_and_clear_bit(HFSPLUS_I_ALLOC_DIRTY, &hip->flags)) {
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 340) error2 = filemap_write_and_wait(sbi->alloc_file->i_mapping);
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 341) if (!error)
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 342) error = error2;
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 343) }
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 344)
34a2d313c51f4 (Christoph Hellwig 2010-11-23 14:38:21 +0100 345) if (!test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
c6bf3f0e25f4c (Christoph Hellwig 2021-01-26 15:52:35 +0100 346) blkdev_issue_flush(inode->i_sb->s_bdev);
34a2d313c51f4 (Christoph Hellwig 2010-11-23 14:38:21 +0100 347)
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 348) inode_unlock(inode);
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 349)
281469766bdde (Christoph Hellwig 2010-11-23 14:38:06 +0100 350) return error;
b5fc510c48f63 (Al Viro 2010-07-04 12:24:09 +0400 351) }
b5fc510c48f63 (Al Viro 2010-07-04 12:24:09 +0400 352)
92e1d5be91a0e (Arjan van de Ven 2007-02-12 00:55:39 -0800 353) static const struct inode_operations hfsplus_file_inode_operations = {
d39aae9ec447d (Christoph Hellwig 2010-06-04 11:29:59 +0200 354) .setattr = hfsplus_setattr,
f93ca1ed9ba09 (Ernesto A. Fernández 2019-01-03 15:27:46 -0800 355) .getattr = hfsplus_getattr,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 356) .listxattr = hfsplus_listxattr,
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 357) .fileattr_get = hfsplus_fileattr_get,
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 358) .fileattr_set = hfsplus_fileattr_set,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 359) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 360)
4b6f5d20b04dc (Arjan van de Ven 2006-03-28 01:56:42 -0800 361) static const struct file_operations hfsplus_file_operations = {
20b7643d8ee44 (Anton Salikhmetov 2010-12-16 18:08:40 +0200 362) .llseek = generic_file_llseek,
aad4f8bb42af0 (Al Viro 2014-04-02 14:33:16 -0400 363) .read_iter = generic_file_read_iter,
8174202b34c30 (Al Viro 2014-04-03 03:17:43 -0400 364) .write_iter = generic_file_write_iter,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 365) .mmap = generic_file_mmap,
5ffc4ef45b3b0 (Jens Axboe 2007-06-01 11:49:19 +0200 366) .splice_read = generic_file_splice_read,
b5fc510c48f63 (Al Viro 2010-07-04 12:24:09 +0400 367) .fsync = hfsplus_file_fsync,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 368) .open = hfsplus_file_open,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 369) .release = hfsplus_file_release,
7cc4bcc6f152d (Arnd Bergmann 2010-04-27 16:24:20 +0200 370) .unlocked_ioctl = hfsplus_ioctl,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 371) };
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 372)
b0cd38c7f54c9 (Ernesto A. Fernandez 2018-02-06 15:49:02 -0800 373) struct inode *hfsplus_new_inode(struct super_block *sb, struct inode *dir,
b0cd38c7f54c9 (Ernesto A. Fernandez 2018-02-06 15:49:02 -0800 374) umode_t mode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 375) {
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 376) struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 377) struct inode *inode = new_inode(sb);
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 378) struct hfsplus_inode_info *hip;
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 379)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 380) if (!inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 381) return NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 382)
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 383) inode->i_ino = sbi->next_cnid++;
21cb47be6fb9e (Christian Brauner 2021-01-21 14:19:25 +0100 384) inode_init_owner(&init_user_ns, inode, dir, mode);
bfe8684869601 (Miklos Szeredi 2011-10-28 14:13:29 +0200 385) set_nlink(inode, 1);
02027d42c3f74 (Deepa Dinamani 2016-09-14 07:48:05 -0700 386) inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 387)
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 388) hip = HFSPLUS_I(inode);
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 389) INIT_LIST_HEAD(&hip->open_dir_list);
323ee8fc544d4 (Al Viro 2016-05-12 20:02:09 -0400 390) spin_lock_init(&hip->open_dir_lock);
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 391) mutex_init(&hip->extents_lock);
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 392) atomic_set(&hip->opencnt, 0);
b33b7921db14a (Christoph Hellwig 2010-11-23 14:38:13 +0100 393) hip->extent_state = 0;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 394) hip->flags = 0;
f3922382ce930 (Matthew Garrett 2012-03-13 12:10:34 -0400 395) hip->userflags = 0;
d7d673a591701 (Sergei Antonov 2014-03-10 15:49:51 -0700 396) hip->subfolders = 0;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 397) memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec));
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 398) memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 399) hip->alloc_blocks = 0;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 400) hip->first_blocks = 0;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 401) hip->cached_start = 0;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 402) hip->cached_blocks = 0;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 403) hip->phys_size = 0;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 404) hip->fs_blocks = 0;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 405) hip->rsrc_inode = NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 406) if (S_ISDIR(inode->i_mode)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 407) inode->i_size = 2;
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 408) sbi->folder_count++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 409) inode->i_op = &hfsplus_dir_inode_operations;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 410) inode->i_fop = &hfsplus_dir_operations;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 411) } else if (S_ISREG(inode->i_mode)) {
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 412) sbi->file_count++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 413) inode->i_op = &hfsplus_file_inode_operations;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 414) inode->i_fop = &hfsplus_file_operations;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 415) inode->i_mapping->a_ops = &hfsplus_aops;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 416) hip->clump_blocks = sbi->data_clump_blocks;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 417) } else if (S_ISLNK(inode->i_mode)) {
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 418) sbi->file_count++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 419) inode->i_op = &page_symlink_inode_operations;
21fc61c73c390 (Al Viro 2015-11-17 01:07:57 -0500 420) inode_nohighmem(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 421) inode->i_mapping->a_ops = &hfsplus_aops;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 422) hip->clump_blocks = 1;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 423) } else
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 424) sbi->file_count++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 425) insert_inode_hash(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 426) mark_inode_dirty(inode);
9e6c5829b07c9 (Artem Bityutskiy 2012-07-12 17:26:31 +0300 427) hfsplus_mark_mdb_dirty(sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 428)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 429) return inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 430) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 431)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 432) void hfsplus_delete_inode(struct inode *inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 433) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 434) struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 435)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 436) if (S_ISDIR(inode->i_mode)) {
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 437) HFSPLUS_SB(sb)->folder_count--;
9e6c5829b07c9 (Artem Bityutskiy 2012-07-12 17:26:31 +0300 438) hfsplus_mark_mdb_dirty(sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 439) return;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 440) }
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 441) HFSPLUS_SB(sb)->file_count--;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 442) if (S_ISREG(inode->i_mode)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 443) if (!inode->i_nlink) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 444) inode->i_size = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 445) hfsplus_file_truncate(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 446) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 447) } else if (S_ISLNK(inode->i_mode)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 448) inode->i_size = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 449) hfsplus_file_truncate(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 450) }
9e6c5829b07c9 (Artem Bityutskiy 2012-07-12 17:26:31 +0300 451) hfsplus_mark_mdb_dirty(sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 452) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 453)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 454) void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 455) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 456) struct super_block *sb = inode->i_sb;
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 457) struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 458) struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 459) u32 count;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 460) int i;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 461)
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 462) memcpy(&hip->first_extents, &fork->extents, sizeof(hfsplus_extent_rec));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 463) for (count = 0, i = 0; i < 8; i++)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 464) count += be32_to_cpu(fork->extents[i].block_count);
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 465) hip->first_blocks = count;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 466) memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 467) hip->cached_start = 0;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 468) hip->cached_blocks = 0;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 469)
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 470) hip->alloc_blocks = be32_to_cpu(fork->total_blocks);
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 471) hip->phys_size = inode->i_size = be64_to_cpu(fork->total_size);
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 472) hip->fs_blocks =
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 473) (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 474) inode_set_bytes(inode, hip->fs_blocks << sb->s_blocksize_bits);
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 475) hip->clump_blocks =
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 476) be32_to_cpu(fork->clump_size) >> sbi->alloc_blksz_shift;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 477) if (!hip->clump_blocks) {
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 478) hip->clump_blocks = HFSPLUS_IS_RSRC(inode) ?
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 479) sbi->rsrc_clump_blocks :
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 480) sbi->data_clump_blocks;
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 481) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 482) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 483)
2753cc281c9a0 (Anton Salikhmetov 2010-12-16 18:08:38 +0200 484) void hfsplus_inode_write_fork(struct inode *inode,
2753cc281c9a0 (Anton Salikhmetov 2010-12-16 18:08:38 +0200 485) struct hfsplus_fork_raw *fork)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 486) {
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 487) memcpy(&fork->extents, &HFSPLUS_I(inode)->first_extents,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 488) sizeof(hfsplus_extent_rec));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 489) fork->total_size = cpu_to_be64(inode->i_size);
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 490) fork->total_blocks = cpu_to_be32(HFSPLUS_I(inode)->alloc_blocks);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 491) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 492)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 493) int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 494) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 495) hfsplus_cat_entry entry;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 496) int res = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 497) u16 type;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 498)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 499) type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 500)
f6089ff87d309 (Christoph Hellwig 2010-10-14 09:54:28 -0400 501) HFSPLUS_I(inode)->linkid = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 502) if (type == HFSPLUS_FOLDER) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 503) struct hfsplus_cat_folder *folder = &entry.folder;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 504)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 505) if (fd->entrylength < sizeof(struct hfsplus_cat_folder))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 506) /* panic? */;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 507) hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 508) sizeof(struct hfsplus_cat_folder));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 509) hfsplus_get_perms(inode, &folder->permissions, 1);
bfe8684869601 (Miklos Szeredi 2011-10-28 14:13:29 +0200 510) set_nlink(inode, 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 511) inode->i_size = 2 + be32_to_cpu(folder->valence);
4ddfc3dc60a24 (Arnd Bergmann 2018-06-20 09:47:26 +0200 512) inode->i_atime = hfsp_mt2ut(folder->access_date);
4ddfc3dc60a24 (Arnd Bergmann 2018-06-20 09:47:26 +0200 513) inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
4ddfc3dc60a24 (Arnd Bergmann 2018-06-20 09:47:26 +0200 514) inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date);
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 515) HFSPLUS_I(inode)->create_date = folder->create_date;
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 516) HFSPLUS_I(inode)->fs_blocks = 0;
d7d673a591701 (Sergei Antonov 2014-03-10 15:49:51 -0700 517) if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) {
d7d673a591701 (Sergei Antonov 2014-03-10 15:49:51 -0700 518) HFSPLUS_I(inode)->subfolders =
d7d673a591701 (Sergei Antonov 2014-03-10 15:49:51 -0700 519) be32_to_cpu(folder->subfolders);
d7d673a591701 (Sergei Antonov 2014-03-10 15:49:51 -0700 520) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 521) inode->i_op = &hfsplus_dir_inode_operations;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 522) inode->i_fop = &hfsplus_dir_operations;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 523) } else if (type == HFSPLUS_FILE) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 524) struct hfsplus_cat_file *file = &entry.file;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 525)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 526) if (fd->entrylength < sizeof(struct hfsplus_cat_file))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 527) /* panic? */;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 528) hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 529) sizeof(struct hfsplus_cat_file));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 530)
b33b7921db14a (Christoph Hellwig 2010-11-23 14:38:13 +0100 531) hfsplus_inode_read_fork(inode, HFSPLUS_IS_RSRC(inode) ?
b33b7921db14a (Christoph Hellwig 2010-11-23 14:38:13 +0100 532) &file->rsrc_fork : &file->data_fork);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 533) hfsplus_get_perms(inode, &file->permissions, 0);
bfe8684869601 (Miklos Szeredi 2011-10-28 14:13:29 +0200 534) set_nlink(inode, 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 535) if (S_ISREG(inode->i_mode)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 536) if (file->permissions.dev)
bfe8684869601 (Miklos Szeredi 2011-10-28 14:13:29 +0200 537) set_nlink(inode,
bfe8684869601 (Miklos Szeredi 2011-10-28 14:13:29 +0200 538) be32_to_cpu(file->permissions.dev));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 539) inode->i_op = &hfsplus_file_inode_operations;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 540) inode->i_fop = &hfsplus_file_operations;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 541) inode->i_mapping->a_ops = &hfsplus_aops;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 542) } else if (S_ISLNK(inode->i_mode)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 543) inode->i_op = &page_symlink_inode_operations;
21fc61c73c390 (Al Viro 2015-11-17 01:07:57 -0500 544) inode_nohighmem(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 545) inode->i_mapping->a_ops = &hfsplus_aops;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 546) } else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 547) init_special_inode(inode, inode->i_mode,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 548) be32_to_cpu(file->permissions.dev));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 549) }
4ddfc3dc60a24 (Arnd Bergmann 2018-06-20 09:47:26 +0200 550) inode->i_atime = hfsp_mt2ut(file->access_date);
4ddfc3dc60a24 (Arnd Bergmann 2018-06-20 09:47:26 +0200 551) inode->i_mtime = hfsp_mt2ut(file->content_mod_date);
4ddfc3dc60a24 (Arnd Bergmann 2018-06-20 09:47:26 +0200 552) inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date);
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 553) HFSPLUS_I(inode)->create_date = file->create_date;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 554) } else {
d614267329f2b (Joe Perches 2013-04-30 15:27:55 -0700 555) pr_err("bad catalog entry used to create inode\n");
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 556) res = -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 557) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 558) return res;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 559) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 560)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 561) int hfsplus_cat_write_inode(struct inode *inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 562) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 563) struct inode *main_inode = inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 564) struct hfs_find_data fd;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 565) hfsplus_cat_entry entry;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 566)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 567) if (HFSPLUS_IS_RSRC(inode))
6af502de224c3 (Christoph Hellwig 2010-10-01 05:43:31 +0200 568) main_inode = HFSPLUS_I(inode)->rsrc_inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 569)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 570) if (!main_inode->i_nlink)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 571) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 572)
dd73a01a30d72 (Christoph Hellwig 2010-10-01 05:42:59 +0200 573) if (hfs_find_init(HFSPLUS_SB(main_inode->i_sb)->cat_tree, &fd))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 574) /* panic? */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 575) return -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 576)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 577) if (hfsplus_find_cat(main_inode->i_sb, main_inode->i_ino, &fd))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 578) /* panic? */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 579) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 580)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 581) if (S_ISDIR(main_inode->i_mode)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 582) struct hfsplus_cat_folder *folder = &entry.folder;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 583)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 584) if (fd.entrylength < sizeof(struct hfsplus_cat_folder))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 585) /* panic? */;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 586) hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 587) sizeof(struct hfsplus_cat_folder));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 588) /* simple node checks? */
90e616905a423 (Christoph Hellwig 2010-10-14 09:54:39 -0400 589) hfsplus_cat_set_perms(inode, &folder->permissions);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 590) folder->access_date = hfsp_ut2mt(inode->i_atime);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 591) folder->content_mod_date = hfsp_ut2mt(inode->i_mtime);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 592) folder->attribute_mod_date = hfsp_ut2mt(inode->i_ctime);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 593) folder->valence = cpu_to_be32(inode->i_size - 2);
d7d673a591701 (Sergei Antonov 2014-03-10 15:49:51 -0700 594) if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) {
d7d673a591701 (Sergei Antonov 2014-03-10 15:49:51 -0700 595) folder->subfolders =
d7d673a591701 (Sergei Antonov 2014-03-10 15:49:51 -0700 596) cpu_to_be32(HFSPLUS_I(inode)->subfolders);
d7d673a591701 (Sergei Antonov 2014-03-10 15:49:51 -0700 597) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 598) hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 599) sizeof(struct hfsplus_cat_folder));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 600) } else if (HFSPLUS_IS_RSRC(inode)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 601) struct hfsplus_cat_file *file = &entry.file;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 602) hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 603) sizeof(struct hfsplus_cat_file));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 604) hfsplus_inode_write_fork(inode, &file->rsrc_fork);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 605) hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 606) sizeof(struct hfsplus_cat_file));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 607) } else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 608) struct hfsplus_cat_file *file = &entry.file;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 609)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 610) if (fd.entrylength < sizeof(struct hfsplus_cat_file))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 611) /* panic? */;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 612) hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 613) sizeof(struct hfsplus_cat_file));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 614) hfsplus_inode_write_fork(inode, &file->data_fork);
90e616905a423 (Christoph Hellwig 2010-10-14 09:54:39 -0400 615) hfsplus_cat_set_perms(inode, &file->permissions);
2753cc281c9a0 (Anton Salikhmetov 2010-12-16 18:08:38 +0200 616) if (HFSPLUS_FLG_IMMUTABLE &
2753cc281c9a0 (Anton Salikhmetov 2010-12-16 18:08:38 +0200 617) (file->permissions.rootflags |
2753cc281c9a0 (Anton Salikhmetov 2010-12-16 18:08:38 +0200 618) file->permissions.userflags))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 619) file->flags |= cpu_to_be16(HFSPLUS_FILE_LOCKED);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 620) else
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 621) file->flags &= cpu_to_be16(~HFSPLUS_FILE_LOCKED);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 622) file->access_date = hfsp_ut2mt(inode->i_atime);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 623) file->content_mod_date = hfsp_ut2mt(inode->i_mtime);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 624) file->attribute_mod_date = hfsp_ut2mt(inode->i_ctime);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 625) hfs_bnode_write(fd.bnode, &entry, fd.entryoffset,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 626) sizeof(struct hfsplus_cat_file));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 627) }
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 628)
e34947056076c (Christoph Hellwig 2010-11-23 14:38:15 +0100 629) set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 630) out:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 631) hfs_find_exit(&fd);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 632) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 633) }
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 634)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 635) int hfsplus_fileattr_get(struct dentry *dentry, struct fileattr *fa)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 636) {
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 637) struct inode *inode = d_inode(dentry);
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 638) struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 639) unsigned int flags = 0;
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 640)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 641) if (inode->i_flags & S_IMMUTABLE)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 642) flags |= FS_IMMUTABLE_FL;
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 643) if (inode->i_flags & S_APPEND)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 644) flags |= FS_APPEND_FL;
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 645) if (hip->userflags & HFSPLUS_FLG_NODUMP)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 646) flags |= FS_NODUMP_FL;
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 647)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 648) fileattr_fill_flags(fa, flags);
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 649)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 650) return 0;
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 651) }
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 652)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 653) int hfsplus_fileattr_set(struct user_namespace *mnt_userns,
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 654) struct dentry *dentry, struct fileattr *fa)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 655) {
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 656) struct inode *inode = d_inode(dentry);
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 657) struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 658) unsigned int new_fl = 0;
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 659)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 660) if (fileattr_has_fsx(fa))
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 661) return -EOPNOTSUPP;
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 662)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 663) /* don't silently ignore unsupported ext2 flags */
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 664) if (fa->flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL))
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 665) return -EOPNOTSUPP;
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 666)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 667) if (fa->flags & FS_IMMUTABLE_FL)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 668) new_fl |= S_IMMUTABLE;
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 669)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 670) if (fa->flags & FS_APPEND_FL)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 671) new_fl |= S_APPEND;
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 672)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 673) inode_set_flags(inode, new_fl, S_IMMUTABLE | S_APPEND);
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 674)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 675) if (fa->flags & FS_NODUMP_FL)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 676) hip->userflags |= HFSPLUS_FLG_NODUMP;
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 677) else
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 678) hip->userflags &= ~HFSPLUS_FLG_NODUMP;
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 679)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 680) inode->i_ctime = current_time(inode);
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 681) mark_inode_dirty(inode);
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 682)
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 683) return 0;
9cbae74838e62 (Miklos Szeredi 2021-04-07 14:36:44 +0200 684) }