fsimage_grub.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 387 行

C
387
字号
/* * 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: *  * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. *  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Copyright 2008 Sun Microsystems, Inc.  All rights reserved. * Use is subject to license terms. */#ifndef __sun__#define	_XOPEN_SOURCE 500#endif#include <stdlib.h>#include <strings.h>#include <errno.h>#include "fsimage_grub.h"#include "fsimage_priv.h"static char *disk_read_junk;typedef struct fsig_data {	char fd_buf[FSYS_BUFLEN];} fsig_data_t;typedef struct fsig_file_data {	char ffd_buf[FSYS_BUFLEN];	uint64_t ffd_curpos;	uint64_t ffd_filepos;	uint64_t ffd_filemax;	int ffd_int1;	int ffd_int2;	int ffd_errnum;} fsig_file_data_t;fsi_file_t *fsig_file_alloc(fsi_t *fsi){	fsi_file_t *ffi;	fsig_file_data_t *data = malloc(sizeof (fsig_file_data_t));	if (data == NULL)		return (NULL);	bzero(data, sizeof (fsig_file_data_t));	bcopy(fsig_fs_buf(fsi), data->ffd_buf, FSYS_BUFLEN);	if ((ffi = fsip_file_alloc(fsi, data)) == NULL) {		free(data);		return (NULL);	}	return (ffi);}void *fsig_fs_buf(fsi_t *fsi){	fsig_data_t *data = fsip_fs_data(fsi);	return ((void *)data->fd_buf);}void *fsig_file_buf(fsi_file_t *ffi){	fsig_file_data_t *data = fsip_file_data(ffi);	return ((void *)data->ffd_buf);}uint64_t *fsig_filepos(fsi_file_t *ffi){	fsig_file_data_t *data = fsip_file_data(ffi);	return (&data->ffd_filepos);}uint64_t *fsig_filemax(fsi_file_t *ffi){	fsig_file_data_t *data = fsip_file_data(ffi);	return (&data->ffd_filemax);}int *fsig_int1(fsi_file_t *ffi){	fsig_file_data_t *data = fsip_file_data(ffi);	return (&data->ffd_int1);}int *fsig_int2(fsi_file_t *ffi){	fsig_file_data_t *data = fsip_file_data(ffi);	return (&data->ffd_int2);}int *fsig_errnum(fsi_file_t *ffi){	fsig_file_data_t *data = fsip_file_data(ffi);	return (&data->ffd_errnum);}char **fsig_disk_read_junk(void){	return (&disk_read_junk);}#if defined(__i386__) || defined(__x86_64__)#ifdef __amd64#define BSF "bsfq"#else#define BSF "bsfl"#endifunsigned longfsig_log2 (unsigned long word){  __asm__ (BSF " %1,%0"	   : "=r" (word)	   : "r" (word));  return word;}#elif defined(__ia64__)#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)# define ia64_popcnt(x) __builtin_popcountl(x)#else# define ia64_popcnt(x)                                     \  ({                                                        \    uint64_t ia64_intri_res;                                \    asm ("popcnt %0=%1" : "=r" (ia64_intri_res) : "r" (x)); \    ia64_intri_res;                                         \  })#endifunsigned longfsig_log2 (unsigned long word){  unsigned long result;  result = ia64_popcnt((word - 1) & ~word);  return result;}#elif defined(__powerpc__)#ifdef __powerpc64__#define PPC_CNTLZL "cntlzd"#else#define PPC_CNTLZL "cntlzw"#endif#define BITS_PER_LONG (sizeof(long) * 8)static int__ilog2(unsigned long x){  int lz;  asm (PPC_CNTLZL " %0,%1" : "=r" (lz) : "r" (x));  return BITS_PER_LONG - 1 - lz;}unsigned longfsig_log2 (unsigned long word){  return __ilog2(word & -word);}#else /* Unoptimized */unsigned longfsig_log2 (unsigned long word){  unsigned long result = 0;  while (!(word & 1UL))    {      result++;      word >>= 1;    }  return result;}#endifintfsig_devread(fsi_file_t *ffi, unsigned int sector, unsigned int offset,    unsigned int bufsize, char *buf){	off_t off;	ssize_t ret;	int n, r;	char tmp[SECTOR_SIZE];	off = ffi->ff_fsi->f_off + ((off_t)sector * SECTOR_SIZE) + offset;	/*	 * Make reads from a raw disk sector-aligned. This is a requirement	 * for NetBSD. Split the read up into to three parts to meet this	 * requirement.	 */	n = (off & (SECTOR_SIZE - 1));	if (n > 0) {		r = SECTOR_SIZE - n;		if (r > bufsize)			r = bufsize;		ret = pread(ffi->ff_fsi->f_fd, tmp, SECTOR_SIZE, off - n);		if (ret < n + r)			return (0);		memcpy(buf, tmp + n, r);		buf += r;		bufsize -= r;		off += r;	}	n = (bufsize & ~(SECTOR_SIZE - 1));	if (n > 0) {		ret = pread(ffi->ff_fsi->f_fd, buf, n, off);		if (ret < n)			return (0);		buf += n;		bufsize -= n;		off += n;	}	if (bufsize > 0) {		ret = pread(ffi->ff_fsi->f_fd, tmp, SECTOR_SIZE, off);		if (ret < bufsize)			return (0);		memcpy(buf, tmp, bufsize);	}	return (1);}intfsig_substring(const char *s1, const char *s2){	while (*s1 == *s2) {		if (*s1 == '\0')			return (0);		s1++;		s2++;	}	if (*s1 == '\0')		return (-1);	return (1);}static intfsig_mount(fsi_t *fsi, const char *path, const char *options){	fsig_plugin_ops_t *ops = fsi->f_plugin->fp_data;	fsi_file_t *ffi;	fsi->f_data = malloc(sizeof (fsig_data_t));	if (fsi->f_data == NULL)		return (-1);	if ((ffi = fsig_file_alloc(fsi)) == NULL) {		free(fsi->f_data);		fsi->f_data = NULL;		return (-1);	}	bzero(fsi->f_data, sizeof (fsig_data_t));	if (!ops->fpo_mount(ffi, options)) {		fsip_file_free(ffi);		fsi_bootstring_free(fsi);		free(fsi->f_data);		fsi->f_data = NULL;		return (-1);	}	bcopy(fsig_file_buf(ffi), fsig_fs_buf(fsi), FSYS_BUFLEN);	fsip_file_free(ffi);	return (0);}static intfsig_umount(fsi_t *fsi){	fsi_bootstring_free(fsi);	free(fsi->f_data);	return (0);}static fsi_file_t *fsig_open(fsi_t *fsi, const char *name){	fsig_plugin_ops_t *ops = fsi->f_plugin->fp_data;	char *path = strdup(name);	fsi_file_t *ffi = NULL;	if (path == NULL || (ffi = fsig_file_alloc(fsi)) == NULL)		goto out;	if (ops->fpo_dir(ffi, path) == 0) {		fsip_file_free(ffi);		ffi = NULL;		errno = ENOENT;	}out:	free(path);	return (ffi);}static ssize_tfsig_pread(fsi_file_t *ffi, void *buf, size_t nbytes, uint64_t off){	fsig_plugin_ops_t *ops = ffi->ff_fsi->f_plugin->fp_data;	fsig_file_data_t *data = fsip_file_data(ffi);	data->ffd_filepos = off;	if (data->ffd_filepos >= data->ffd_filemax)		return (0);	/* FIXME: check */	if (data->ffd_filepos + nbytes > data->ffd_filemax)		nbytes = data->ffd_filemax - data->ffd_filepos;	errnum = 0;	return (ops->fpo_read(ffi, buf, nbytes));}static ssize_tfsig_read(fsi_file_t *ffi, void *buf, size_t nbytes){	fsig_file_data_t *data = fsip_file_data(ffi);	ssize_t ret;	ret = fsig_pread(ffi, buf, nbytes, data->ffd_curpos);	data->ffd_curpos = data->ffd_filepos;	return (ret);}static intfsig_close(fsi_file_t *ffi){	free(ffi->ff_data);	fsip_file_free(ffi);	return (0);}static fsi_plugin_ops_t fsig_grub_ops = {	.fpo_version = FSIMAGE_PLUGIN_VERSION,	.fpo_mount = fsig_mount,	.fpo_umount = fsig_umount,	.fpo_open = fsig_open,	.fpo_read = fsig_read,	.fpo_pread = fsig_pread,	.fpo_close = fsig_close};fsi_plugin_ops_t *fsig_init(fsi_plugin_t *plugin, fsig_plugin_ops_t *ops){	if (ops->fpo_version > FSIMAGE_PLUGIN_VERSION)		return (NULL);	plugin->fp_data = ops;	return (&fsig_grub_ops);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?