/* * linux/fs/hfs/catalog.c * * Copyright (C) 1995-1997 Paul H. Hargrove * (C) 2003 Ardis Technologies <roman@ardistech.com> * This file may be distributed under the terms of the GNU General Public License. * * This file contains the functions related to the catalog B-tree. * * Cache code shamelessly stolen from * linux/fs/inode.c Copyright (C) 1991, 1992 Linus Torvalds * re-shamelessly stolen Copyright (C) 1997 Linus Torvalds
*/
#include"hfs_fs.h" #include"btree.h"
/* * hfs_cat_build_key() * * Given the ID of the parent and the name build a search key.
*/ void hfs_cat_build_key(struct super_block *sb, btree_key *key, u32 parent, conststruct qstr *name)
{
key->cat.reserved = 0;
key->cat.ParID = cpu_to_be32(parent); if (name) {
hfs_asc2mac(sb, &key->cat.CName, name);
key->key_len = 6 + key->cat.CName.len;
} else {
memset(&key->cat.CName, 0, sizeof(struct hfs_name));
key->key_len = 6;
}
}
/* * create_entry() * * Add a new file or directory to the catalog B-tree and * return a (struct hfs_cat_entry) for it in '*result'.
*/ int hfs_cat_create(u32 cnid, struct inode *dir, conststruct qstr *str, struct inode *inode)
{ struct hfs_find_data fd; struct super_block *sb; union hfs_cat_rec entry; int entry_size; int err;
/* * Fail early and avoid ENOSPC during the btree operations. We may * have to split the root node at most once.
*/
err = hfs_bmap_reserve(fd.tree, 2 * fd.tree->depth); if (err) goto err2;
/* * hfs_cat_compare() * * Description: * This is the comparison function used for the catalog B-tree. In * comparing catalog B-tree entries, the parent id is the most * significant field (compared as unsigned ints). The name field is * the least significant (compared in "Macintosh lexical order", * see hfs_strcmp() in string.c) * Input Variable(s): * struct hfs_cat_key *key1: pointer to the first key to compare * struct hfs_cat_key *key2: pointer to the second key to compare * Output Variable(s): * NONE * Returns: * int: negative if key1<key2, positive if key1>key2, and 0 if key1==key2 * Preconditions: * key1 and key2 point to "valid" (struct hfs_cat_key)s. * Postconditions: * This function has no side-effects
*/ int hfs_cat_keycmp(const btree_key *key1, const btree_key *key2)
{
__be32 k1p, k2p;
/* Try to get a catalog entry for given catalog id */ // move to read_super??? int hfs_cat_find_brec(struct super_block *sb, u32 cnid, struct hfs_find_data *fd)
{
hfs_cat_rec rec; int res, len, type;
hfs_cat_build_key(sb, fd->search_key, cnid, NULL);
res = hfs_brec_read(fd, &rec, sizeof(rec)); if (res) return res;
type = rec.type; if (type != HFS_CDR_THD && type != HFS_CDR_FTH) {
pr_err("found bad thread record in catalog\n"); return -EIO;
}
/* we only need to take spinlock for exclusion with ->release() */
spin_lock(&HFS_I(dir)->open_dir_lock);
list_for_each_entry(rd, &HFS_I(dir)->open_dir_list, list) { if (fd.tree->keycmp(fd.search_key, (void *)&rd->key) < 0)
rd->file->f_pos--;
}
spin_unlock(&HFS_I(dir)->open_dir_lock);
res = hfs_brec_remove(&fd); if (res) goto out;
hfs_cat_build_key(sb, fd.search_key, cnid, NULL);
res = hfs_brec_find(&fd); if (!res) {
res = hfs_brec_remove(&fd); if (res) goto out;
}
dir->i_size--;
inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));
mark_inode_dirty(dir);
res = 0;
out:
hfs_find_exit(&fd);
return res;
}
/* * hfs_cat_move() * * Rename a file or directory, possibly to a new directory. * If the destination exists it is removed and a * (struct hfs_cat_entry) for it is returned in '*result'.
*/ int hfs_cat_move(u32 cnid, struct inode *src_dir, conststruct qstr *src_name, struct inode *dst_dir, conststruct qstr *dst_name)
{ struct super_block *sb; struct hfs_find_data src_fd, dst_fd; union hfs_cat_rec entry; int entry_size, type; int err;
/* * Fail early and avoid ENOSPC during the btree operations. We may * have to split the root node at most once.
*/
err = hfs_bmap_reserve(src_fd.tree, 2 * src_fd.tree->depth); if (err) goto out;
/* find the old dir entry and read the data */
hfs_cat_build_key(sb, src_fd.search_key, src_dir->i_ino, src_name);
err = hfs_brec_find(&src_fd); if (err) goto out; if (src_fd.entrylength > sizeof(entry) || src_fd.entrylength < 0) {
err = -EIO; goto out;
}
/* create new dir entry with the data from the old entry */
hfs_cat_build_key(sb, dst_fd.search_key, dst_dir->i_ino, dst_name);
err = hfs_brec_find(&dst_fd); if (err != -ENOENT) { if (!err)
err = -EEXIST; goto out;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.