Exemple #1
0
static char * item_type (struct item_head * ih)
{
    static char * types[] = {
        "SD", "DIR", "DRCT", "IND", "???"
    };

    if (I_IS_STAT_DATA_ITEM(ih))
        return types[0];
    if (I_IS_DIRECTORY_ITEM(ih))
        return types[1];
    if (I_IS_DIRECT_ITEM(ih))
        return types[2];
    if (I_IS_INDIRECT_ITEM(ih))
        return types[3];
    return types[4];
}
/* fill direct items with 0s */
static void zero_direct_items (char * buf)
{
    int i;
    struct item_head * ih;

    if (((struct block_head *)buf)->blk_level != DISK_LEAF_NODE_LEVEL)
	return;

    /* leaf node found */
    ih = (struct item_head *)(buf + BLKH_SIZE);

    for (i = 0; i < ((struct block_head *)buf)->blk_nr_item; i ++, ih ++) {
	if (I_IS_DIRECT_ITEM (ih)) {
	    /* FIXME: do not zero symlinks */
	    direct_items ++;
	    direct_item_total_length += ih->ih_item_len;
	    memset (buf + ih->ih_item_location, 0, ih->ih_item_len);
	}
	items ++;
	if (ih->u.ih_free_space == 0xffff)
	    unreachable_items ++;
    }
}
void pack_partition (struct super_block * s)
{
    int i, j, k;
    uint32_t blocknumber32;
    uint16_t reclen16, data16;
    __u32 done = 0;
    char * data;
    long long bytes_to_transfer = 0;
    struct buffer_head * bh;
    int total_block_number;


    total_block_number = get_total_block_number ();
    

    /* write filesystem's block size to stdout as 16 bit number */
    reclen16 = htons (s->s_blocksize);
    if (opt_pack == 'p' || opt_pack_all == 'p')
	write (1, &reclen16, sizeof (uint16_t));
    bytes_to_transfer = sizeof (uint16_t);

    /* go through blocks which are marked used in cautious bitmap */
    for (i = 0; i < SB_BMAP_NR (s); i ++) {
	for (j = 0; j < s->s_blocksize; j ++) {
	    /* make sure, that we are not out of the device */
	    if (i * s->s_blocksize * 8 + j * 8 == SB_BLOCK_COUNT (s))
		goto out_of_bitmap;

	    if (i * s->s_blocksize * 8 + j * 8 + 8 > SB_BLOCK_COUNT (s))
		die ("build_the_tree: Out of bitmap");

	    if (opt_pack_all == 0)
		if (SB_AP_BITMAP (s)[i]->b_data[j] == 0) {
		    /* skip busy block if 'a' not specified */
		    continue;
		}

	    /* read 8 blocks at once */
	    bh = bread (s->s_dev, i * s->s_blocksize + j, s->s_blocksize * 8);
	    for (k = 0; k < 8; k ++) {
		__u32 block;
		
		block = i * s->s_blocksize * 8 + j * 8 + k;
		
		if (opt_pack_all == 0 && (SB_AP_BITMAP (s)[i]->b_data[j] & (1 << k)) == 0)
		    continue;
#if 0
		if ((SB_AP_BITMAP (s)[i]->b_data[j] & (1 << k)) == 0  || /* k-th block is free */
		    block < SB_BUFFER_WITH_SB (s)->b_blocknr) /* is in skipped for drive manager area */
		    continue;
#endif
		
		print_how_far (&done, total_block_number);
		
		data = bh->b_data + k * s->s_blocksize;

		if (not_formatted_node (data, s->s_blocksize)) {
		    /* ok, could not find formatted node here. But
                       this can be commit block, or bitmap which has
                       to be transferred */
		    if (!not_data_block (s, block)) {
			/* this is usual unformatted node. Transfer
                           its number only to erase previously existed
                           formatted nodes on the partition we will
                           apply transferred metadata to */
	    
			/* size of following record in network byte order */
			reclen16 = htons (2);

			/* the record record */
			data16 = htons (MAX_HEIGHT + 1);/*?*/
			data = (char *)&data16;
		    } else {
			/* write super block and bitmap block must be transferred as are */
			/* size of record  */
			reclen16 = htons (s->s_blocksize);
	    
			/* the record itself */
			data = data;
		    }
		} else {
		    /* any kind of formatted nodes gets here (super
                       block, desc block of journal): FIXME: it would
                       be useful to be able to find commit blocks */
		    zero_direct_items (data);
		    /* FIXME: do other packing */
		    /* write size of following record */
		    reclen16 = htons (s->s_blocksize);
		    
		    /* the record itself */
		    data = data;

#if 0
		    if (blkh->blk_level > DISK_LEAF_NODE_LEVEL) {
			/* block must look like internal node on the target
			   partition. But (currently) fsck do not consider internal
			   nodes, therefore we do not have to transfer contents of
			   internal nodes */
	    
			/* size of following record in network byte order */
			reclen16 = htons (2);
	    
			/* the record itself */
			data16 = htons (DISK_LEAF_NODE_LEVEL + 1);
			data = (char *)&data16;	  
		    } else {
	    
			/* leaf node found */
			ih = (struct item_head *)(blkh + 1);
	    
			/* fill direct items with 0s */
			for (l = 0; l < blkh->blk_nr_item; l ++, ih ++)
			    if (I_IS_DIRECT_ITEM (ih)) {
				direct_items ++;
				direct_item_total_length += ih->ih_item_len;
				memset ((char *)blkh + ih->ih_item_location, 0, ih->ih_item_len);
			    }
	    
			/* write size of following record */
			reclen16 = htons (s->s_blocksize);
	    
			/* the record itself */
			data = (char *)blkh;
		    }
#endif
		}
	  
		/*fprintf (stderr, "block %d, reclen %d\n", block, ntohs (reclen16));*/
	
		/* write block number */
		blocknumber32 = htonl (block);
		bytes_to_transfer += sizeof (uint32_t) + sizeof (uint16_t) + ntohs (reclen16);
		if (opt_pack == 'p' || opt_pack_all == 'p') {
		    write (1, &blocknumber32, sizeof (uint32_t));
		    /* write record len */
		    write (1, &reclen16, sizeof (uint16_t));
		    /* write the record */
		    write (1, data, ntohs (reclen16));
		}
	    }
      
	    bforget (bh);
	}
    }
    
 out_of_bitmap:
    fprintf (stderr, "done\n");
    if (opt_pack == 'c' || opt_pack_all == 'c')
	fprintf (stderr, "Bytes to transfer %Ld, sequential 0s %d in %d sequeneces (%items (%d unreacable))\n",
		 bytes_to_transfer, direct_item_total_length, direct_items, items, unreachable_items);
    else
	fprintf (stderr, "Bytes dumped %Ld, sequential 0s %d in %d sequeneces\n",
		 bytes_to_transfer, direct_item_total_length, direct_items);
    
    
}