예제 #1
0
/*
 * hfs_btree_commit()
 *
 * Called to write a possibly dirty btree back to disk.
 */
void hfs_btree_commit(struct hfs_btree *bt, hfs_byte_t ext[12], hfs_lword_t size)
{
	if (bt->dirt) {
		struct BTHdrRec *th;
		th = (struct BTHdrRec *)((char *)hfs_buffer_data(bt->head.buf) +
						 sizeof(struct NodeDescriptor));

		hfs_put_hs(bt->bthDepth,  th->bthDepth);
		hfs_put_hl(bt->bthRoot,   th->bthRoot);
		hfs_put_hl(bt->bthNRecs,  th->bthNRecs);
		hfs_put_hl(bt->bthFNode,  th->bthFNode);
		hfs_put_hl(bt->bthLNode,  th->bthLNode);
		hfs_put_hl(bt->bthNNodes, th->bthNNodes);
		hfs_put_hl(bt->bthFree,   th->bthFree);
		hfs_buffer_dirty(bt->head.buf);

		/*
		 * Commit the bnodes which are not cached.
		 * The map nodes don't need to be committed here because
		 * they are committed every time they are changed.
		 */
		hfs_bnode_commit(&bt->head);
		if (bt->root) {
			hfs_bnode_commit(bt->root);
		}

	
		hfs_put_hl(bt->bthNNodes << HFS_SECTOR_SIZE_BITS, size);
		hfs_extent_out(&bt->entry.u.file.data_fork, ext);
		/* hfs_buffer_dirty(mdb->buf); (Done by caller) */

		bt->dirt = 0;
	}
}
예제 #2
0
/*
 * build_key
 */
static inline void build_key(struct hfs_ext_key *key,
                             const struct hfs_fork *fork, hfs_u16 block)
{
    key->KeyLen = 7;
    key->FkType = fork->fork;
    hfs_put_nl(fork->entry->cnid, key->FNum);
    hfs_put_hs(block,             key->FABN);
}
예제 #3
0
/*
 * hfs_bnode_shift_right()
 *
 * Description:
 *   Shifts some records from a node to its right neighbor.
 * Input Variable(s):
 *   struct hfs_bnode* left: the node to shift records from
 *   struct hfs_bnode* right: the node to shift records to
 *   hfs_u16 first: the number of the first record in 'left' to move to 'right'
 * Output Variable(s):
 *   NONE
 * Returns:
 *   void
 * Preconditions:
 *   'left' and 'right' point to valid (struct hfs_bnode)s.
 *   'left' contains at least 'first' records.
 *   'right' has enough free space to hold the records to be moved from 'left'
 * Postconditions:
 *   The record numbered 'first' and all records after it in 'left' are
 *   placed at the beginning of 'right'.
 *   The key corresponding to 'right' in its parent is NOT updated.
 */
void hfs_bnode_shift_right(struct hfs_bnode *left, struct hfs_bnode *right,
			   int first)
{
	int i, adjust, nrecs;
	unsigned size;
	hfs_u16 *to, *from;

	if ((first <= 0) || (first > left->ndNRecs)) {
		hfs_warn("bad argument to shift_right: first=%d, nrecs=%d\n",
		       first, left->ndNRecs);
		return;
	}

	/* initialize variables */
	nrecs = left->ndNRecs + 1 - first;
	size = bnode_end(left) - bnode_offset(left, first);

	/* move (possibly empty) contents of right node forward */
	memmove(bnode_datastart(right) + size,
		bnode_datastart(right), 
		bnode_end(right) - sizeof(struct NodeDescriptor));

	/* copy in new records */
	memcpy(bnode_datastart(right), bnode_key(left,first), size);

	/* fix up offsets in right node */
	i = right->ndNRecs + 1;
	from = RECTBL(right, i);
	to = from - nrecs;
	while (i--) {
		hfs_put_hs(hfs_get_hs(from++) + size, to++);
	}
	adjust = sizeof(struct NodeDescriptor) - bnode_offset(left, first);
	i = nrecs-1;
	from = RECTBL(left, first+i);
	while (i--) {
		hfs_put_hs(hfs_get_hs(from++) + adjust, to++);
	}

	/* fix record counts */
	left->ndNRecs -= nrecs;
	right->ndNRecs += nrecs;
}
예제 #4
0
/*
 * hfs_bnode_shift_left()
 *
 * Description:
 *   Shifts some records from a node to its left neighbor.
 * Input Variable(s):
 *   struct hfs_bnode* left: the node to shift records to
 *   struct hfs_bnode* right: the node to shift records from
 *   hfs_u16 last: the number of the last record in 'right' to move to 'left'
 * Output Variable(s):
 *   NONE
 * Returns:
 *   void
 * Preconditions:
 *   'left' and 'right' point to valid (struct hfs_bnode)s.
 *   'right' contains at least 'last' records.
 *   'left' has enough free space to hold the records to be moved from 'right'
 * Postconditions:
 *   The record numbered 'last' and all records before it in 'right' are
 *   placed at the end of 'left'.
 *   The key corresponding to 'right' in its parent is NOT updated.
 */
