^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * linux/fs/hfs/catalog.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 1995-1997 Paul H. Hargrove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * (C) 2003 Ardis Technologies <roman@ardistech.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This file may be distributed under the terms of the GNU General Public License.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This file contains the functions related to the catalog B-tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Cache code shamelessly stolen from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * linux/fs/inode.c Copyright (C) 1991, 1992 Linus Torvalds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * re-shamelessly stolen Copyright (C) 1997 Linus Torvalds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "hfs_fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "btree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * hfs_cat_build_key()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Given the ID of the parent and the name build a search key.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) void hfs_cat_build_key(struct super_block *sb, btree_key *key, u32 parent, const struct qstr *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) key->cat.reserved = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) key->cat.ParID = cpu_to_be32(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) if (name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) hfs_asc2mac(sb, &key->cat.CName, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) key->key_len = 6 + key->cat.CName.len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) memset(&key->cat.CName, 0, sizeof(struct hfs_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) key->key_len = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static int hfs_cat_build_record(hfs_cat_rec *rec, u32 cnid, struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) __be32 mtime = hfs_mtime();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) memset(rec, 0, sizeof(*rec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (S_ISDIR(inode->i_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) rec->type = HFS_CDR_DIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) rec->dir.DirID = cpu_to_be32(cnid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) rec->dir.CrDat = mtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) rec->dir.MdDat = mtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) rec->dir.BkDat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) rec->dir.UsrInfo.frView = cpu_to_be16(0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return sizeof(struct hfs_cat_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* init some fields for the file record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) rec->type = HFS_CDR_FIL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) rec->file.Flags = HFS_FIL_USED | HFS_FIL_THD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (!(inode->i_mode & S_IWUSR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) rec->file.Flags |= HFS_FIL_LOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) rec->file.FlNum = cpu_to_be32(cnid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) rec->file.CrDat = mtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) rec->file.MdDat = mtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) rec->file.BkDat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) rec->file.UsrWds.fdType = HFS_SB(inode->i_sb)->s_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) rec->file.UsrWds.fdCreator = HFS_SB(inode->i_sb)->s_creator;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return sizeof(struct hfs_cat_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static int hfs_cat_build_thread(struct super_block *sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) hfs_cat_rec *rec, int type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) u32 parentid, const struct qstr *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) rec->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) memset(rec->thread.reserved, 0, sizeof(rec->thread.reserved));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) rec->thread.ParID = cpu_to_be32(parentid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) hfs_asc2mac(sb, &rec->thread.CName, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return sizeof(struct hfs_cat_thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * create_entry()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * Add a new file or directory to the catalog B-tree and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * return a (struct hfs_cat_entry) for it in '*result'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int hfs_cat_create(u32 cnid, struct inode *dir, const struct qstr *str, struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct hfs_find_data fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct super_block *sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) union hfs_cat_rec entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int entry_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) hfs_dbg(CAT_MOD, "create_cat: %s,%u(%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) str->name, cnid, inode->i_nlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (dir->i_size >= HFS_MAX_VALENCE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) sb = dir->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) err = hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * Fail early and avoid ENOSPC during the btree operations. We may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * have to split the root node at most once.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) err = hfs_bmap_reserve(fd.tree, 2 * fd.tree->depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) goto err2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) hfs_cat_build_key(sb, fd.search_key, cnid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) entry_size = hfs_cat_build_thread(sb, &entry, S_ISDIR(inode->i_mode) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) HFS_CDR_THD : HFS_CDR_FTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) dir->i_ino, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) err = hfs_brec_find(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (err != -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) err = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) goto err2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) err = hfs_brec_insert(&fd, &entry, entry_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) goto err2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) hfs_cat_build_key(sb, fd.search_key, dir->i_ino, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) entry_size = hfs_cat_build_record(&entry, cnid, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) err = hfs_brec_find(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (err != -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* panic? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) err = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) goto err1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) err = hfs_brec_insert(&fd, &entry, entry_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) goto err1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) dir->i_size++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) dir->i_mtime = dir->i_ctime = current_time(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) mark_inode_dirty(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) hfs_find_exit(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) err1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) hfs_cat_build_key(sb, fd.search_key, cnid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (!hfs_brec_find(&fd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) hfs_brec_remove(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) err2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) hfs_find_exit(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * hfs_cat_compare()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * This is the comparison function used for the catalog B-tree. In
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * comparing catalog B-tree entries, the parent id is the most
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * significant field (compared as unsigned ints). The name field is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * the least significant (compared in "Macintosh lexical order",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * see hfs_strcmp() in string.c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * Input Variable(s):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * struct hfs_cat_key *key1: pointer to the first key to compare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * struct hfs_cat_key *key2: pointer to the second key to compare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * Output Variable(s):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * NONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * Returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * int: negative if key1<key2, positive if key1>key2, and 0 if key1==key2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * Preconditions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * key1 and key2 point to "valid" (struct hfs_cat_key)s.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * Postconditions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * This function has no side-effects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) int hfs_cat_keycmp(const btree_key *key1, const btree_key *key2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) __be32 k1p, k2p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) k1p = key1->cat.ParID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) k2p = key2->cat.ParID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (k1p != k2p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return hfs_strcmp(key1->cat.CName.name, key1->cat.CName.len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) key2->cat.CName.name, key2->cat.CName.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /* Try to get a catalog entry for given catalog id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) // move to read_super???
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct hfs_find_data *fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) hfs_cat_rec rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) int res, len, type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) hfs_cat_build_key(sb, fd->search_key, cnid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) res = hfs_brec_read(fd, &rec, sizeof(rec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) type = rec.type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (type != HFS_CDR_THD && type != HFS_CDR_FTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) pr_err("found bad thread record in catalog\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) fd->search_key->cat.ParID = rec.thread.ParID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) len = fd->search_key->cat.CName.len = rec.thread.CName.len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (len > HFS_NAMELEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) pr_err("bad catalog namelength\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) memcpy(fd->search_key->cat.CName.name, rec.thread.CName.name, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return hfs_brec_find(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * hfs_cat_delete()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * Delete the indicated file or directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * The associated thread is also removed unless ('with_thread'==0).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int hfs_cat_delete(u32 cnid, struct inode *dir, const struct qstr *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct super_block *sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct hfs_find_data fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct hfs_readdir_data *rd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) int res, type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) hfs_dbg(CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) sb = dir->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) res = hfs_find_init(HFS_SB(sb)->cat_tree, &fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) hfs_cat_build_key(sb, fd.search_key, dir->i_ino, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) res = hfs_brec_find(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) type = hfs_bnode_read_u8(fd.bnode, fd.entryoffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (type == HFS_CDR_FIL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct hfs_cat_file file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) hfs_bnode_read(fd.bnode, &file, fd.entryoffset, sizeof(file));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (be32_to_cpu(file.FlNum) == cnid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) hfs_free_fork(sb, &file, HFS_FK_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) hfs_free_fork(sb, &file, HFS_FK_RSRC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /* we only need to take spinlock for exclusion with ->release() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) spin_lock(&HFS_I(dir)->open_dir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) list_for_each_entry(rd, &HFS_I(dir)->open_dir_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) rd->file->f_pos--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) spin_unlock(&HFS_I(dir)->open_dir_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) res = hfs_brec_remove(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) hfs_cat_build_key(sb, fd.search_key, cnid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) res = hfs_brec_find(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) res = hfs_brec_remove(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) dir->i_size--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) dir->i_mtime = dir->i_ctime = current_time(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) mark_inode_dirty(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) hfs_find_exit(&fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * hfs_cat_move()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * Rename a file or directory, possibly to a new directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * If the destination exists it is removed and a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * (struct hfs_cat_entry) for it is returned in '*result'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) int hfs_cat_move(u32 cnid, struct inode *src_dir, const struct qstr *src_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct inode *dst_dir, const struct qstr *dst_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct super_block *sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct hfs_find_data src_fd, dst_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) union hfs_cat_rec entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) int entry_size, type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) hfs_dbg(CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) cnid, src_dir->i_ino, src_name->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) dst_dir->i_ino, dst_name->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) sb = src_dir->i_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) err = hfs_find_init(HFS_SB(sb)->cat_tree, &src_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) dst_fd = src_fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * Fail early and avoid ENOSPC during the btree operations. We may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * have to split the root node at most once.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) err = hfs_bmap_reserve(src_fd.tree, 2 * src_fd.tree->depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* find the old dir entry and read the data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) hfs_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) err = hfs_brec_find(&src_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (src_fd.entrylength > sizeof(entry) || src_fd.entrylength < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) err = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) src_fd.entrylength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /* create new dir entry with the data from the old entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) hfs_cat_build_key(sb, dst_fd.search_key, dst_dir->i_ino, dst_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) err = hfs_brec_find(&dst_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (err != -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) err = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) err = hfs_brec_insert(&dst_fd, &entry, src_fd.entrylength);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) dst_dir->i_size++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) dst_dir->i_mtime = dst_dir->i_ctime = current_time(dst_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) mark_inode_dirty(dst_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) /* finally remove the old entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) hfs_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) err = hfs_brec_find(&src_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) err = hfs_brec_remove(&src_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) src_dir->i_size--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) src_dir->i_mtime = src_dir->i_ctime = current_time(src_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) mark_inode_dirty(src_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) type = entry.type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (type == HFS_CDR_FIL && !(entry.file.Flags & HFS_FIL_THD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /* remove old thread entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) hfs_cat_build_key(sb, src_fd.search_key, cnid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) err = hfs_brec_find(&src_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) err = hfs_brec_remove(&src_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /* create new thread entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) hfs_cat_build_key(sb, dst_fd.search_key, cnid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) entry_size = hfs_cat_build_thread(sb, &entry, type == HFS_CDR_FIL ? HFS_CDR_FTH : HFS_CDR_THD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) dst_dir->i_ino, dst_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) err = hfs_brec_find(&dst_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (err != -ENOENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) err = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) err = hfs_brec_insert(&dst_fd, &entry, entry_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) hfs_bnode_put(dst_fd.bnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) hfs_find_exit(&src_fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }