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 + -
显示快捷键?