亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? block-qcow.c

?? xen source 推出最新的VHD操作工具VHD-UTIL 實現源碼,超強
?? C
?? 第 1 頁 / 共 3 頁
字號:
/* block-qcow.c
 *
 * Asynchronous Qemu copy-on-write disk implementation.
 * Code based on the Qemu implementation
 * (see copyright notice below)
 *
 * (c) 2006 Andrew Warfield and Julian Chesterfield
 *
 */

/*
 * Block driver for the QCOW format
 * 
 * Copyright (c) 2004 Fabrice Bellard
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files(the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 */

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/statvfs.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <string.h>
#include <zlib.h>
#include <inttypes.h>
#include <libaio.h>
#include <openssl/md5.h>
#include "bswap.h"
#include "aes.h"

#include "tapdisk.h"
#include "tapdisk-driver.h"
#include "tapdisk-interface.h"
#include "qcow.h"
#include "blk.h"
#include "atomicio.h"

/* *BSD has no O_LARGEFILE */
#ifndef O_LARGEFILE
#define O_LARGEFILE     0
#endif

#if 1
#define ASSERT(_p) \
    if ( !(_p) ) { DPRINTF("Assertion '%s' failed, line %d, file %s", #_p , \
    __LINE__, __FILE__); *(int*)0=0; }
#else
#define ASSERT(_p) ((void)0)
#endif

struct pending_aio {
        td_callback_t cb;
        int id;
        void *private;
	int nb_sectors;
	char *buf;
	uint64_t sector;
};

#undef IOCB_IDX
#define IOCB_IDX(_s, _io) ((_io) - (_s)->iocb_list)

#define ZERO_TEST(_b) (_b | 0x00)

struct qcow_request {
	td_request_t         treq;
	struct tiocb         tiocb;
	struct tdqcow_state  *state;
};

static int decompress_cluster(struct tdqcow_state *s, uint64_t cluster_offset);

#ifdef USE_GCRYPT

#include <gcrypt.h>

uint32_t gen_cksum(char *ptr, int len)
{
  int i;
  uint32_t md[4];

  /* Generate checksum */
  gcry_md_hash_buffer(GCRY_MD_MD5, md, ptr, len);

  return md[0];
}

#else /* use libcrypto */

#include <openssl/md5.h>

uint32_t gen_cksum(char *ptr, int len)
{
  int i;
  unsigned char *md;
  uint32_t ret;

  md = malloc(MD5_DIGEST_LENGTH);
  if(!md) return 0;

  /* Generate checksum */
  if (MD5((unsigned char *)ptr, len, md) != md)
    ret = 0;
  else
    memcpy(&ret, md, sizeof(uint32_t));

  free(md);
  return ret;
}

#endif


static void free_aio_state(struct tdqcow_state* s)
{
	free(s->aio_requests);
	free(s->aio_free_list);
}

static int init_aio_state(td_driver_t *driver)
{
	int i, ret;
	td_disk_info_t *bs = &(driver->info);
	struct tdqcow_state   *s  = (struct tdqcow_state *)driver->data;
	
        // A segment (i.e. a page) can span multiple clusters
        s->max_aio_reqs = ((getpagesize() / s->cluster_size) + 1) *
	  MAX_SEGMENTS_PER_REQ * MAX_REQUESTS;

	s->aio_free_count = s->max_aio_reqs;

	if (!(s->aio_requests  = calloc(s->max_aio_reqs, sizeof(struct qcow_request))) || 
	    !(s->aio_free_list = calloc(s->max_aio_reqs, sizeof(struct qcow_request)))) {
	    DPRINTF("Failed to allocate AIO structs (max_aio_reqs = %d)\n",
		    s->max_aio_reqs);
	    goto fail;
	}

	for (i = 0; i < s->max_aio_reqs; i++)
		s->aio_free_list[i] = &s->aio_requests[i];

        DPRINTF("AIO state initialised\n");

        return 0;
 fail:
	return -1;
}

