[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel][PATCH] qemu-fuse
From: |
Shahar Frank |
Subject: |
[Qemu-devel][PATCH] qemu-fuse |
Date: |
Wed, 27 Aug 2008 08:50:15 -0700 |
Hi All,
The attached is a small utility to mount qemu images as pseudo
partition files. It can be very useful to access (rw) images from the
host.
I would not use it for production, but it seems to be stable.
Limitations:
1. Only primary partitions on disks are recognized.
2. The qemu-fuse is forced to be single threaded.
3. The write behind option is enabled for the images (better to be
turned off).
4. No snapshot access support.
5. Other?
Signed-off-by: Shahar Frank <address@hidden>
Index: qemu-fuse.c
===================================================================
--- qemu-fuse.c (revision 0)
+++ qemu-fuse.c (revision 0)
@@ -0,0 +1,643 @@
+/*
+ * QEMU disk image fuse server
+ *
+ * Copyright (c) 2008 Shahar Frank
+ *
+ * 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.
+ */
+#include "qemu-common.h"
+#include "block_int.h"
+#include <assert.h>
+
+#define FUSE_USE_VERSION 26
+
+#include <fuse/fuse_lowlevel.h>
+#include <fuse.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#define QDISK_MAX_PART 5
+typedef struct QDiskPart {
+ uint32_t start;
+ uint64_t count;
+ unsigned char type;
+ int boot;
+ char const *path;
+} QDiskPart;
+
+QDiskPart qparttbl[QDISK_MAX_PART];
+
+static const char *qemu_parttbl_path = "/parttbl";
+static char qemu_parttbl_str[8192];
+static int qemu_parttbl_str_len;
+
+static BlockDriverState *qemu_bs;
+static BlockDriver *qemu_bdrv;
+static char *qemu_img_path;
+static char *prog;
+static long qemu_dsize;
+static int open_flags = 0;
+
+
+void *qemu_memalign(size_t alignment, size_t size)
+{
+#if defined(_POSIX_C_SOURCE)
+ int ret;
+ void *ptr;
+ ret = posix_memalign(&ptr, alignment, size);
+ if (ret != 0)
+ return NULL;
+ return ptr;
+#elif defined(_BSD)
+ return valloc(size);
+#else
+ return memalign(alignment, size);
+#endif
+}
+
+static void __attribute__ ((noreturn)) error(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "qemu-fuse: ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ exit(1);
+ va_end(ap);
+}
+
+static void format_print(void *opaque, const char *name)
+{
+ printf(" %s", name);
+}
+
+void usage(void)
+{
+ printf("%s version " QEMU_VERSION
+ ", Copyright (c) 2007 Qumranet, Shahar Frank\n"
+ "usage: qemu-fuse [options] <image_path> <mount_point>
[fuse options]\n"
+ "QEMU disk image file system utility\n" "\n" "Options:\n"
+ " -d # debug mode (force also forground)\n"
+ " -f fmt # force image format\n"
+ " -F # keep program in forground\n"
+ " -h # help (this text)\n" "\n" "Examples:\n"
+ "\tmkdir -p /tmp/qemu /tmp/ext3 /tmp/ntfs\n"
+ "\t%s /images/disk.vmdk /tmp/qemu\n"
+ "\tmount -o loop /tmp/qemu/img2 /tmp/ext3\n"
+ "\tmount -o loop -t ntfs-3g -o force /tmp/qemu/img1
/tmp/ntfs\n",
+ prog, prog);
+ printf("\nSupported formats:");
+ bdrv_iterate_format(format_print, NULL);
+ printf("\n");
+ exit(1);
+}
+
+void help(void)
+{
+ usage();
+}
+
+#include <termios.h>
+
+static struct termios oldtty;
+
+static void term_exit(void)
+{
+ tcsetattr(0, TCSANOW, &oldtty);
+}
+
+static void term_init(void)
+{
+ struct termios tty;
+
+ tcgetattr(0, &tty);
+ oldtty = tty;
+
+ tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
+ | INLCR | IGNCR | ICRNL | IXON);
+ tty.c_oflag |= OPOST;
+ tty.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN);
+ tty.c_cflag &= ~(CSIZE | PARENB);
+ tty.c_cflag |= CS8;
+ tty.c_cc[VMIN] = 1;
+ tty.c_cc[VTIME] = 0;
+
+ tcsetattr(0, TCSANOW, &tty);
+
+ atexit(term_exit);
+}
+
+static int read_password(char *buf, int buf_size)
+{
+ uint8_t ch;
+ int i, ret;
+
+ printf("password: ");
+ fflush(stdout);
+ term_init();
+ i = 0;
+ for (;;) {
+ ret = read(0, &ch, 1);
+ if (ret == -1) {
+ if (errno == EAGAIN || errno == EINTR) {
+ continue;
+ } else {
+ ret = -1;
+ break;
+ }
+ } else if (ret == 0) {
+ ret = -1;
+ break;
+ } else {
+ if (ch == '\r') {
+ ret = 0;
+ break;
+ }
+ if (i < (buf_size - 1))
+ buf[i++] = ch;
+ }
+ }
+ term_exit();
+ buf[i] = '\0';
+ printf("\n");
+ return ret;
+}
+
+static BlockDriverState *bdrv_new_open(const char *filename,
+ const char *fmt)
+{
+ BlockDriverState *bs;
+ BlockDriver *drv;
+ char password[256];
+
+ bs = bdrv_new("");
+ if (!bs)
+ error("Not enough memory");
+ if (fmt) {
+ drv = bdrv_find_format(fmt);
+ if (!drv)
+ error("Unknown file format '%s'", fmt);
+ } else {
+ drv = NULL;
+ }
+ if (bdrv_open2(bs, filename, open_flags, drv) < 0) {
+ error("Could not open '%s'", filename);
+ }
+ if (bdrv_is_encrypted(bs)) {
+ printf("Disk image '%s' is encrypted.\n", filename);
+ if (read_password(password, sizeof(password)) < 0)
+ error("No password given");
+ if (bdrv_set_key(bs, password) < 0)
+ error("invalid password");
+ }
+ qemu_bs = bs;
+ qemu_bdrv = drv;
+ return bs;
+}
+
+static int64_t get_allocated_file_size(const char *filename)
+{
+ struct stat st;
+ if (stat(filename, &st) < 0)
+ return -1;
+ return (int64_t) st.st_blocks * 512;
+}
+
+static void dump_snapshots(BlockDriverState * bs)
+{
+ QEMUSnapshotInfo *sn_tab, *sn;
+ int nb_sns, i;
+ char buf[256];
+
+ nb_sns = bdrv_snapshot_list(bs, &sn_tab);
+ if (nb_sns <= 0)
+ return;
+ printf("Snapshot list:\n");
+ printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
+ for (i = 0; i < nb_sns; i++) {
+ sn = &sn_tab[i];
+ printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf),
sn));
+ }
+ qemu_free(sn_tab);
+}
+
+static int open_img(const char *filename, const char *fmt)
+{
+ BlockDriverState *bs;
+ char fmt_name[128], size_buf[128], dsize_buf[128];
+ uint64_t total_sectors;
+ int64_t allocated_size;
+ char backing_filename[1024];
+ char backing_filename2[1024];
+ BlockDriverInfo bdi;
+
+ if (!(bs = bdrv_new_open(filename, fmt))) {
+ error("Could not open '%s'", filename);
+ }
+ bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
+ bdrv_get_geometry(bs, &total_sectors);
+ get_human_readable_size(size_buf, sizeof(size_buf),
+ total_sectors * 512);
+ allocated_size = get_allocated_file_size(filename);
+ if (allocated_size < 0)
+ sprintf(dsize_buf, "unavailable");
+ else
+ get_human_readable_size(dsize_buf, sizeof(dsize_buf),
+ allocated_size);
+ printf("image: %s\n"
+ "file format: %s\n"
+ "virtual size: %s (%" PRId64 " bytes)\n"
+ "disk size: %s\n",
+ filename, fmt_name, size_buf,
+ (total_sectors * 512), dsize_buf);
+ if (bdrv_is_encrypted(bs))
+ printf("encrypted: yes\n");
+ if (bdrv_get_info(bs, &bdi) >= 0) {
+ if (bdi.cluster_size != 0)
+ printf("cluster_size: %d\n", bdi.cluster_size);
+ }
+ bdrv_get_backing_filename(bs, backing_filename,
+ sizeof(backing_filename));
+ if (backing_filename[0] != '\0') {
+ path_combine(backing_filename2,
sizeof(backing_filename2),
+ filename, backing_filename);
+ printf("backing file: %s (actual path: %s)\n",
+ backing_filename, backing_filename2);
+ }
+ dump_snapshots(bs);
+ qemu_img_path = strdup(filename);
+ qemu_dsize = total_sectors * 512;
+ return 0;
+}
+
+
+#define DOS_PARTTBL_OFFS 0x1be
+#define DOS_PARTTBL_SZ 66
+#define DOS_PARTTBL_ENT_SZ 16
+#define DOS_PARTTBL_MAGIC_LO 0x55
+#define DOS_PARTTBL_MAGIC_HI 0xaa
+#define DOS_PARTTBL_MAX_PART 4
+
+typedef struct PTableEntry {
+ unsigned char bootdisk;
+ unsigned char start_cylinder;
+ unsigned char start_head;
+ unsigned char start_sector;
+ unsigned char part_type;
+ unsigned char end_cylinder;
+ unsigned char end_head;
+ unsigned char end_sector;
+ unsigned char start_lba[4];
+ unsigned char sectors_count[4];
+} PTableEntry; /* use char only so
__attribute__((packed)) not required */
+
+static unsigned lt32_to_u32(char *lt32)
+{
+ uint32_t u = 0;
+ int i;
+ for (i = 0; i < 4; i++)
+ u |= ((uint32_t) lt32[i] & 0xff) << (i * 8);
+ return u;
+}
+
+static int fill_pent(QDiskPart * qtbl, char *buf, int n)
+{
+ return snprintf(buf, n,
+ "%s:\tstart %10u \tsectors %10llu \ttype %x
%s\n",
+ qtbl->path, qtbl->start,
+ (long long unsigned) qtbl->count, (int)
qtbl->type,
+ qtbl->boot ? "*" : "");
+}
+
+/* FIXME: parses only primary partition table */
+static char *build_partition_table(unsigned char *tbl, QDiskPart *
qtbl)
+{
+ PTableEntry *pent;
+ char buf[64] = "";
+ int i = 0, n = 0;
+
+ /* Init first entry as the whole disk */
+ qtbl[0].start = 0;
+ qtbl[0].count = qemu_dsize / 512;
+ qtbl[0].type = 0;
+ qtbl[0].boot = 0;
+ qtbl[0].path = "/img";
+ n += fill_pent(qtbl, qemu_parttbl_str + n,
+ sizeof(qemu_parttbl_str) - n - 1);
+ if (n >= sizeof(qemu_parttbl_str) - 1)
+ return "parttbl string too large";
+ qemu_parttbl_str_len = n;
+
+ /*
+ * disk part tbl should be the last 66 bytes of the first
sector,
+ * last two bytes are magic.
+ */
+ if (tbl[DOS_PARTTBL_SZ - 2] != DOS_PARTTBL_MAGIC_LO ||
+ tbl[DOS_PARTTBL_SZ - 1] != DOS_PARTTBL_MAGIC_HI)
+ return NULL; /* no valid partition table, only /img
file will be created */
+
+ for (i = 1; i < DOS_PARTTBL_MAX_PART;
+ i++, tbl += DOS_PARTTBL_ENT_SZ) {
+ if (i >= QDISK_MAX_PART)
+ return "Internal: too much partitions";
+ pent = (void *) tbl;
+ qtbl[i].start = lt32_to_u32(pent->start_lba);
+ if (qtbl[i].start == 0)
+ continue;
+ qtbl[i].count = lt32_to_u32(pent->sectors_count);
+ qtbl[i].type = pent->part_type;
+ qtbl[i].boot = pent->bootdisk & 0x80;
+ snprintf(buf, sizeof(buf) - 1, "/img%d", i);
+ qtbl[i].path = strdup(buf);
+ n += fill_pent(qtbl + i, qemu_parttbl_str + n,
+ sizeof(qemu_parttbl_str) - n - 1);
+ if (n >= sizeof(qemu_parttbl_str) - 1)
+ return "parttbl string too large";
+ }
+ qemu_parttbl_str_len = n;
+ return NULL;
+}
+
+static int has_path(const char *path)
+{
+ int i;
+
+ if (!strcmp(path, qemu_parttbl_path))
+ return 1;
+ for (i = 0; i < QDISK_MAX_PART; i++)
+ if (!strcmp(path, qparttbl[i].path))
+ return 1;
+ return 0;
+}
+
+static QDiskPart *find_part(const char *path)
+{
+ int i;
+
+ for (i = 0; i < QDISK_MAX_PART; i++)
+ if (!strcmp(path, qparttbl[i].path))
+ return qparttbl + i;
+ return NULL;
+}
+
+static int qemu_parttbl_read(char *buf, int sz, long offset)
+{
+ if (offset >= qemu_parttbl_str_len)
+ return 0;
+
+ if (sz > qemu_parttbl_str_len - offset)
+ sz = qemu_parttbl_str_len - offset;
+
+ memcpy(buf, qemu_parttbl_str + offset, sz);
+
+ return sz;
+}
+
+static int qemu_getattr(const char *path, struct stat *stbuf)
+{
+ int i;
+
+ memset(stbuf, 0, sizeof(struct stat));
+ if (strcmp(path, "/") == 0) {
+ stbuf->st_mode = S_IFDIR | 0755;
+ stbuf->st_nlink = 2;
+ return 0;
+ }
+
+ if (strcmp(path, qemu_parttbl_path) == 0) {
+ stbuf->st_mode = S_IFREG | 0444;
+ stbuf->st_nlink = 1;
+ stbuf->st_size = qemu_parttbl_str_len;
+ return 0;
+ }
+
+ for (i = 0; i < QDISK_MAX_PART; i++) {
+ if (!qparttbl[i].path
+ || (strcmp(path, qparttbl[i].path) != 0))
+ continue;
+ stbuf->st_mode = S_IFREG | 0666;
+ stbuf->st_nlink = 1;
+ stbuf->st_size = (uint64_t) qparttbl[i].count * 512;
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
+static int qemu_readdir(const char *path, void *buf,
+ fuse_fill_dir_t filler, off_t offset,
+ struct fuse_file_info *fi)
+{
+ int i;
+
+ (void) offset;
+ (void) fi;
+
+ if (strcmp(path, "/") != 0)
+ return -ENOENT;
+
+ filler(buf, ".", NULL, 0);
+ filler(buf, "..", NULL, 0);
+ filler(buf, qemu_parttbl_path + 1, NULL, 0);
+ for (i = 0; i < QDISK_MAX_PART; i++)
+ if (qparttbl[i].path)
+ filler(buf, qparttbl[i].path + 1, NULL, 0);
+ return 0;
+}
+
+static int qemu_open(const char *path, struct fuse_file_info *fi)
+{
+ if (!has_path(path))
+ return -ENOENT;
+
+ return 0;
+}
+
+static int qemu_read(const char *path, char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ QDiskPart *qpart;
+
+ if (strcmp(path, qemu_parttbl_path) == 0)
+ return qemu_parttbl_read(buf, size, offset);
+ if (!(qpart = find_part(path)))
+ return -ENOENT;
+ return bdrv_pread(qemu_bs, offset + qpart->start * 512, buf,
size);
+}
+
+static int qemu_write(const char *path, const char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ QDiskPart *qpart;
+
+ fprintf(stderr, "W: path %s\n", path);
+ if (strcmp(path, qemu_parttbl_path) == 0)
+ return -EPERM;
+ if (!(qpart = find_part(path)))
+ return -ENOENT;
+ return bdrv_pwrite(qemu_bs, offset + qpart->start * 512, buf,
+ size);
+}
+
+static int qemu_flush(const char *path, struct fuse_file_info *fi)
+{
+ bdrv_flush(qemu_bs);
+ return 0;
+}
+
+/** Rename a file */
+//static int qemu_rename (const char *, const char *);
+
+/** Create a hard link to a file */
+//int qemu_link (const char *, const char *){}
+
+
+/** Change the permission bits of a file */
+static int qemu_chmod(const char *s, mode_t m)
+{
+ return 0;
+}
+
+/** Change the owner and group of a file */
+static int qemu_chown(const char *s, uid_t u, gid_t g)
+{
+ return 0;
+}
+
+ /** Change the size of a file */
+static int qemu_truncate(const char *s, off_t t)
+{
+ return 0;
+}
+
+/** Change the access and/or modification times of a file
+ *
+ * Deprecated, use utimens() instead.
+ */
+static int qemu_utime(const char *s, struct utimbuf *u)
+{
+ return 0;
+}
+
+static struct fuse_operations qemu_oper = {
+ .getattr = qemu_getattr,
+ .readdir = qemu_readdir,
+ .open = qemu_open,
+ .read = qemu_read,
+ .write = qemu_write,
+ .flush = qemu_flush,
+ // .rename = qemu_rename,
+ .chmod = qemu_chmod,
+ .chown = qemu_chown,
+ .truncate = qemu_truncate,
+ .utime = qemu_utime,
+};
+
+char *init_fs(void)
+{
+ unsigned char buf[DOS_PARTTBL_SZ];
+
+ if (bdrv_pread(qemu_bs, DOS_PARTTBL_OFFS, buf, DOS_PARTTBL_SZ)
!=
+ DOS_PARTTBL_SZ)
+ error("can't read partion table, bad read size");
+
+ return build_partition_table(buf, qparttbl);
+}
+
+int main(int argc, char *argv[])
+{
+ char *err, *filename, *fmt = NULL, **newargs;
+ int forground = 0, debug = 0;
+ int c, r;
+
+ prog = strrchr(argv[0], '/');
+ if (!prog)
+ prog = argv[0];
+
+ for (;;) {
+ /*
+ The + in the start of opsting is to force POSIX
parsing -
+ i.e. stop parsing at first non option. This is
required to
+ handle fuse options correctly. Without the +, the
getopt will
+ permute the options to force them at start...
+ */
+ c = getopt(argc, argv, "+f:hFd");
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'h':
+ help();
+ break;
+ case 'f':
+ fmt = optarg;
+ break;
+ case 'F':
+ forground = 1;
+ break;
+ case 'd':
+ debug = 1;
+ forground = 1;
+ break;
+ }
+ }
+ if (optind >= argc)
+ help();
+ filename = argv[optind++];
+
+
+ if (!forground) {
+ if ((r = fork()) < 0)
+ error("can't fork");
+ if (r > 0)
+ exit(0);
+ /* chield */
+ if (daemon(0, 0) < 0) {
+ error("qemu-fuse: failed to daemonize
program\n");
+ return -1;
+ }
+ }
+
+ bdrv_init();
+
+ open_img(filename, fmt);
+
+ if ((err = init_fs()))
+ error("init: %s", err);
+
+ // remove first arg and pass the rest to fuse_main
+ if (argc < optind)
+ error("Missing mount point");
+
+ argc -= optind - 1;
+
+ if (!(newargs = calloc(argc + 3, sizeof(char *))))
+ error("out of mem");
+ memcpy(newargs, argv + optind - 1, argc * sizeof(char *));
+ newargs[0] = argv[0];
+ newargs[argc] = "-s"; /* force single thread mode - qemu code
is not thread safe */
+ if (debug)
+ newargs[argc + 1] = "-d"; /* force debug and
forground mode */
+ else
+ newargs[argc + 1] = "-f"; /* force forground mode,
overcome signal masking problems */
+ newargs[argc + 2] = 0;
+
+ return fuse_main(argc + 2, newargs, &qemu_oper, NULL);
+}
Index: Makefile
===================================================================
--- Makefile (revision 5089)
+++ Makefile (working copy)
@@ -188,6 +188,14 @@
qemu-img-%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -DQEMU_IMG -c -o $@ $<
+ifdef CONFIG_FUSE
+qemu-fuse$(EXESUF): qemu-fuse.o qemu-img-block.o $(QEMU_IMG_BLOCK_OBJS)
+ $(CC) $(LDFLAGS) -o $@ $^ $(FUSELIBS) -lz $(LIBS)
+
+qemu-fuse.o: qemu-fuse.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -DQEMU_IMG
$(FUSEFLAGS) -g -c -o $@ $<
+endif
+
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
@@ -342,6 +350,7 @@
$(bindir)/qemu-cris \
$(bindir)/qemu-img \
$(bindir)/qemu-nbd \
+ $(bindir)/qemu-fuse \
$(datadir)/bios.bin \
$(datadir)/vgabios.bin \
$(datadir)/vgabios-cirrus.bin \
Index: configure
===================================================================
--- configure (revision 5089)
+++ configure (working copy)
@@ -110,6 +110,7 @@
aio="yes"
nptl="yes"
mixemu="no"
+fuse="no"
# OS specific
targetos=`uname -s`
@@ -340,6 +341,8 @@
;;
--disable-aio) aio="no"
;;
+ --enable-fuse) fuse="yes"
+ ;;
*) echo "ERROR: unknown option $opt"; show_help="yes"
;;
esac
@@ -436,6 +439,7 @@
echo " --sparc_cpu=V Build qemu for Sparc architecture v7,
v8, v8plus, v8plusa, v9"
echo " --disable-vde disable support for vde network"
echo " --disable-aio disable AIO support"
+echo " --enable-fuse enable fuse support"
echo ""
echo "NOTE: The object files are built at the place where configure is
launched"
exit 1
@@ -479,7 +483,11 @@
if [ "$bsd" = "yes" -o "$darwin" = "yes" -o "$mingw32" = "yes" ] ; then
AIOLIBS=
+ FUSELIBS=
+ FUSEFLAGS=
else
+ FUSELIBS="-lfuse"
+ FUSEFLAGS=-D_FILE_OFFSET_BITS=64
# Some Linux architectures (e.g. s390) don't imply -lpthread
automatically.
AIOLIBS="-lrt -lpthread"
fi
@@ -889,6 +897,22 @@
fi
fi
+##########################################
+# Fuse probe
+if test "$fuse" = "yes" ; then
+ fuse=no
+ cat > $TMPC << EOF
+#define FUSE_USE_VERSION 26
+#include <fuse/fuse_lowlevel.h>
+#include <fuse.h>
+static struct fuse_operations qemu_oper = {};
+int main(int argc, char **argv) { return fuse_main(argc, argv,
&qemu_oper, NULL);}
+EOF
+ if $cc $ARCH_CFLAGS $FUSEFLAGS -o $TMPE $FUSELIBS $TMPC 2> /dev/null
; then
+ fuse=yes
+ fi
+fi
+
# Check if tools are available to build documentation.
if [ -x "`which texi2html 2>/dev/null`" ] && \
[ -x "`which pod2man 2>/dev/null`" ]; then
@@ -961,6 +985,7 @@
echo "NPTL support $nptl"
echo "vde support $vde"
echo "AIO support $aio"
+echo "FUSE support $fuse"
if test $sdl_too_old = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL
support"
@@ -1007,6 +1032,9 @@
echo "LDFLAGS=$LDFLAGS" >> $config_mak
echo "EXESUF=$EXESUF" >> $config_mak
echo "AIOLIBS=$AIOLIBS" >> $config_mak
+echo "FUSELIBS=$FUSELIBS" >> $config_mak
+echo "FUSEFLAGS=$FUSEFLAGS" >> $config_mak
+
case "$cpu" in
i386)
echo "ARCH=i386" >> $config_mak
@@ -1216,6 +1244,10 @@
if test "$aio" = "yes" ; then
echo "#define CONFIG_AIO 1" >> $config_h
fi
+if test "$fuse" = "yes" ; then
+ echo "#define CONFIG_FUSE 1" >> $config_h
+ echo "CONFIG_FUSE=yes" >> $config_mak
+fi
# XXX: suppress that
if [ "$bsd" = "yes" ] ; then
@@ -1232,6 +1264,9 @@
if [ "$linux" = "yes" ] ; then
tools="qemu-nbd\$(EXESUF) $tools"
fi
+ if [ "$fuse" = "yes" ];then
+ tools="$tools qemu-fuse\$(EXESUF)"
+ fi
fi
echo "TOOLS=$tools" >> $config_mak
qemu-fuse-5089.patch
Description: qemu-fuse-5089.patch
- [Qemu-devel][PATCH] qemu-fuse,
Shahar Frank <=
- Re: [Qemu-devel][PATCH] qemu-fuse, Anthony Liguori, 2008/08/27
- Re: [Qemu-devel][PATCH] qemu-fuse, Luca Bigliardi, 2008/08/27
- Re: [Qemu-devel][PATCH] qemu-fuse, Anthony Liguori, 2008/08/27
- Re: [Qemu-devel][PATCH] qemu-fuse, Daniel P. Berrange, 2008/08/27
- Re: [Qemu-devel][PATCH] qemu-fuse, Jamie Lokier, 2008/08/27
- RE: [Qemu-devel][PATCH] qemu-fuse, Shahar Frank, 2008/08/28
- [Qemu-devel][PATCH] block level testing/execersing utility, Shahar Frank, 2008/08/28
- Re: [Qemu-devel][PATCH] block level testing/execersing utility, Samuel Thibault, 2008/08/28
- RE: [Qemu-devel][PATCH] block level testing/execersing utility, Shahar Frank, 2008/08/28
- Re: [Qemu-devel][PATCH] block level testing/execersing utility, Anthony Liguori, 2008/08/28