mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
daemon: Allow xorriso as an alternative to isoinfo.
Currently the guestfs_isoinfo and guestfs_isoinfo_device APIs run isoinfo inside the appliance to extract the information. isoinfo is part of genisoimage which is somewhat dead upstream. xorriso is supposedly the new thing. (For a summary of the situation see: https://wiki.debian.org/genisoimage). This commit rewrites the parsing from C to OCaml to make it easier to deal with, and allows you to use either isoinfo or xorriso. Mostly the same fields are available from either tool, but xorriso is a bit more awkward to parse.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -92,6 +92,7 @@ Makefile.in
|
||||
/daemon/guestfsd.exe
|
||||
/daemon/inspect.mli
|
||||
/daemon/is.mli
|
||||
/daemon/isoinfo.mli
|
||||
/daemon/ldm.mli
|
||||
/daemon/link.mli
|
||||
/daemon/listfs.mli
|
||||
|
||||
@@ -45,6 +45,7 @@ ifelse(REDHAT,1,
|
||||
syslinux-extlinux
|
||||
systemd dnl for /sbin/reboot and udevd
|
||||
vim-minimal
|
||||
xorriso dnl alternative for genisoimage
|
||||
xz
|
||||
zfs-fuse
|
||||
)
|
||||
@@ -84,6 +85,7 @@ dnl iproute has been renamed to iproute2
|
||||
systemd dnl alternative for /sbin/reboot
|
||||
ufsutils
|
||||
vim-tiny
|
||||
xorriso dnl alternative for genisoimage
|
||||
xz-utils
|
||||
zfs-fuse
|
||||
uuid-runtime
|
||||
|
||||
@@ -46,6 +46,7 @@ generator_built = \
|
||||
findfs.mli \
|
||||
inspect.mli \
|
||||
is.mli \
|
||||
isoinfo.mli \
|
||||
ldm.mli \
|
||||
link.mli \
|
||||
listfs.mli \
|
||||
@@ -142,7 +143,6 @@ guestfsd_SOURCES = \
|
||||
inotify.c \
|
||||
internal.c \
|
||||
is.c \
|
||||
isoinfo.c \
|
||||
journal.c \
|
||||
labels.c \
|
||||
ldm.c \
|
||||
@@ -291,6 +291,7 @@ SOURCES_MLI = \
|
||||
inspect_types.mli \
|
||||
inspect_utils.mli \
|
||||
is.mli \
|
||||
isoinfo.mli \
|
||||
ldm.mli \
|
||||
link.mli \
|
||||
listfs.mli \
|
||||
@@ -324,6 +325,7 @@ SOURCES_ML = \
|
||||
devsparts.ml \
|
||||
file.ml \
|
||||
filearch.ml \
|
||||
isoinfo.ml \
|
||||
is.ml \
|
||||
ldm.ml \
|
||||
link.ml \
|
||||
|
||||
279
daemon/isoinfo.c
279
daemon/isoinfo.c
@@ -1,279 +0,0 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2012 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "guestfs_protocol.h"
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
|
||||
static int
|
||||
parse_uint32 (uint32_t *ret, const char *str)
|
||||
{
|
||||
uint32_t r;
|
||||
|
||||
if (sscanf (str, "%" SCNu32, &r) != 1) {
|
||||
reply_with_error ("cannot parse numeric field from isoinfo: %s", str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ret = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is always in a fixed format:
|
||||
* "2012 03 16 11:05:46.00"
|
||||
* or if the field is not present, then:
|
||||
* "0000 00 00 00:00:00.00"
|
||||
*/
|
||||
static int
|
||||
parse_time_t (int64_t *ret, const char *str)
|
||||
{
|
||||
struct tm tm;
|
||||
time_t r;
|
||||
|
||||
if (STREQ (str, "0000 00 00 00:00:00.00") ||
|
||||
STREQ (str, " : : . ")) {
|
||||
*ret = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sscanf (str, "%04d %02d %02d %02d:%02d:%02d",
|
||||
&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
|
||||
&tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
|
||||
reply_with_error ("cannot parse date from isoinfo: %s", str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Adjust fields. */
|
||||
tm.tm_year -= 1900;
|
||||
tm.tm_mon--;
|
||||
tm.tm_isdst = -1;
|
||||
|
||||
/* Convert to time_t. */
|
||||
r = timegm (&tm);
|
||||
if (r == -1) {
|
||||
reply_with_error ("invalid date or time: %s", str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ret = r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static guestfs_int_isoinfo *
|
||||
parse_isoinfo (char **lines)
|
||||
{
|
||||
guestfs_int_isoinfo *ret;
|
||||
size_t i;
|
||||
|
||||
ret = calloc (1, sizeof *ret);
|
||||
if (ret == NULL) {
|
||||
reply_with_perror ("calloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Default each int field in the struct to -1. */
|
||||
ret->iso_volume_space_size = (uint32_t) -1;
|
||||
ret->iso_volume_set_size = (uint32_t) -1;
|
||||
ret->iso_volume_sequence_number = (uint32_t) -1;
|
||||
ret->iso_logical_block_size = (uint32_t) -1;
|
||||
ret->iso_volume_creation_t = -1;
|
||||
ret->iso_volume_modification_t = -1;
|
||||
ret->iso_volume_expiration_t = -1;
|
||||
ret->iso_volume_effective_t = -1;
|
||||
|
||||
for (i = 0; lines[i] != NULL; ++i) {
|
||||
if (STRPREFIX (lines[i], "System id: ")) {
|
||||
ret->iso_system_id = strdup (&lines[i][11]);
|
||||
if (ret->iso_system_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Volume id: ")) {
|
||||
ret->iso_volume_id = strdup (&lines[i][11]);
|
||||
if (ret->iso_volume_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Volume set id: ")) {
|
||||
ret->iso_volume_set_id = strdup (&lines[i][15]);
|
||||
if (ret->iso_volume_set_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Publisher id: ")) {
|
||||
ret->iso_publisher_id = strdup (&lines[i][14]);
|
||||
if (ret->iso_publisher_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Data preparer id: ")) {
|
||||
ret->iso_data_preparer_id = strdup (&lines[i][18]);
|
||||
if (ret->iso_data_preparer_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Application id: ")) {
|
||||
ret->iso_application_id = strdup (&lines[i][16]);
|
||||
if (ret->iso_application_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Copyright File id: ")) {
|
||||
ret->iso_copyright_file_id = strdup (&lines[i][19]);
|
||||
if (ret->iso_copyright_file_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Abstract File id: ")) {
|
||||
ret->iso_abstract_file_id = strdup (&lines[i][18]);
|
||||
if (ret->iso_abstract_file_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Bibliographic File id: ")) {
|
||||
ret->iso_bibliographic_file_id = strdup (&lines[i][23]);
|
||||
if (ret->iso_bibliographic_file_id == NULL) goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Volume size is: ")) {
|
||||
if (parse_uint32 (&ret->iso_volume_space_size, &lines[i][16]) == -1)
|
||||
goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Volume set size is: ")) {
|
||||
if (parse_uint32 (&ret->iso_volume_set_size, &lines[i][20]) == -1)
|
||||
goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Volume set sequence number is: ")) {
|
||||
if (parse_uint32 (&ret->iso_volume_sequence_number, &lines[i][31]) == -1)
|
||||
goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Logical block size is: ")) {
|
||||
if (parse_uint32 (&ret->iso_logical_block_size, &lines[i][23]) == -1)
|
||||
goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Creation Date: ")) {
|
||||
if (parse_time_t (&ret->iso_volume_creation_t, &lines[i][19]) == -1)
|
||||
goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Modification Date: ")) {
|
||||
if (parse_time_t (&ret->iso_volume_modification_t, &lines[i][19]) == -1)
|
||||
goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Expiration Date: ")) {
|
||||
if (parse_time_t (&ret->iso_volume_expiration_t, &lines[i][19]) == -1)
|
||||
goto error;
|
||||
}
|
||||
else if (STRPREFIX (lines[i], "Effective Date: ")) {
|
||||
if (parse_time_t (&ret->iso_volume_effective_t, &lines[i][19]) == -1)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Any string fields which were not set above will be NULL. However
|
||||
* we cannot return NULL fields in structs, so we convert these to
|
||||
* empty strings here.
|
||||
*/
|
||||
if (ret->iso_system_id == NULL) {
|
||||
ret->iso_system_id = strdup ("");
|
||||
if (ret->iso_system_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_volume_id == NULL) {
|
||||
ret->iso_volume_id = strdup ("");
|
||||
if (ret->iso_volume_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_volume_set_id == NULL) {
|
||||
ret->iso_volume_set_id = strdup ("");
|
||||
if (ret->iso_volume_set_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_publisher_id == NULL) {
|
||||
ret->iso_publisher_id = strdup ("");
|
||||
if (ret->iso_publisher_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_data_preparer_id == NULL) {
|
||||
ret->iso_data_preparer_id = strdup ("");
|
||||
if (ret->iso_data_preparer_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_application_id == NULL) {
|
||||
ret->iso_application_id = strdup ("");
|
||||
if (ret->iso_application_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_copyright_file_id == NULL) {
|
||||
ret->iso_copyright_file_id = strdup ("");
|
||||
if (ret->iso_copyright_file_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_abstract_file_id == NULL) {
|
||||
ret->iso_abstract_file_id = strdup ("");
|
||||
if (ret->iso_abstract_file_id == NULL) goto error;
|
||||
}
|
||||
if (ret->iso_bibliographic_file_id == NULL) {
|
||||
ret->iso_bibliographic_file_id = strdup ("");
|
||||
if (ret->iso_bibliographic_file_id == NULL) goto error;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
free (ret->iso_system_id);
|
||||
free (ret->iso_volume_id);
|
||||
free (ret->iso_volume_set_id);
|
||||
free (ret->iso_publisher_id);
|
||||
free (ret->iso_data_preparer_id);
|
||||
free (ret->iso_application_id);
|
||||
free (ret->iso_copyright_file_id);
|
||||
free (ret->iso_abstract_file_id);
|
||||
free (ret->iso_bibliographic_file_id);
|
||||
free (ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static guestfs_int_isoinfo *
|
||||
isoinfo (const char *path)
|
||||
{
|
||||
int r;
|
||||
CLEANUP_FREE char *out = NULL, *err = NULL;
|
||||
CLEANUP_FREE_STRING_LIST char **lines = NULL;
|
||||
|
||||
/* --debug is necessary to get additional fields, in particular
|
||||
* the date & time fields.
|
||||
*/
|
||||
r = command (&out, &err, "isoinfo", "--debug", "-d", "-i", path, NULL);
|
||||
if (r == -1) {
|
||||
reply_with_error ("%s", err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lines = split_lines (out);
|
||||
if (lines == NULL)
|
||||
return NULL;
|
||||
|
||||
return parse_isoinfo (lines);
|
||||
}
|
||||
|
||||
guestfs_int_isoinfo *
|
||||
do_isoinfo_device (const char *device)
|
||||
{
|
||||
return isoinfo (device);
|
||||
}
|
||||
|
||||
guestfs_int_isoinfo *
|
||||
do_isoinfo (const char *path)
|
||||
{
|
||||
guestfs_int_isoinfo *ret;
|
||||
CLEANUP_FREE char *buf = sysroot_path (path);
|
||||
if (!buf) {
|
||||
reply_with_perror ("malloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = isoinfo (buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
248
daemon/isoinfo.ml
Normal file
248
daemon/isoinfo.ml
Normal file
@@ -0,0 +1,248 @@
|
||||
(* Parse isoinfo or xorriso output.
|
||||
* Copyright (C) 2009-2021 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*)
|
||||
|
||||
open Printf
|
||||
open Scanf
|
||||
open Unix
|
||||
|
||||
open Std_utils
|
||||
open Unix_utils
|
||||
|
||||
open Mountable
|
||||
open Utils
|
||||
|
||||
include Structs
|
||||
|
||||
type tool = Isoinfo | Xorriso
|
||||
let tool = ref None
|
||||
|
||||
let get_tool () =
|
||||
match !tool with
|
||||
| Some t -> t
|
||||
| None ->
|
||||
(* Prefer isoinfo because we've been using that tool for longer. *)
|
||||
if Sys.command "isoinfo -version" = 0 then (
|
||||
tool := Some Isoinfo;
|
||||
Isoinfo
|
||||
)
|
||||
else if Sys.command "xorriso -version" = 0 then (
|
||||
tool := Some Xorriso;
|
||||
Xorriso
|
||||
)
|
||||
else
|
||||
failwith "isoinfo or xorriso not available"
|
||||
|
||||
(* Default each int field in the struct to -1 and each string to "". *)
|
||||
let default_iso = {
|
||||
iso_system_id = "";
|
||||
iso_volume_id = "";
|
||||
iso_volume_space_size = -1_l;
|
||||
iso_volume_set_size = -1_l;
|
||||
iso_volume_sequence_number = -1_l;
|
||||
(* This is almost always true for CDs because of the media itself,
|
||||
* and is not available from xorriso.
|
||||
*)
|
||||
iso_logical_block_size = 2048_l;
|
||||
iso_volume_set_id = "";
|
||||
iso_publisher_id = "";
|
||||
iso_data_preparer_id = "";
|
||||
iso_application_id = "";
|
||||
iso_copyright_file_id = "";
|
||||
iso_abstract_file_id = "";
|
||||
iso_bibliographic_file_id = "";
|
||||
iso_volume_creation_t = -1_L;
|
||||
iso_volume_modification_t = -1_L;
|
||||
iso_volume_expiration_t = -1_L;
|
||||
iso_volume_effective_t = -1_L;
|
||||
}
|
||||
|
||||
(* This is always in a fixed format:
|
||||
* "2012 03 16 11:05:46.00"
|
||||
* or if the field is not present, then:
|
||||
* "0000 00 00 00:00:00.00"
|
||||
*)
|
||||
let parse_isoinfo_date str =
|
||||
if str = "0000 00 00 00:00:00.00" ||
|
||||
str = " : : . " then
|
||||
-1_L
|
||||
else (
|
||||
sscanf str "%04d %02d %02d %02d:%02d:%02d"
|
||||
(fun tm_year tm_mon tm_mday tm_hour tm_min tm_sec ->
|
||||
(* Adjust fields. *)
|
||||
let tm_year = tm_year - 1900 in
|
||||
let tm_mon = tm_mon - 1 in
|
||||
|
||||
(* Convert to time_t *)
|
||||
let tm = { tm_sec; tm_min; tm_hour; tm_mday; tm_mon; tm_year;
|
||||
tm_wday = -1; tm_yday = -1; tm_isdst = false } in
|
||||
Int64.of_float (fst (Unix.mktime tm))
|
||||
)
|
||||
)
|
||||
|
||||
let do_isoinfo dev =
|
||||
(* --debug is necessary to get additional fields, in particular
|
||||
* the date & time fields.
|
||||
*)
|
||||
let lines = command "isoinfo" ["--debug"; "-d"; "-i"; dev] in
|
||||
let lines = String.nsplit "\n" lines in
|
||||
|
||||
let ret = ref default_iso in
|
||||
List.iter (
|
||||
fun line ->
|
||||
let n = String.length line in
|
||||
if String.is_prefix line "System id: " then
|
||||
ret := { !ret with iso_system_id = String.sub line 11 (n-11) }
|
||||
else if String.is_prefix line "Volume id: " then
|
||||
ret := { !ret with iso_volume_id = String.sub line 11 (n-11) }
|
||||
else if String.is_prefix line "Volume set id: " then
|
||||
ret := { !ret with iso_volume_set_id = String.sub line 15 (n-15) }
|
||||
else if String.is_prefix line "Publisher id: " then
|
||||
ret := { !ret with iso_publisher_id = String.sub line 14 (n-14) }
|
||||
else if String.is_prefix line "Data preparer id: " then
|
||||
ret := { !ret with iso_data_preparer_id = String.sub line 18 (n-18) }
|
||||
else if String.is_prefix line "Application id: " then
|
||||
ret := { !ret with iso_application_id = String.sub line 16 (n-16) }
|
||||
else if String.is_prefix line "Copyright File id: " then
|
||||
ret := { !ret with iso_copyright_file_id = String.sub line 19 (n-19) }
|
||||
else if String.is_prefix line "Abstract File id: " then
|
||||
ret := { !ret with iso_abstract_file_id = String.sub line 18 (n-18) }
|
||||
else if String.is_prefix line "Bibliographic File id: " then
|
||||
ret := { !ret with
|
||||
iso_bibliographic_file_id = String.sub line 23 (n-23) }
|
||||
else if String.is_prefix line "Volume size is: " then (
|
||||
let i = Int32.of_string (String.sub line 16 (n-16)) in
|
||||
ret := { !ret with iso_volume_space_size = i }
|
||||
)
|
||||
else if String.is_prefix line "Volume set size is: " then (
|
||||
let i = Int32.of_string (String.sub line 20 (n-20)) in
|
||||
ret := { !ret with iso_volume_set_size = i }
|
||||
)
|
||||
else if String.is_prefix line "Volume set sequence number is: " then (
|
||||
let i = Int32.of_string (String.sub line 31 (n-31)) in
|
||||
ret := { !ret with iso_volume_sequence_number = i }
|
||||
)
|
||||
else if String.is_prefix line "Logical block size is: " then (
|
||||
let i = Int32.of_string (String.sub line 23 (n-23)) in
|
||||
ret := { !ret with iso_logical_block_size = i }
|
||||
)
|
||||
else if String.is_prefix line "Creation Date: " then (
|
||||
let t = parse_isoinfo_date (String.sub line 19 (n-19)) in
|
||||
ret := { !ret with iso_volume_creation_t = t }
|
||||
)
|
||||
else if String.is_prefix line "Modification Date: " then (
|
||||
let t = parse_isoinfo_date (String.sub line 19 (n-19)) in
|
||||
ret := { !ret with iso_volume_modification_t = t }
|
||||
)
|
||||
else if String.is_prefix line "Expiration Date: " then (
|
||||
let t = parse_isoinfo_date (String.sub line 19 (n-19)) in
|
||||
ret := { !ret with iso_volume_expiration_t = t }
|
||||
)
|
||||
else if String.is_prefix line "Effective Date: " then (
|
||||
let t = parse_isoinfo_date (String.sub line 19 (n-19)) in
|
||||
ret := { !ret with iso_volume_effective_t = t }
|
||||
)
|
||||
) lines;
|
||||
!ret
|
||||
|
||||
(* This is always in a fixed format:
|
||||
* "2021033012313200"
|
||||
* or if the field is not present, then:
|
||||
* "0000000000000000"
|
||||
* XXX Parse the time zone fields too.
|
||||
*)
|
||||
let parse_xorriso_date str =
|
||||
if str = "0000000000000000" then -1_L
|
||||
else if String.length str <> 16 then -1_L
|
||||
else (
|
||||
let tm_year = int_of_string (String.sub str 0 4) in
|
||||
let tm_mon = int_of_string (String.sub str 4 2) in
|
||||
let tm_mday = int_of_string (String.sub str 6 2) in
|
||||
let tm_hour = int_of_string (String.sub str 8 2) in
|
||||
let tm_min = int_of_string (String.sub str 10 2) in
|
||||
let tm_sec = int_of_string (String.sub str 12 2) in
|
||||
|
||||
(* Adjust fields. *)
|
||||
let tm_year = tm_year - 1900 in
|
||||
let tm_mon = tm_mon - 1 in
|
||||
|
||||
(* Convert to time_t *)
|
||||
let tm = { tm_sec; tm_min; tm_hour; tm_mday; tm_mon; tm_year;
|
||||
tm_wday = -1; tm_yday = -1; tm_isdst = false } in
|
||||
Int64.of_float (fst (Unix.mktime tm))
|
||||
)
|
||||
|
||||
let do_xorriso dev =
|
||||
(* stdio: prefix is to work around a stupidity of xorriso. *)
|
||||
let lines = command "xorriso" ["-indev"; "stdio:" ^ dev; "-pvd_info"] in
|
||||
let lines = String.nsplit "\n" lines in
|
||||
|
||||
let ret = ref default_iso in
|
||||
List.iter (
|
||||
fun line ->
|
||||
let n = String.length line in
|
||||
if String.is_prefix line "System Id : " then
|
||||
ret := { !ret with iso_system_id = String.sub line 15 (n-15) }
|
||||
else if String.is_prefix line "Volume Id : " then
|
||||
ret := { !ret with iso_volume_id = String.sub line 15 (n-15) }
|
||||
else if String.is_prefix line "Volume Set Id: " then
|
||||
ret := { !ret with iso_volume_set_id = String.sub line 15 (n-15) }
|
||||
else if String.is_prefix line "Publisher Id : " then
|
||||
ret := { !ret with iso_publisher_id = String.sub line 15 (n-15) }
|
||||
else if String.is_prefix line "App Id : " then
|
||||
ret := { !ret with iso_application_id = String.sub line 15 (n-15) }
|
||||
else if String.is_prefix line "CopyrightFile: " then
|
||||
ret := { !ret with iso_copyright_file_id = String.sub line 15 (n-15) }
|
||||
else if String.is_prefix line "Abstract File: " then
|
||||
ret := { !ret with iso_abstract_file_id = String.sub line 15 (n-15) }
|
||||
else if String.is_prefix line "Biblio File : " then
|
||||
ret := { !ret with
|
||||
iso_bibliographic_file_id = String.sub line 15 (n-15) }
|
||||
(* XXX The following fields don't appear to be available
|
||||
* with xorriso:
|
||||
* - iso_volume_space_size (only available on stderr)
|
||||
* - iso_volume_sequence_number
|
||||
* - iso_logical_block_size
|
||||
*)
|
||||
(* XXX xorriso provides a timezone for these fields, but
|
||||
* we don't use it here.
|
||||
*)
|
||||
else if String.is_prefix line "Creation Time: " then (
|
||||
let t = parse_xorriso_date (String.sub line 15 (n-15)) in
|
||||
ret := { !ret with iso_volume_creation_t = t }
|
||||
)
|
||||
else if String.is_prefix line "Modif. Time : " then (
|
||||
let t = parse_xorriso_date (String.sub line 15 (n-15)) in
|
||||
ret := { !ret with iso_volume_modification_t = t }
|
||||
)
|
||||
else if String.is_prefix line "Expir. Time : " then (
|
||||
let t = parse_xorriso_date (String.sub line 15 (n-15)) in
|
||||
ret := { !ret with iso_volume_expiration_t = t }
|
||||
)
|
||||
else if String.is_prefix line "Eff. Time : " then (
|
||||
let t = parse_xorriso_date (String.sub line 15 (n-15)) in
|
||||
ret := { !ret with iso_volume_effective_t = t }
|
||||
)
|
||||
) lines;
|
||||
!ret
|
||||
|
||||
let isoinfo dev =
|
||||
match get_tool () with
|
||||
| Isoinfo -> do_isoinfo dev
|
||||
| Xorriso -> do_xorriso dev
|
||||
|
||||
let isoinfo_device = isoinfo
|
||||
@@ -103,7 +103,6 @@ daemon/initrd.c
|
||||
daemon/inotify.c
|
||||
daemon/internal.c
|
||||
daemon/is.c
|
||||
daemon/isoinfo.c
|
||||
daemon/journal.c
|
||||
daemon/labels.c
|
||||
daemon/ldm.c
|
||||
|
||||
@@ -6878,6 +6878,7 @@ this will create the largest possible LV." };
|
||||
{ defaults with
|
||||
name = "isoinfo_device"; added = (1, 17, 19);
|
||||
style = RStruct ("isodata", "isoinfo"), [String (Device, "device")], [];
|
||||
impl = OCaml "Isoinfo.isoinfo_device";
|
||||
tests = [
|
||||
InitNone, Always, TestResult (
|
||||
[["isoinfo_device"; "/dev/sdd"]],
|
||||
@@ -6904,6 +6905,7 @@ L<https://wiki.osdev.org/ISO_9660#The_Primary_Volume_Descriptor>" };
|
||||
{ defaults with
|
||||
name = "isoinfo"; added = (1, 17, 19);
|
||||
style = RStruct ("isodata", "isoinfo"), [String (Pathname, "isofile")], [];
|
||||
impl = OCaml "Isoinfo.isoinfo";
|
||||
shortdesc = "get ISO information from primary volume descriptor of ISO file";
|
||||
longdesc = "\
|
||||
This is the same as C<guestfs_isoinfo_device> except that it
|
||||
|
||||
@@ -82,7 +82,6 @@ daemon/initrd.c
|
||||
daemon/inotify.c
|
||||
daemon/internal.c
|
||||
daemon/is.c
|
||||
daemon/isoinfo.c
|
||||
daemon/journal.c
|
||||
daemon/labels.c
|
||||
daemon/ldm.c
|
||||
|
||||
Reference in New Issue
Block a user