/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
#include <linux/config.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#include <linux/time.h>
#include <linux/reiserfs_fs.h>
#include <linux/buffer_head.h>
/* these are used in do_balance.c */
/* leaf_move_items
leaf_shift_left
leaf_shift_right
leaf_delete_items
leaf_insert_into_buf
leaf_paste_in_buffer
leaf_cut_from_buffer
leaf_paste_entries
*/
/* copy copy_count entries from source directory item to dest buffer (creating new item if needed) */
static void leaf_copy_dir_entries (struct buffer_info * dest_bi, struct buffer_head * source,
int last_first, int item_num, int from, int copy_count)
{
struct buffer_head * dest = dest_bi->bi_bh;
int item_num_in_dest; /* either the number of target item,
or if we must create a new item,
the number of the item we will
create it next to */
struct item_head * ih;
struct reiserfs_de_head * deh;
int copy_records_len; /* length of all records in item to be copied */
char * records;
ih = B_N_PITEM_HEAD (source, item_num);
RFALSE( !is_direntry_le_ih (ih), "vs-10000: item must be directory item");
/* length of all record to be copied and first byte of the last of them */
deh = B_I_DEH (source, ih);
if (copy_count) {
copy_records_len = (from ? deh_location( &(deh[from - 1]) ) :
ih_item_len(ih)) - deh_location( &(deh[from + copy_count - 1]));
records = source->b_data + ih_location(ih) +
deh_location( &(deh[from + copy_count - 1]));
} else {
copy_records_len = 0;
records = NULL;
}
/* when copy last to first, dest buffer can contain 0 items */
item_num_in_dest = (last_first == LAST_TO_FIRST) ? (( B_NR_ITEMS(dest) ) ? 0 : -1) : (B_NR_ITEMS(dest) - 1);
/* if there are no items in dest or the first/last item in dest is not item of the same directory */
if ( (item_num_in_dest == - 1) ||
(last_first == FIRST_TO_LAST && le_ih_k_offset (ih) == DOT_OFFSET) ||
(last_first == LAST_TO_FIRST && comp_short_le_keys/*COMP_SHORT_KEYS*/ (&ih->ih_key, B_N_PKEY (dest, item_num_in_dest)))) {
/* create new item in dest */
struct item_head new_ih;
/* form item header */
memcpy (&new_ih.ih_key, &ih->ih_key, KEY_SIZE);
put_ih_version( &new_ih, KEY_FORMAT_3_5 );
/* calculate item len */
put_ih_item_len( &new_ih, DEH_SIZE * copy_count + copy_records_len );
put_ih_entry_count( &new_ih, 0 );
if (last_first == LAST_TO_FIRST) {
/* form key by the following way */
if (from < I_ENTRY_COUNT(ih)) {
set_le_ih_k_offset( &new_ih, deh_offset( &(deh[from])