int get_filesize(char *filename, uint64_t *size, struct stat *st)
{
	int fd;
	QCowHeader header;

	/*Set to the backing file size*/
	fd = open(filename, O_RDONLY);
	if (fd < 0)
		return -1;
	if (read(fd, &header, sizeof(header)) < sizeof(header)) {
		close(fd);
		return -1;
	}
	close(fd);
	
	be32_to_cpus(&header.magic);
	be64_to_cpus(&header.size);
	if (header.magic == QCOW_MAGIC) {
		*size = header.size >> SECTOR_SHIFT;
		return 0;
	}

	if(S_ISBLK(st->st_mode)) {
		fd = open(filename, O_RDONLY);
		if (fd < 0)
			return -1;
		if (blk_getimagesize(fd, size) != 0) {
			printf("Unable to get Block device size\n");
			close(fd);
			return -1;
		}
		close(fd);
	} else *size = (st->st_size >> SECTOR_SHIFT);	
	return 0;
}

static int qcow_set_key(struct tdqcow_state *s, const char *key)
{
	uint8_t keybuf[16];
	int len, i;
	
	memset(keybuf, 0, 16);
	len = strlen(key);
	if (len > 16)
		len = 16;
	/* XXX: we could compress the chars to 7 bits to increase
	   entropy */
	for (i = 0; i < len; i++) {
		keybuf[i] = key[i];
	}
	s->crypt_method = s->crypt_method_header;
	
	if (AES_set_encrypt_key(keybuf, 128, &s->aes_encrypt_key) != 0)
		return -1;
	if (AES_set_decrypt_key(keybuf, 128, &s->aes_decrypt_key) != 0)
		return -1;
#if 0
	/* test */
	{
		uint8_t in[16];
		uint8_t out[16];
		uint8_t tmp[16];
		for (i=0; i<16; i++)
			in[i] = i;
		AES_encrypt(in, tmp, &s->aes_encrypt_key);
		AES_decrypt(tmp, out, &s->aes_decrypt_key);
		for (i = 0; i < 16; i++)
			DPRINTF(" %02x", tmp[i]);
		DPRINTF("\n");
		for (i = 0; i < 16; i++)
			DPRINTF(" %02x", out[i]);
		DPRINTF("\n");
	}
#endif
	return 0;
}

void tdqcow_complete(void *arg, struct tiocb *tiocb, int err)
{
	struct qcow_request *aio = (struct qcow_request *)arg;
	struct tdqcow_state *s = aio->state;

	td_complete_request(aio->treq, err);

	s->aio_free_list[s->aio_free_count++] = aio;
}

static void async_read(td_driver_t *driver, td_request_t treq)
{
	int size;
	uint64_t offset;
	struct qcow_request *aio;
	struct tdqcow_state *prv;

	prv    = (struct tdqcow_state *)driver->data;
	size   = treq.secs * driver->info.sector_size;
	offset = treq.sec  * (uint64_t)driver->info.sector_size;

	if (prv->aio_free_count == 0)
		goto fail;

	aio        = prv->aio_free_list[--prv->aio_free_count];
	aio->treq  = treq;
	aio->state = prv;

	td_prep_read(&aio->tiocb, prv->fd, treq.buf,
		     size, offset, tdqcow_complete, aio);
	td_queue_tiocb(driver, &aio->tiocb);

	return;

fail:
	td_complete_request(treq, -EBUSY);
}

static void async_write(td_driver_t *driver, td_request_t treq)
{
	int size;
	uint64_t offset;
	struct qcow_request *aio;
	struct tdqcow_state *prv;

	prv     = (struct tdqcow_state *)driver->data;
	size    = treq.secs * driver->info.sector_size;
	offset  = treq.sec  * (uint64_t)driver->info.sector_size;

	if (prv->aio_free_count == 0)
		goto fail;

	aio        = prv->aio_free_list[--prv->aio_free_count];
	aio->treq  = treq;
	aio->state = prv;

	td_prep_write(&aio->tiocb, prv->fd, treq.buf,
		      size, offset, tdqcow_complete, aio);
	td_queue_tiocb(driver, &aio->tiocb);

	return;

fail:
	td_complete_request(treq, -EBUSY);
}

/* 
 * The crypt function is compatible with the linux cryptoloop
 * algorithm for < 4 GB images. NOTE: out_buf == in_buf is
 * supported .
 */
static void encrypt_sectors(struct tdqcow_state *s, int64_t sector_num,
                            uint8_t *out_buf, const uint8_t *in_buf,
                            int nb_sectors, int enc,
                            const AES_KEY *key)
{
	union {
		uint64_t ll[2];
		uint8_t b[16];
	} ivec;
	int i;
	
	for (i = 0; i < nb_sectors; i++) {
		ivec.ll[0] = cpu_to_le64(sector_num);
		ivec.ll[1] = 0;
		AES_cbc_encrypt(in_buf, out_buf, 512, key, 
				ivec.b, enc);
		sector_num++;
		in_buf += 512;
		out_buf += 512;
	}
}