void hfs_bnode_shift_left(struct hfs_bnode *left, struct hfs_bnode *right,
			  int last)
{
	int i, adjust, nrecs;
	unsigned size;
	hfs_u16 *to, *from;

	if ((last <= 0) || (last > right->ndNRecs)) {
		hfs_warn("bad argument to shift_left: last=%d, nrecs=%d\n",
		       last, right->ndNRecs);
		return;
	}

	/* initialize variables */
	size = bnode_offset(right, last + 1) - sizeof(struct NodeDescriptor);

	/* copy records to left node */
	memcpy(bnode_dataend(left), bnode_datastart(right), size);

	/* move (possibly empty) remainder of right node backward */
	memmove(bnode_datastart(right), bnode_datastart(right) + size, 
			bnode_end(right) - bnode_offset(right, last + 1));

	/* fix up offsets */
	nrecs = left->ndNRecs;
	i = last;
	from = RECTBL(right, 2);
	to = RECTBL(left, nrecs + 2);
	adjust = bnode_offset(left, nrecs + 1) - sizeof(struct NodeDescriptor);
	while (i--) {
		hfs_put_hs(hfs_get_hs(from--) + adjust, to--);
	}
	i = right->ndNRecs + 1 - last;
	++from;
	to = RECTBL(right, 1);
	while (i--) {
		hfs_put_hs(hfs_get_hs(from--) - size, to--);
	}

	/* fix record counts */
	left->ndNRecs += last;
	right->ndNRecs -= last;
}
예제 #5
0
/*
 * write_extent()
 *
 * Initializes a (struct hfs_raw_extent) from a (struct hfs_extent).
 *
 * Note that the callers must check that to,from != NULL
 */
static void write_extent(struct hfs_raw_extent *to,
                         const struct hfs_extent *from)
{
    hfs_put_hs(from->block[0], to->block1);
    hfs_put_hs(from->length[0], to->length1);
    hfs_put_hs(from->block[1], to->block2);
    hfs_put_hs(from->length[1], to->length2);
    hfs_put_hs(from->block[2], to->block3);
    hfs_put_hs(from->length[2], to->length3);
}
예제 #6
0
/*
 * cap_build_meta()
 *
 * Build the metadata structure.
 */
static void cap_build_meta(struct hfs_cap_info *meta,
			   struct hfs_cat_entry *entry)
{
	memset(meta, 0, sizeof(*meta));
	memcpy(meta->fi_fndr, &entry->info, 32);
	if ((entry->type == HFS_CDR_FIL) &&
	    (entry->u.file.flags & HFS_FIL_LOCK)) {
		/* Couple the locked bit of the file to the
		   AFP {write,rename,delete} inhibit bits. */
		hfs_put_hs(HFS_AFP_RDONLY, meta->fi_attr);
	}
	meta->fi_magic1 = HFS_CAP_MAGIC1;
	meta->fi_version = HFS_CAP_VERSION;
	meta->fi_magic = HFS_CAP_MAGIC;
	meta->fi_bitmap = HFS_CAP_LONGNAME;
	memcpy(meta->fi_macfilename, entry->key.CName.Name,
	       entry->key.CName.Len);
	meta->fi_datemagic = HFS_CAP_DMAGIC;
	meta->fi_datevalid = HFS_CAP_MDATE | HFS_CAP_CDATE;
	hfs_put_nl(hfs_m_to_htime(entry->create_date), meta->fi_ctime);
	hfs_put_nl(hfs_m_to_htime(entry->modify_date), meta->fi_mtime);
	hfs_put_nl(CURRENT_TIME,                       meta->fi_utime);
}
예제 #7
0
/*
 * bdelete_nonempty()
 *
 * Description:
 *   Deletes a record from a given bnode without regard to it becoming empty.
 * Input Variable(s):
 *   struct hfs_brec* brec: pointer to the brec for the deletion
 *   struct hfs_belem* belem: which node in 'brec' to delete from
 * Output Variable(s):
 *   NONE
 * Returns:
 *   void
 * Preconditions:
 *   'brec' points to a valid (struct hfs_brec).
 *   'belem' points to a valid (struct hfs_belem) in 'brec'.
 * Postconditions:
 *   The record has been inserted in the position indicated by 'brec'.
 */
static void bdelete_nonempty(struct hfs_brec *brec, struct hfs_belem *belem)
{
	int i, rec, nrecs, tomove;
	hfs_u16 size;
	hfs_u8 *start;
	struct hfs_bnode *bnode = belem->bnr.bn;

	rec = belem->record;
	nrecs = bnode->ndNRecs;
	size = bnode_rsize(bnode, rec);
	tomove = bnode_offset(bnode, nrecs+1) - bnode_offset(bnode, rec+1);
	
	/* adjust the record table */
	for (i = rec+1; i <= nrecs; ++i) {
		hfs_put_hs(bnode_offset(bnode,i+1) - size, RECTBL(bnode,i));
	}

	/* move it down */
	start = bnode_key(bnode, rec);
	memmove(start, start + size, tomove);

	/* update record count */
	--bnode->ndNRecs;
}