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