int qtruncate(int fd, off_t length, int sparse)
{
	int ret, i; 
	int current = 0, rem = 0;
	uint64_t sectors;
	struct stat st;
	char *buf;

	/* If length is greater than the current file len
	 * we synchronously write zeroes to the end of the 
	 * file, otherwise we truncate the length down
	 */
	ret = fstat(fd, &st);
	if (ret == -1) 
		return -1;
	if (S_ISBLK(st.st_mode))
		return 0;

	sectors = (length + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE;
	current = (st.st_size + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE;
	rem     = st.st_size % DEFAULT_SECTOR_SIZE;

	/* If we are extending this file, we write zeros to the end --
	 * this tries to ensure that the extents allocated wind up being
	 * contiguous on disk.
	 */
	if(st.st_size < sectors * DEFAULT_SECTOR_SIZE) {
		/*We are extending the file*/
		if ((ret = posix_memalign((void **)&buf, 
					  512, DEFAULT_SECTOR_SIZE))) {
			DPRINTF("posix_memalign failed: %d\n", ret);
			return -1;
		}
		memset(buf, 0x00, DEFAULT_SECTOR_SIZE);
		if (lseek(fd, 0, SEEK_END)==-1) {
			DPRINTF("Lseek EOF failed (%d), internal error\n",
				errno);
			free(buf);
			return -1;
		}
		if (rem) {
			ret = write(fd, buf, rem);
			if (ret != rem) {
				DPRINTF("write failed: ret = %d, err = %s\n",
					ret, strerror(errno));
				free(buf);
				return -1;
			}
		}
		for (i = current; i < sectors; i++ ) {
			ret = write(fd, buf, DEFAULT_SECTOR_SIZE);
			if (ret != DEFAULT_SECTOR_SIZE) {
				DPRINTF("write failed: ret = %d, err = %s\n",
					ret, strerror(errno));
				free(buf);
				return -1;
			}
		}
		free(buf);
	} else if(sparse && (st.st_size > sectors * DEFAULT_SECTOR_SIZE))
		if (ftruncate(fd, (off_t)sectors * DEFAULT_SECTOR_SIZE)==-1) {
			DPRINTF("Ftruncate failed (%s)\n", strerror(errno));
			return -1;
		}
	return 0;
}

/* 'allocate' is:
 *
 * 0 to not allocate.
 *
 * 1 to allocate a normal cluster (for sector indexes 'n_start' to
 * 'n_end')
 *
 * 2 to allocate a compressed cluster of size
 * 'compressed_size'. 'compressed_size' must be > 0 and <
 * cluster_size 
 *
 * return 0 if not allocated.
 */
static uint64_t get_cluster_offset(struct tdqcow_state *s,
                                   uint64_t offset, int allocate,
                                   int compressed_size,
                                   int n_start, int n_end)
{
	int min_index, i, j, l1_index, l2_index, l2_sector, l1_sector;
	char *tmp_ptr2, *l2_ptr, *l1_ptr;
	uint64_t *tmp_ptr;
	uint64_t l2_offset, *l2_table, cluster_offset, tmp;
	uint32_t min_count;
	int new_l2_table;

	/*Check L1 table for the extent offset*/
	l1_index = offset >> (s->l2_bits + s->cluster_bits);
	l2_offset = s->l1_table[l1_index];
	new_l2_table = 0;
	if (!l2_offset) {
		if (!allocate)
			return 0;
		/* 
		 * allocating a new l2 entry + extent 
		 * at the end of the file, we must also
		 * update the L1 entry safely.
		 */
		l2_offset = s->fd_end;

		/* round to cluster size */
		l2_offset = (l2_offset + s->cluster_size - 1) 
			& ~(s->cluster_size - 1);

		/* update the L1 entry */
		s->l1_table[l1_index] = l2_offset;
		
		/*Truncate file for L2 table 
		 *(initialised to zero in case we crash)*/
		if (qtruncate(s->fd, 
			      l2_offset + (s->l2_size * sizeof(uint64_t)),
			      s->sparse) != 0) {
			DPRINTF("ERROR truncating file\n");
			return 0;
		}
		s->fd_end = l2_offset + (s->l2_size * sizeof(uint64_t));

		/*Update the L1 table entry on disk
                 * (for O_DIRECT we write 4KByte blocks)*/
		l1_sector = (l1_index * sizeof(uint64_t)) >> 12;
		l1_ptr = (char *)s->l1_table + (l1_sector << 12);

		if (posix_memalign((void **)&tmp_ptr, 4096, 4096) != 0) {
			DPRINTF("ERROR allocating memory for L1 table\n");
		}
		memcpy(tmp_ptr, l1_ptr, 4096);

		/* Convert block to write to big endian */
		for(i = 0; i < 4096 / sizeof(uint64_t); i++) {
			cpu_to_be64s(&tmp_ptr[i]);
		}

		/*
		 * Issue non-asynchronous L1 write.
		 * For safety, we must ensure that
		 * entry is written before blocks.
		 */
		lseek(s->fd, s->l1_table_offset + (l1_sector << 12), SEEK_SET);
		if (write(s->fd, tmp_ptr, 4096) != 4096) {
			free(tmp_ptr);
		 	return 0;
		}
		free(tmp_ptr);

		new_l2_table = 1;
		goto cache_miss;
	} else if (s->min_cluster_alloc == s->l2_size) {
		/*Fast-track the request*/
		cluster_offset = l2_offset + (s->l2_size * sizeof(uint64_t));
		l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
		return cluster_offset + (l2_index * s->cluster_size);
	}

	/*Check to see if L2 entry is already cached*/
	for (i = 0; i < L2_CACHE_SIZE; i++) {
		if (l2_offset == s->l2_cache_offsets[i]) {
			/* increment the hit count */
			if (++s->l2_cache_counts[i] == 0xffffffff) {
				for (j = 0; j < L2_CACHE_SIZE; j++) {
					s->l2_cache_counts[j] >>= 1;
				}
			}
			l2_table = s->l2_cache + (i << s->l2_bits);
			goto found;
		}
	}

cache_miss:
	/* not found: load a new entry in the least used one */
	min_index = 0;
	min_count = 0xffffffff;
	for (i = 0; i < L2_CACHE_SIZE; i++) {
		if (s->l2_cache_counts[i] < min_count) {

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
国产精品主播直播| 午夜精品123| 成人综合婷婷国产精品久久蜜臀 | 欧美日韩国产综合久久| 亚洲免费高清视频在线| 在线观看日韩精品| 亚洲成人资源网| 91精品国产综合久久久久久漫画 | 亚洲欧美二区三区| 色屁屁一区二区| 日日噜噜夜夜狠狠视频欧美人| 91精品国产综合久久福利 | 国产真实乱子伦精品视频| 在线亚洲+欧美+日本专区| 久久这里只有精品首页| 国产福利一区二区| 综合久久久久久| 欧美中文字幕亚洲一区二区va在线 | 亚洲一区二区视频| 欧美精品色一区二区三区| 蜜臀av性久久久久蜜臀aⅴ| 精品国产伦一区二区三区观看体验 | 亚洲国产一区二区视频| 在线综合视频播放| 国产美女av一区二区三区| 国产精品天美传媒沈樵| 欧美蜜桃一区二区三区| 国产麻豆午夜三级精品| **性色生活片久久毛片| 欧美精选在线播放| 国产91色综合久久免费分享| 亚洲精品写真福利| 欧美不卡一区二区| 91在线精品一区二区| 日韩精品亚洲一区| 日韩美女啊v在线免费观看| 5月丁香婷婷综合| 成人精品一区二区三区四区| 丝瓜av网站精品一区二区| 中文字幕av一区二区三区高| 欧美日韩国产bt| 成人黄色小视频在线观看| 日韩成人精品视频| 亚洲柠檬福利资源导航| 精品国产在天天线2019| 欧美日韩国产免费一区二区| jvid福利写真一区二区三区| 青青草国产成人av片免费| 国产精品久久久久久久久动漫 | 成人激情免费视频| 精品美女一区二区| 在线看日韩精品电影| 国产在线精品一区二区三区不卡| 一区二区三区不卡视频| 国产精品色婷婷久久58| 91精品国产综合久久久久| 色综合天天综合色综合av| 国产精品一级黄| 精品一区二区三区久久| 亚洲成人在线免费| 一区二区三区美女视频| 国产精品麻豆欧美日韩ww| 久久久电影一区二区三区| 日韩欧美成人激情| 欧美区视频在线观看| 精品久久久久久久久久久院品网| 欧美本精品男人aⅴ天堂| 99精品视频在线免费观看| 麻豆久久久久久| 午夜精品福利一区二区三区av| 亚洲欧美国产77777| 亚洲欧洲日韩综合一区二区| 国产性做久久久久久| 久久影院视频免费| 26uuu另类欧美亚洲曰本| 3atv在线一区二区三区| 欧美日韩精品是欧美日韩精品| 91精品1区2区| 在线观看免费一区| 欧美色欧美亚洲另类二区| 色综合久久久久网| 97se亚洲国产综合自在线| jlzzjlzz亚洲女人18| 国产精品18久久久| 国产一区不卡视频| 懂色av一区二区三区蜜臀| 丁香婷婷综合激情五月色| 国产精品一区免费视频| 国产精品自拍av| 国产91精品露脸国语对白| 婷婷成人综合网| 婷婷成人激情在线网| 日本va欧美va欧美va精品| 日本午夜一本久久久综合| 日韩成人午夜精品| 极品少妇xxxx偷拍精品少妇| 精品中文字幕一区二区小辣椒| 国模冰冰炮一区二区| 高清不卡在线观看| 一本色道久久综合狠狠躁的推荐| 色综合天天综合网国产成人综合天 | av在线播放一区二区三区| av激情综合网| 在线观看av一区| 欧美一区二区视频免费观看| 精品福利视频一区二区三区| 国产香蕉久久精品综合网| 国产精品不卡视频| 亚洲成av人片一区二区三区| 久久精品久久精品| av高清久久久| 91.麻豆视频| 久久久精品黄色| 亚洲精选免费视频| 久久99久久99精品免视看婷婷| 国产精华液一区二区三区| 色综合久久综合中文综合网| 欧美日韩卡一卡二| 久久综合九色综合欧美亚洲| 最新久久zyz资源站| 日韩国产一区二| 成人在线综合网| 欧美日韩1234| 国产午夜精品理论片a级大结局| 一区二区视频在线| 精品中文字幕一区二区| 日本二三区不卡| 久久影院午夜片一区| 亚洲五码中文字幕| 国产91丝袜在线18| 91精品国产一区二区三区香蕉| 亚洲国产成人自拍| 免费观看成人av| 欧美制服丝袜第一页| 国产婷婷色一区二区三区四区| 日韩精品色哟哟| jiyouzz国产精品久久| 在线91免费看| 亚洲欧美国产三级| 国产成人免费av在线| 日韩一区二区影院| 亚洲午夜一区二区三区| 99久久er热在这里只有精品15| 91精品国产色综合久久不卡电影| 亚洲区小说区图片区qvod| 精品亚洲成a人| 91精品麻豆日日躁夜夜躁| 亚洲色图欧美激情| 成人黄色网址在线观看| 欧美成人r级一区二区三区| 亚洲一区二区黄色| 99久久99久久精品免费观看| 精品国产乱码久久| 喷水一区二区三区| 欧美久久久一区| 亚洲综合成人在线| 91麻豆精品一区二区三区| 中文字幕精品一区二区精品绿巨人| 欧美bbbbb| 欧美男男青年gay1069videost | 色吊一区二区三区| 国产亚洲一本大道中文在线| 精品一区二区三区视频 | 91激情在线视频| 国产精品国产三级国产aⅴ无密码| 国产美女精品人人做人人爽| 日韩久久久精品| 久久99久久久久久久久久久| 日韩一区二区三区电影| 日本v片在线高清不卡在线观看| 欧美三级电影网站| 午夜精品成人在线视频| 欧美精品1区2区| 青青国产91久久久久久| 日韩一卡二卡三卡国产欧美| 婷婷成人激情在线网| 欧美一区二区啪啪| 免费不卡在线视频| 精品国产一区二区三区av性色 | 国产欧美一区二区精品婷婷| 国内精品视频一区二区三区八戒| 精品久久人人做人人爽| 国产在线精品国自产拍免费| 国产亚洲综合av| 99国产精品久久久久久久久久 | 91免费国产在线观看| 亚洲精品一二三四区| 欧美日韩高清影院| 麻豆一区二区三| 久久亚洲私人国产精品va媚药| 国产一区二区精品久久| 国产精品久久久久久久久久久免费看| 99久久久精品| 亚洲成国产人片在线观看| 欧美精品一卡二卡| 韩国中文字幕2020精品| 国产精品欧美综合在线| 91福利社在线观看| 久久精品国产免费| 一区在线播放视频|