diff --git a/src/info.c b/src/info.c index 2ceddccf5..b5d192808 100644 --- a/src/info.c +++ b/src/info.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -235,17 +236,40 @@ static yajl_val get_json_output (guestfs_h *g, const char *filename) { CLEANUP_CMD_CLOSE struct command *cmd = guestfs___new_command (g); - int r; + int fd, r; + char fdpath[64]; yajl_val tree = NULL; + struct stat statbuf; + + fd = open (filename, O_RDONLY /* NB: !O_CLOEXEC */); + if (fd == -1) { + perrorf (g, "disk info: %s", filename); + return NULL; + } + + if (fstat (fd, &statbuf) == -1) { + perrorf (g, "disk info: fstat: %s", filename); + close (fd); + return NULL; + } + if (S_ISDIR (statbuf.st_mode)) { + error (g, "disk info: %s is a directory", filename); + close (fd); + return NULL; + } + + snprintf (fdpath, sizeof fdpath, "/dev/fd/%d", fd); + guestfs___cmd_clear_close_files (cmd); guestfs___cmd_add_arg (cmd, "qemu-img"); guestfs___cmd_add_arg (cmd, "info"); guestfs___cmd_add_arg (cmd, "--output"); guestfs___cmd_add_arg (cmd, "json"); - guestfs___cmd_add_arg (cmd, filename); + guestfs___cmd_add_arg (cmd, fdpath); guestfs___cmd_set_stdout_callback (cmd, parse_json, &tree, CMD_STDOUT_FLAG_WHOLE_BUFFER); r = guestfs___cmd_run (cmd); + close (fd); if (r == -1) return NULL; if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {