162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * linux/fs/hfs/catalog.c 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 1995-1997 Paul H. Hargrove 562306a36Sopenharmony_ci * (C) 2003 Ardis Technologies <roman@ardistech.com> 662306a36Sopenharmony_ci * This file may be distributed under the terms of the GNU General Public License. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * This file contains the functions related to the catalog B-tree. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Cache code shamelessly stolen from 1162306a36Sopenharmony_ci * linux/fs/inode.c Copyright (C) 1991, 1992 Linus Torvalds 1262306a36Sopenharmony_ci * re-shamelessly stolen Copyright (C) 1997 Linus Torvalds 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "hfs_fs.h" 1662306a36Sopenharmony_ci#include "btree.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* 1962306a36Sopenharmony_ci * hfs_cat_build_key() 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * Given the ID of the parent and the name build a search key. 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_civoid hfs_cat_build_key(struct super_block *sb, btree_key *key, u32 parent, const struct qstr *name) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci key->cat.reserved = 0; 2662306a36Sopenharmony_ci key->cat.ParID = cpu_to_be32(parent); 2762306a36Sopenharmony_ci if (name) { 2862306a36Sopenharmony_ci hfs_asc2mac(sb, &key->cat.CName, name); 2962306a36Sopenharmony_ci key->key_len = 6 + key->cat.CName.len; 3062306a36Sopenharmony_ci } else { 3162306a36Sopenharmony_ci memset(&key->cat.CName, 0, sizeof(struct hfs_name)); 3262306a36Sopenharmony_ci key->key_len = 6; 3362306a36Sopenharmony_ci } 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic int hfs_cat_build_record(hfs_cat_rec *rec, u32 cnid, struct inode *inode) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci __be32 mtime = hfs_mtime(); 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci memset(rec, 0, sizeof(*rec)); 4162306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode)) { 4262306a36Sopenharmony_ci rec->type = HFS_CDR_DIR; 4362306a36Sopenharmony_ci rec->dir.DirID = cpu_to_be32(cnid); 4462306a36Sopenharmony_ci rec->dir.CrDat = mtime; 4562306a36Sopenharmony_ci rec->dir.MdDat = mtime; 4662306a36Sopenharmony_ci rec->dir.BkDat = 0; 4762306a36Sopenharmony_ci rec->dir.UsrInfo.frView = cpu_to_be16(0xff); 4862306a36Sopenharmony_ci return sizeof(struct hfs_cat_dir); 4962306a36Sopenharmony_ci } else { 5062306a36Sopenharmony_ci /* init some fields for the file record */ 5162306a36Sopenharmony_ci rec->type = HFS_CDR_FIL; 5262306a36Sopenharmony_ci rec->file.Flags = HFS_FIL_USED | HFS_FIL_THD; 5362306a36Sopenharmony_ci if (!(inode->i_mode & S_IWUSR)) 5462306a36Sopenharmony_ci rec->file.Flags |= HFS_FIL_LOCK; 5562306a36Sopenharmony_ci rec->file.FlNum = cpu_to_be32(cnid); 5662306a36Sopenharmony_ci rec->file.CrDat = mtime; 5762306a36Sopenharmony_ci rec->file.MdDat = mtime; 5862306a36Sopenharmony_ci rec->file.BkDat = 0; 5962306a36Sopenharmony_ci rec->file.UsrWds.fdType = HFS_SB(inode->i_sb)->s_type; 6062306a36Sopenharmony_ci rec->file.UsrWds.fdCreator = HFS_SB(inode->i_sb)->s_creator; 6162306a36Sopenharmony_ci return sizeof(struct hfs_cat_file); 6262306a36Sopenharmony_ci } 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic int hfs_cat_build_thread(struct super_block *sb, 6662306a36Sopenharmony_ci hfs_cat_rec *rec, int type, 6762306a36Sopenharmony_ci u32 parentid, const struct qstr *name) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci rec->type = type; 7062306a36Sopenharmony_ci memset(rec->thread.reserved, 0, sizeof(rec->thread.reserved)); 7162306a36Sopenharmony_ci rec->thread.ParID = cpu_to_be32(parentid); 7262306a36Sopenharmony_ci hfs_asc2mac(sb, &rec->thread.CName, name); 7362306a36Sopenharmony_ci return sizeof(struct hfs_cat_thread); 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci/* 7762306a36Sopenharmony_ci * create_entry() 7862306a36Sopenharmony_ci * 7962306a36Sopenharmony_ci * Add a new file or directory to the catalog B-tree and 8062306a36Sopenharmony_ci * return a (struct hfs_cat_entry) for it in '*result'. 8162306a36Sopenharmony_ci */ 8262306a36Sopenharmony_ciint hfs_cat_create(u32 cnid, struct inode *dir, const struct qstr *str, struct inode *inode) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci struct hfs_find_data fd; 8562306a36Sopenharmony_ci struct super_block *sb; 8662306a36Sopenharmony_ci union hfs_cat_rec entry; 8762306a36Sopenharmony_ci int entry_size; 8862306a36Sopenharmony_ci int err; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci hfs_dbg(CAT_MOD, "create_cat: %s,%u(%d)\n", 9162306a36Sopenharmony_ci str->name, cnid, inode->i_nlink); 9262306a36Sopenharmony_ci if (dir->i_size >= HFS_MAX_VALENCE) 9362306a36Sopenharmony_ci return -ENOSPC; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci sb = dir->i_sb; 9662306a36Sopenharmony_ci err = hfs_find_init(HFS_SB(sb)->cat_tree, &fd); 9762306a36Sopenharmony_ci if (err) 9862306a36Sopenharmony_ci return err; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci /* 10162306a36Sopenharmony_ci * Fail early and avoid ENOSPC during the btree operations. We may 10262306a36Sopenharmony_ci * have to split the root node at most once. 10362306a36Sopenharmony_ci */ 10462306a36Sopenharmony_ci err = hfs_bmap_reserve(fd.tree, 2 * fd.tree->depth); 10562306a36Sopenharmony_ci if (err) 10662306a36Sopenharmony_ci goto err2; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci hfs_cat_build_key(sb, fd.search_key, cnid, NULL); 10962306a36Sopenharmony_ci entry_size = hfs_cat_build_thread(sb, &entry, S_ISDIR(inode->i_mode) ? 11062306a36Sopenharmony_ci HFS_CDR_THD : HFS_CDR_FTH, 11162306a36Sopenharmony_ci dir->i_ino, str); 11262306a36Sopenharmony_ci err = hfs_brec_find(&fd); 11362306a36Sopenharmony_ci if (err != -ENOENT) { 11462306a36Sopenharmony_ci if (!err) 11562306a36Sopenharmony_ci err = -EEXIST; 11662306a36Sopenharmony_ci goto err2; 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci err = hfs_brec_insert(&fd, &entry, entry_size); 11962306a36Sopenharmony_ci if (err) 12062306a36Sopenharmony_ci goto err2; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci hfs_cat_build_key(sb, fd.search_key, dir->i_ino, str); 12362306a36Sopenharmony_ci entry_size = hfs_cat_build_record(&entry, cnid, inode); 12462306a36Sopenharmony_ci err = hfs_brec_find(&fd); 12562306a36Sopenharmony_ci if (err != -ENOENT) { 12662306a36Sopenharmony_ci /* panic? */ 12762306a36Sopenharmony_ci if (!err) 12862306a36Sopenharmony_ci err = -EEXIST; 12962306a36Sopenharmony_ci goto err1; 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci err = hfs_brec_insert(&fd, &entry, entry_size); 13262306a36Sopenharmony_ci if (err) 13362306a36Sopenharmony_ci goto err1; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci dir->i_size++; 13662306a36Sopenharmony_ci dir->i_mtime = inode_set_ctime_current(dir); 13762306a36Sopenharmony_ci mark_inode_dirty(dir); 13862306a36Sopenharmony_ci hfs_find_exit(&fd); 13962306a36Sopenharmony_ci return 0; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cierr1: 14262306a36Sopenharmony_ci hfs_cat_build_key(sb, fd.search_key, cnid, NULL); 14362306a36Sopenharmony_ci if (!hfs_brec_find(&fd)) 14462306a36Sopenharmony_ci hfs_brec_remove(&fd); 14562306a36Sopenharmony_cierr2: 14662306a36Sopenharmony_ci hfs_find_exit(&fd); 14762306a36Sopenharmony_ci return err; 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci/* 15162306a36Sopenharmony_ci * hfs_cat_compare() 15262306a36Sopenharmony_ci * 15362306a36Sopenharmony_ci * Description: 15462306a36Sopenharmony_ci * This is the comparison function used for the catalog B-tree. In 15562306a36Sopenharmony_ci * comparing catalog B-tree entries, the parent id is the most 15662306a36Sopenharmony_ci * significant field (compared as unsigned ints). The name field is 15762306a36Sopenharmony_ci * the least significant (compared in "Macintosh lexical order", 15862306a36Sopenharmony_ci * see hfs_strcmp() in string.c) 15962306a36Sopenharmony_ci * Input Variable(s): 16062306a36Sopenharmony_ci * struct hfs_cat_key *key1: pointer to the first key to compare 16162306a36Sopenharmony_ci * struct hfs_cat_key *key2: pointer to the second key to compare 16262306a36Sopenharmony_ci * Output Variable(s): 16362306a36Sopenharmony_ci * NONE 16462306a36Sopenharmony_ci * Returns: 16562306a36Sopenharmony_ci * int: negative if key1<key2, positive if key1>key2, and 0 if key1==key2 16662306a36Sopenharmony_ci * Preconditions: 16762306a36Sopenharmony_ci * key1 and key2 point to "valid" (struct hfs_cat_key)s. 16862306a36Sopenharmony_ci * Postconditions: 16962306a36Sopenharmony_ci * This function has no side-effects 17062306a36Sopenharmony_ci */ 17162306a36Sopenharmony_ciint hfs_cat_keycmp(const btree_key *key1, const btree_key *key2) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci __be32 k1p, k2p; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci k1p = key1->cat.ParID; 17662306a36Sopenharmony_ci k2p = key2->cat.ParID; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci if (k1p != k2p) 17962306a36Sopenharmony_ci return be32_to_cpu(k1p) < be32_to_cpu(k2p) ? -1 : 1; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci return hfs_strcmp(key1->cat.CName.name, key1->cat.CName.len, 18262306a36Sopenharmony_ci key2->cat.CName.name, key2->cat.CName.len); 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/* Try to get a catalog entry for given catalog id */ 18662306a36Sopenharmony_ci// move to read_super??? 18762306a36Sopenharmony_ciint hfs_cat_find_brec(struct super_block *sb, u32 cnid, 18862306a36Sopenharmony_ci struct hfs_find_data *fd) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci hfs_cat_rec rec; 19162306a36Sopenharmony_ci int res, len, type; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci hfs_cat_build_key(sb, fd->search_key, cnid, NULL); 19462306a36Sopenharmony_ci res = hfs_brec_read(fd, &rec, sizeof(rec)); 19562306a36Sopenharmony_ci if (res) 19662306a36Sopenharmony_ci return res; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci type = rec.type; 19962306a36Sopenharmony_ci if (type != HFS_CDR_THD && type != HFS_CDR_FTH) { 20062306a36Sopenharmony_ci pr_err("found bad thread record in catalog\n"); 20162306a36Sopenharmony_ci return -EIO; 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci fd->search_key->cat.ParID = rec.thread.ParID; 20562306a36Sopenharmony_ci len = fd->search_key->cat.CName.len = rec.thread.CName.len; 20662306a36Sopenharmony_ci if (len > HFS_NAMELEN) { 20762306a36Sopenharmony_ci pr_err("bad catalog namelength\n"); 20862306a36Sopenharmony_ci return -EIO; 20962306a36Sopenharmony_ci } 21062306a36Sopenharmony_ci memcpy(fd->search_key->cat.CName.name, rec.thread.CName.name, len); 21162306a36Sopenharmony_ci return hfs_brec_find(fd); 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci/* 21662306a36Sopenharmony_ci * hfs_cat_delete() 21762306a36Sopenharmony_ci * 21862306a36Sopenharmony_ci * Delete the indicated file or directory. 21962306a36Sopenharmony_ci * The associated thread is also removed unless ('with_thread'==0). 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_ciint hfs_cat_delete(u32 cnid, struct inode *dir, const struct qstr *str) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci struct super_block *sb; 22462306a36Sopenharmony_ci struct hfs_find_data fd; 22562306a36Sopenharmony_ci struct hfs_readdir_data *rd; 22662306a36Sopenharmony_ci int res, type; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci hfs_dbg(CAT_MOD, "delete_cat: %s,%u\n", str ? str->name : NULL, cnid); 22962306a36Sopenharmony_ci sb = dir->i_sb; 23062306a36Sopenharmony_ci res = hfs_find_init(HFS_SB(sb)->cat_tree, &fd); 23162306a36Sopenharmony_ci if (res) 23262306a36Sopenharmony_ci return res; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci hfs_cat_build_key(sb, fd.search_key, dir->i_ino, str); 23562306a36Sopenharmony_ci res = hfs_brec_find(&fd); 23662306a36Sopenharmony_ci if (res) 23762306a36Sopenharmony_ci goto out; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci type = hfs_bnode_read_u8(fd.bnode, fd.entryoffset); 24062306a36Sopenharmony_ci if (type == HFS_CDR_FIL) { 24162306a36Sopenharmony_ci struct hfs_cat_file file; 24262306a36Sopenharmony_ci hfs_bnode_read(fd.bnode, &file, fd.entryoffset, sizeof(file)); 24362306a36Sopenharmony_ci if (be32_to_cpu(file.FlNum) == cnid) { 24462306a36Sopenharmony_ci#if 0 24562306a36Sopenharmony_ci hfs_free_fork(sb, &file, HFS_FK_DATA); 24662306a36Sopenharmony_ci#endif 24762306a36Sopenharmony_ci hfs_free_fork(sb, &file, HFS_FK_RSRC); 24862306a36Sopenharmony_ci } 24962306a36Sopenharmony_ci } 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci /* we only need to take spinlock for exclusion with ->release() */ 25262306a36Sopenharmony_ci spin_lock(&HFS_I(dir)->open_dir_lock); 25362306a36Sopenharmony_ci list_for_each_entry(rd, &HFS_I(dir)->open_dir_list, list) { 25462306a36Sopenharmony_ci if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0) 25562306a36Sopenharmony_ci rd->file->f_pos--; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci spin_unlock(&HFS_I(dir)->open_dir_lock); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci res = hfs_brec_remove(&fd); 26062306a36Sopenharmony_ci if (res) 26162306a36Sopenharmony_ci goto out; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci hfs_cat_build_key(sb, fd.search_key, cnid, NULL); 26462306a36Sopenharmony_ci res = hfs_brec_find(&fd); 26562306a36Sopenharmony_ci if (!res) { 26662306a36Sopenharmony_ci res = hfs_brec_remove(&fd); 26762306a36Sopenharmony_ci if (res) 26862306a36Sopenharmony_ci goto out; 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci dir->i_size--; 27262306a36Sopenharmony_ci dir->i_mtime = inode_set_ctime_current(dir); 27362306a36Sopenharmony_ci mark_inode_dirty(dir); 27462306a36Sopenharmony_ci res = 0; 27562306a36Sopenharmony_ciout: 27662306a36Sopenharmony_ci hfs_find_exit(&fd); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci return res; 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci/* 28262306a36Sopenharmony_ci * hfs_cat_move() 28362306a36Sopenharmony_ci * 28462306a36Sopenharmony_ci * Rename a file or directory, possibly to a new directory. 28562306a36Sopenharmony_ci * If the destination exists it is removed and a 28662306a36Sopenharmony_ci * (struct hfs_cat_entry) for it is returned in '*result'. 28762306a36Sopenharmony_ci */ 28862306a36Sopenharmony_ciint hfs_cat_move(u32 cnid, struct inode *src_dir, const struct qstr *src_name, 28962306a36Sopenharmony_ci struct inode *dst_dir, const struct qstr *dst_name) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci struct super_block *sb; 29262306a36Sopenharmony_ci struct hfs_find_data src_fd, dst_fd; 29362306a36Sopenharmony_ci union hfs_cat_rec entry; 29462306a36Sopenharmony_ci int entry_size, type; 29562306a36Sopenharmony_ci int err; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci hfs_dbg(CAT_MOD, "rename_cat: %u - %lu,%s - %lu,%s\n", 29862306a36Sopenharmony_ci cnid, src_dir->i_ino, src_name->name, 29962306a36Sopenharmony_ci dst_dir->i_ino, dst_name->name); 30062306a36Sopenharmony_ci sb = src_dir->i_sb; 30162306a36Sopenharmony_ci err = hfs_find_init(HFS_SB(sb)->cat_tree, &src_fd); 30262306a36Sopenharmony_ci if (err) 30362306a36Sopenharmony_ci return err; 30462306a36Sopenharmony_ci dst_fd = src_fd; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci /* 30762306a36Sopenharmony_ci * Fail early and avoid ENOSPC during the btree operations. We may 30862306a36Sopenharmony_ci * have to split the root node at most once. 30962306a36Sopenharmony_ci */ 31062306a36Sopenharmony_ci err = hfs_bmap_reserve(src_fd.tree, 2 * src_fd.tree->depth); 31162306a36Sopenharmony_ci if (err) 31262306a36Sopenharmony_ci goto out; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci /* find the old dir entry and read the data */ 31562306a36Sopenharmony_ci hfs_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name); 31662306a36Sopenharmony_ci err = hfs_brec_find(&src_fd); 31762306a36Sopenharmony_ci if (err) 31862306a36Sopenharmony_ci goto out; 31962306a36Sopenharmony_ci if (src_fd.entrylength > sizeof(entry) || src_fd.entrylength < 0) { 32062306a36Sopenharmony_ci err = -EIO; 32162306a36Sopenharmony_ci goto out; 32262306a36Sopenharmony_ci } 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset, 32562306a36Sopenharmony_ci src_fd.entrylength); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci /* create new dir entry with the data from the old entry */ 32862306a36Sopenharmony_ci hfs_cat_build_key(sb, dst_fd.search_key, dst_dir->i_ino, dst_name); 32962306a36Sopenharmony_ci err = hfs_brec_find(&dst_fd); 33062306a36Sopenharmony_ci if (err != -ENOENT) { 33162306a36Sopenharmony_ci if (!err) 33262306a36Sopenharmony_ci err = -EEXIST; 33362306a36Sopenharmony_ci goto out; 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci err = hfs_brec_insert(&dst_fd, &entry, src_fd.entrylength); 33762306a36Sopenharmony_ci if (err) 33862306a36Sopenharmony_ci goto out; 33962306a36Sopenharmony_ci dst_dir->i_size++; 34062306a36Sopenharmony_ci dst_dir->i_mtime = inode_set_ctime_current(dst_dir); 34162306a36Sopenharmony_ci mark_inode_dirty(dst_dir); 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci /* finally remove the old entry */ 34462306a36Sopenharmony_ci hfs_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name); 34562306a36Sopenharmony_ci err = hfs_brec_find(&src_fd); 34662306a36Sopenharmony_ci if (err) 34762306a36Sopenharmony_ci goto out; 34862306a36Sopenharmony_ci err = hfs_brec_remove(&src_fd); 34962306a36Sopenharmony_ci if (err) 35062306a36Sopenharmony_ci goto out; 35162306a36Sopenharmony_ci src_dir->i_size--; 35262306a36Sopenharmony_ci src_dir->i_mtime = inode_set_ctime_current(src_dir); 35362306a36Sopenharmony_ci mark_inode_dirty(src_dir); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci type = entry.type; 35662306a36Sopenharmony_ci if (type == HFS_CDR_FIL && !(entry.file.Flags & HFS_FIL_THD)) 35762306a36Sopenharmony_ci goto out; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci /* remove old thread entry */ 36062306a36Sopenharmony_ci hfs_cat_build_key(sb, src_fd.search_key, cnid, NULL); 36162306a36Sopenharmony_ci err = hfs_brec_find(&src_fd); 36262306a36Sopenharmony_ci if (err) 36362306a36Sopenharmony_ci goto out; 36462306a36Sopenharmony_ci err = hfs_brec_remove(&src_fd); 36562306a36Sopenharmony_ci if (err) 36662306a36Sopenharmony_ci goto out; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci /* create new thread entry */ 36962306a36Sopenharmony_ci hfs_cat_build_key(sb, dst_fd.search_key, cnid, NULL); 37062306a36Sopenharmony_ci entry_size = hfs_cat_build_thread(sb, &entry, type == HFS_CDR_FIL ? HFS_CDR_FTH : HFS_CDR_THD, 37162306a36Sopenharmony_ci dst_dir->i_ino, dst_name); 37262306a36Sopenharmony_ci err = hfs_brec_find(&dst_fd); 37362306a36Sopenharmony_ci if (err != -ENOENT) { 37462306a36Sopenharmony_ci if (!err) 37562306a36Sopenharmony_ci err = -EEXIST; 37662306a36Sopenharmony_ci goto out; 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci err = hfs_brec_insert(&dst_fd, &entry, entry_size); 37962306a36Sopenharmony_ciout: 38062306a36Sopenharmony_ci hfs_bnode_put(dst_fd.bnode); 38162306a36Sopenharmony_ci hfs_find_exit(&src_fd); 38262306a36Sopenharmony_ci return err; 38362306a36Sopenharmony_ci} 384