New upstream version 1.45.4.
This commit is contained in:
parent
a6a11a65c9
commit
6ab119c488
@ -1,35 +0,0 @@
|
||||
From 49b8b69cb8e10e5476bbe86a708ee1babfe330e8 Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Tue, 30 Mar 2021 12:56:06 +0100
|
||||
Subject: [PATCH 1/5] daemon/xfs.c: Fix error message.
|
||||
|
||||
Fixes: commit 87206e4e9e3b0ca813a4ff7b5fac0eccc07a484a
|
||||
---
|
||||
daemon/xfs.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/daemon/xfs.c b/daemon/xfs.c
|
||||
index 3707f56d9..aa056ddff 100644
|
||||
--- a/daemon/xfs.c
|
||||
+++ b/daemon/xfs.c
|
||||
@@ -62,7 +62,7 @@ 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);
|
||||
+ reply_with_error ("cannot parse numeric field from xfs_info: %s", str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ parse_uint64 (uint64_t *ret, const char *str)
|
||||
uint64_t r;
|
||||
|
||||
if (sscanf (str, "%" SCNu64, &r) != 1) {
|
||||
- reply_with_error ("cannot parse numeric field from isoinfo: %s", str);
|
||||
+ reply_with_error ("cannot parse numeric field from xfs_info: %s", str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
--
|
||||
2.29.0.rc2
|
||||
|
@ -1,67 +0,0 @@
|
||||
From 2216ab2e328457ef172d6bfa534272edf2f81a3a Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Tue, 30 Mar 2021 12:41:58 +0100
|
||||
Subject: [PATCH 2/5] tests: Prefer xorriso over genisoimage to generate
|
||||
test.iso
|
||||
|
||||
This Debian page explains the upstream situation:
|
||||
https://wiki.debian.org/genisoimage
|
||||
|
||||
On Fedora, xorriso provides a compatibility program called "mkisofs".
|
||||
However this is not present in Debian. Hence the choice to look for
|
||||
the program called "xorrisofs".
|
||||
---
|
||||
docs/guestfs-building.pod | 4 ++--
|
||||
m4/guestfs-progs.m4 | 6 +++---
|
||||
test-data/Makefile.am | 2 +-
|
||||
3 files changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/docs/guestfs-building.pod b/docs/guestfs-building.pod
|
||||
index 8fb2361b2..4d0e943cb 100644
|
||||
--- a/docs/guestfs-building.pod
|
||||
+++ b/docs/guestfs-building.pod
|
||||
@@ -152,9 +152,9 @@ I<Required>.
|
||||
|
||||
I<Required>.
|
||||
|
||||
-=item genisoimage
|
||||
+=item xorriso, genisoimage or mkisofs
|
||||
|
||||
-I<Required>.
|
||||
+One of these is I<Required>.
|
||||
|
||||
=item libxml2
|
||||
|
||||
diff --git a/m4/guestfs-progs.m4 b/m4/guestfs-progs.m4
|
||||
index 4819df627..cd8662e86 100644
|
||||
--- a/m4/guestfs-progs.m4
|
||||
+++ b/m4/guestfs-progs.m4
|
||||
@@ -49,10 +49,10 @@ AC_CHECK_PROG([GPERF],[gperf],[gperf],[no])
|
||||
test "x$GPERF" = "xno" &&
|
||||
AC_MSG_ERROR([gperf must be installed])
|
||||
|
||||
-dnl Check for genisoimage/mkisofs
|
||||
-AC_PATH_PROGS([GENISOIMAGE],[genisoimage mkisofs],[no],
|
||||
+dnl Check for xorriso/genisoimage/mkisofs.
|
||||
+AC_PATH_PROGS([MKISOFS],[xorrisofs genisoimage mkisofs],[no],
|
||||
[$PATH$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin])
|
||||
-test "x$GENISOIMAGE" = "xno" && AC_MSG_ERROR([genisoimage must be installed])
|
||||
+test "x$MKISOFS" = "xno" && AC_MSG_ERROR([xorriso or genisoimage or mkisofs must be installed])
|
||||
|
||||
dnl Check for optional xmllint.
|
||||
AC_CHECK_PROG([XMLLINT],[xmllint],[xmllint],[no])
|
||||
diff --git a/test-data/Makefile.am b/test-data/Makefile.am
|
||||
index 8a832c94c..b603311a1 100644
|
||||
--- a/test-data/Makefile.am
|
||||
+++ b/test-data/Makefile.am
|
||||
@@ -98,6 +98,6 @@ test.iso: $(images_files)
|
||||
cp $(image_files) d/
|
||||
mkdir -p d/directory
|
||||
cd d && ln -sf /10klines abssymlink
|
||||
- cd d && $(GENISOIMAGE) -J -r -o ../$@-t .
|
||||
+ cd d && $(MKISOFS) -J -r -o ../$@-t .
|
||||
rm -rf d
|
||||
mv $@-t $@
|
||||
--
|
||||
2.29.0.rc2
|
||||
|
@ -1,684 +0,0 @@
|
||||
From efb8a766cac4ba8e413594946136bf91e176bb8c Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Tue, 30 Mar 2021 13:54:22 +0100
|
||||
Subject: [PATCH 3/5] 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.
|
||||
---
|
||||
.gitignore | 1 +
|
||||
appliance/packagelist.in | 2 +
|
||||
daemon/Makefile.am | 4 +-
|
||||
daemon/isoinfo.c | 279 --------------------------------------
|
||||
daemon/isoinfo.ml | 248 +++++++++++++++++++++++++++++++++
|
||||
docs/C_SOURCE_FILES | 1 -
|
||||
generator/actions_core.ml | 2 +
|
||||
po/POTFILES | 1 -
|
||||
8 files changed, 256 insertions(+), 282 deletions(-)
|
||||
delete mode 100644 daemon/isoinfo.c
|
||||
create mode 100644 daemon/isoinfo.ml
|
||||
|
||||
diff --git a/.gitignore b/.gitignore
|
||||
index f9b95a6c5..de4abff58 100644
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -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
|
||||
diff --git a/appliance/packagelist.in b/appliance/packagelist.in
|
||||
index 2f75a1c17..f4ad50b79 100644
|
||||
--- a/appliance/packagelist.in
|
||||
+++ b/appliance/packagelist.in
|
||||
@@ -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
|
||||
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
|
||||
index 216029b7c..6f13bd43c 100644
|
||||
--- a/daemon/Makefile.am
|
||||
+++ b/daemon/Makefile.am
|
||||
@@ -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 \
|
||||
diff --git a/daemon/isoinfo.c b/daemon/isoinfo.c
|
||||
deleted file mode 100644
|
||||
index e616df82f..000000000
|
||||
--- a/daemon/isoinfo.c
|
||||
+++ /dev/null
|
||||
@@ -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;
|
||||
-}
|
||||
diff --git a/daemon/isoinfo.ml b/daemon/isoinfo.ml
|
||||
new file mode 100644
|
||||
index 000000000..b7fe0af7e
|
||||
--- /dev/null
|
||||
+++ b/daemon/isoinfo.ml
|
||||
@@ -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
|
||||
diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES
|
||||
index 060be051b..e65c2f9d9 100644
|
||||
--- a/docs/C_SOURCE_FILES
|
||||
+++ b/docs/C_SOURCE_FILES
|
||||
@@ -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
|
||||
diff --git a/generator/actions_core.ml b/generator/actions_core.ml
|
||||
index bb92ef2ca..40505d8b5 100644
|
||||
--- a/generator/actions_core.ml
|
||||
+++ b/generator/actions_core.ml
|
||||
@@ -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
|
||||
diff --git a/po/POTFILES b/po/POTFILES
|
||||
index c5f4e6aa7..717579d56 100644
|
||||
--- a/po/POTFILES
|
||||
+++ b/po/POTFILES
|
||||
@@ -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
|
||||
--
|
||||
2.29.0.rc2
|
||||
|
@ -1,405 +0,0 @@
|
||||
From 2f587bbaec718e414e46c7e6f2a3e2662c3a1c2a Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Wed, 31 Mar 2021 10:32:52 +0100
|
||||
Subject: [PATCH 4/5] daemon: Read ISO9660 Primary Volume Descriptor directly.
|
||||
|
||||
It turns out we can read the information we need for the isoinfo API
|
||||
directly from the ISO9660 PVD. We don't need to use either isoinfo or
|
||||
xorriso. This also has the advantages of reducing by 1 the number of
|
||||
dependencies in the appliance, and reducing potential vulnerability to
|
||||
a crafted ISO file.
|
||||
|
||||
This also fixes timezone calculation for the datetime fields.
|
||||
|
||||
Thanks: Thomas Schmitt
|
||||
Updates: commit efb8a766cac4ba8e413594946136bf91e176bb8c
|
||||
---
|
||||
appliance/packagelist.in | 10 --
|
||||
daemon/isoinfo.ml | 282 ++++++++++++---------------------------
|
||||
2 files changed, 82 insertions(+), 210 deletions(-)
|
||||
|
||||
diff --git a/appliance/packagelist.in b/appliance/packagelist.in
|
||||
index f4ad50b79..cede0ac0b 100644
|
||||
--- a/appliance/packagelist.in
|
||||
+++ b/appliance/packagelist.in
|
||||
@@ -26,7 +26,6 @@ ifelse(REDHAT,1,
|
||||
cryptsetup
|
||||
cryptsetup-luks dnl old name used before Fedora 17
|
||||
dhclient
|
||||
- genisoimage
|
||||
gfs-utils
|
||||
gfs2-utils
|
||||
grub
|
||||
@@ -45,7 +44,6 @@ ifelse(REDHAT,1,
|
||||
syslinux-extlinux
|
||||
systemd dnl for /sbin/reboot and udevd
|
||||
vim-minimal
|
||||
- xorriso dnl alternative for genisoimage
|
||||
xz
|
||||
zfs-fuse
|
||||
)
|
||||
@@ -57,7 +55,6 @@ dnl old name used in Jessie and earlier
|
||||
cryptsetup
|
||||
dash
|
||||
extlinux
|
||||
- genisoimage
|
||||
dnl gfs-tools, gfs2-tools have been renamed to gfs2-utils
|
||||
gfs-tools
|
||||
gfs2-tools
|
||||
@@ -85,7 +82,6 @@ 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
|
||||
@@ -124,13 +120,11 @@ ifelse(SUSE,1,
|
||||
cryptsetup
|
||||
dhcpcd
|
||||
dhcp-client
|
||||
- genisoimage
|
||||
glibc-locale
|
||||
gptfdisk
|
||||
initviocons
|
||||
iproute2
|
||||
iputils
|
||||
- mkisofs
|
||||
ntfsprogs
|
||||
ntfs-3g
|
||||
reiserfs
|
||||
@@ -164,8 +158,6 @@ ifelse(FRUGALWARE,1,
|
||||
ifelse(MAGEIA,1,
|
||||
cryptsetup
|
||||
chkconfig /* for /etc/init.d */
|
||||
- cdrkit-genisoimage
|
||||
- cdrkit-isotools
|
||||
dhcp-client
|
||||
extlinux
|
||||
gfs2-utils
|
||||
@@ -190,8 +182,6 @@ ifelse(MAGEIA,1,
|
||||
ifelse(OPENMANDRIVA,1,
|
||||
cryptsetup
|
||||
chkconfig /* for /etc/init.d */
|
||||
- cdrkit-genisoimage
|
||||
- cdrkit-isotools
|
||||
dhcp-client
|
||||
extlinux
|
||||
grub2
|
||||
diff --git a/daemon/isoinfo.ml b/daemon/isoinfo.ml
|
||||
index b7fe0af7e..448563365 100644
|
||||
--- a/daemon/isoinfo.ml
|
||||
+++ b/daemon/isoinfo.ml
|
||||
@@ -17,157 +17,32 @@
|
||||
*)
|
||||
|
||||
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"
|
||||
+(* We treat ISO "strA" and "strD" formats the same way, simply
|
||||
+ * discarding any trailing spaces.
|
||||
*)
|
||||
-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
|
||||
+let iso_parse_strA str =
|
||||
+ let len = String.length str in
|
||||
+ let rec loop len =
|
||||
+ if len > 0 && str.[len-1] = ' ' then loop (len-1) else len
|
||||
+ in
|
||||
+ let len = loop len in
|
||||
+ String.sub str 0 len
|
||||
|
||||
- (* 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 iso_parse_strD = iso_parse_strA
|
||||
|
||||
-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
|
||||
+(* These always parse the intX_LSB (little endian) version. *)
|
||||
+let iso_parse_int16 s = s |> int_of_le16 |> Int64.to_int32
|
||||
+let iso_parse_int32 s = s |> int_of_le32 |> Int64.to_int32
|
||||
|
||||
- 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
|
||||
+(* Parse ISO dec-datetime to a Unix time_t. *)
|
||||
+let iso_parse_datetime str =
|
||||
+ if String.sub str 0 16 = "0000000000000000" 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
|
||||
@@ -180,69 +55,76 @@ let parse_xorriso_date str =
|
||||
let tm_year = tm_year - 1900 in
|
||||
let tm_mon = tm_mon - 1 in
|
||||
|
||||
- (* Convert to time_t *)
|
||||
+ (* Convert to time_t in UTC timezone. *)
|
||||
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 old_TZ = try Some (getenv "TZ") with Not_found -> None in
|
||||
+ putenv "TZ" "UTC";
|
||||
+ let r = Int64.of_float (fst (mktime tm)) in
|
||||
+ Option.may (putenv "TZ") old_TZ;
|
||||
+
|
||||
+ (* The final byte is a time zone offset from GMT.
|
||||
+ *
|
||||
+ * The documentation of this at
|
||||
+ * https://wiki.osdev.org/ISO_9660#The_Primary_Volume_Descriptor
|
||||
+ * is wrong. See the ECMA 119 documentation for a correct
|
||||
+ * description.
|
||||
+ *
|
||||
+ * For a disk image which we know was created
|
||||
+ * in BST (GMT+1), this contains 0x4, ie. 4 * 15 mins ahead.
|
||||
+ * We have to subtract this from the gmtime above.
|
||||
+ *)
|
||||
+ let tz = Char.code str.[16] in
|
||||
+ let tz = if tz >= 128 then tz - 256 else tz in
|
||||
+ r -^ (Int64.of_int (tz * 15 * 60))
|
||||
)
|
||||
|
||||
-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 r, pvd =
|
||||
+ with_openfile dev [O_RDONLY] 0 (
|
||||
+ fun fd ->
|
||||
+ ignore (lseek fd 32768 SEEK_SET);
|
||||
+ let pvd = Bytes.create 2048 in
|
||||
+ let r = read fd pvd 0 2048 in
|
||||
+ r, Bytes.to_string pvd
|
||||
+ ) in
|
||||
+
|
||||
+ let sub = String.sub pvd in
|
||||
+
|
||||
+ (* Check that it looks like an ISO9660 Primary Volume Descriptor.
|
||||
+ * https://wiki.osdev.org/ISO_9660#The_Primary_Volume_Descriptor
|
||||
+ *)
|
||||
+ if r <> 2048 || pvd.[0] <> '\001' || sub 1 5 <> "CD001" then
|
||||
+ failwithf "%s: not an ISO file or CD-ROM" dev;
|
||||
+
|
||||
+ (* Parse out the PVD fields. *)
|
||||
+ let iso_system_id = sub 8 32 |> iso_parse_strA in
|
||||
+ let iso_volume_id = sub 40 32 |> iso_parse_strA in
|
||||
+ let iso_volume_space_size = sub 80 4 |> iso_parse_int32 in
|
||||
+ let iso_volume_set_size = sub 120 2 |> iso_parse_int16 in
|
||||
+ let iso_volume_sequence_number = sub 124 2 |> iso_parse_int16 in
|
||||
+ let iso_logical_block_size = sub 128 2 |> iso_parse_int16 in
|
||||
+ let iso_volume_set_id = sub 190 128 |> iso_parse_strD in
|
||||
+ let iso_publisher_id = sub 318 128 |> iso_parse_strA in
|
||||
+ let iso_data_preparer_id = sub 446 128 |> iso_parse_strA in
|
||||
+ let iso_application_id = sub 574 128 |> iso_parse_strA in
|
||||
+ let iso_copyright_file_id = sub 702 38 |> iso_parse_strD in
|
||||
+ let iso_abstract_file_id = sub 740 36 |> iso_parse_strD in
|
||||
+ let iso_bibliographic_file_id = sub 776 37 |> iso_parse_strD in
|
||||
+ let iso_volume_creation_t = sub 813 17 |> iso_parse_datetime in
|
||||
+ let iso_volume_modification_t = sub 830 17 |> iso_parse_datetime in
|
||||
+ let iso_volume_expiration_t = sub 847 17 |> iso_parse_datetime in
|
||||
+ let iso_volume_effective_t = sub 864 17 |> iso_parse_datetime in
|
||||
+
|
||||
+ (* Return the struct. *)
|
||||
+ {
|
||||
+ iso_system_id; iso_volume_id; iso_volume_space_size;
|
||||
+ iso_volume_set_size; iso_volume_sequence_number;
|
||||
+ iso_logical_block_size; 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; iso_volume_modification_t;
|
||||
+ iso_volume_expiration_t; iso_volume_effective_t;
|
||||
+ }
|
||||
|
||||
let isoinfo_device = isoinfo
|
||||
--
|
||||
2.29.0.rc2
|
||||
|
@ -1,127 +0,0 @@
|
||||
From 278d0d3226f4bdb7c6586986ca46d0a25c976fe4 Mon Sep 17 00:00:00 2001
|
||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||
Date: Wed, 31 Mar 2021 13:40:11 +0100
|
||||
Subject: [PATCH 5/5] lib/appliance-kcmdline.c: Read UUID directly from
|
||||
appliance.
|
||||
|
||||
Instead of using the external file utility, read the UUID directly
|
||||
from the extfs filesystem. file 5.40 broke parsing of UUIDs
|
||||
(https://bugs.astron.com/view.php?id=253).
|
||||
|
||||
Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1945122
|
||||
---
|
||||
lib/appliance-kcmdline.c | 75 +++++++++++++++++++++++++---------------
|
||||
1 file changed, 48 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/lib/appliance-kcmdline.c b/lib/appliance-kcmdline.c
|
||||
index 6d0deef86..8b78655eb 100644
|
||||
--- a/lib/appliance-kcmdline.c
|
||||
+++ b/lib/appliance-kcmdline.c
|
||||
@@ -27,6 +27,9 @@
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <libintl.h>
|
||||
+#include <sys/types.h>
|
||||
|
||||
#include "c-ctype.h"
|
||||
#include "ignore-value.h"
|
||||
@@ -56,49 +59,67 @@
|
||||
#define EARLYPRINTK "earlyprintk=pl011,0x9000000"
|
||||
#endif
|
||||
|
||||
-COMPILE_REGEXP (re_uuid, "UUID=([-0-9a-f]+)", 0)
|
||||
-
|
||||
-static void
|
||||
-read_uuid (guestfs_h *g, void *retv, const char *line, size_t len)
|
||||
-{
|
||||
- char **ret = retv;
|
||||
-
|
||||
- *ret = match1 (g, line, re_uuid);
|
||||
-}
|
||||
-
|
||||
/**
|
||||
* Given a disk image containing an extX filesystem, return the UUID.
|
||||
- * The L<file(1)> command does the hard work.
|
||||
*/
|
||||
static char *
|
||||
get_root_uuid_with_file (guestfs_h *g, const char *appliance)
|
||||
{
|
||||
- CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
|
||||
- char *ret = NULL;
|
||||
- int r;
|
||||
+ unsigned char magic[2], uuid[16];
|
||||
+ char *ret;
|
||||
+ int fd;
|
||||
|
||||
- guestfs_int_cmd_add_arg (cmd, "file");
|
||||
- guestfs_int_cmd_add_arg (cmd, "--");
|
||||
- guestfs_int_cmd_add_arg (cmd, appliance);
|
||||
- guestfs_int_cmd_set_stdout_callback (cmd, read_uuid, &ret, 0);
|
||||
- r = guestfs_int_cmd_run (cmd);
|
||||
- if (r == -1) {
|
||||
- if (ret) free (ret);
|
||||
+ fd = open (appliance, O_RDONLY|O_CLOEXEC);
|
||||
+ if (fd == -1) {
|
||||
+ perrorf (g, _("open: %s"), appliance);
|
||||
return NULL;
|
||||
}
|
||||
- if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
|
||||
- guestfs_int_external_command_failed (g, r, "file", NULL);
|
||||
- if (ret) free (ret);
|
||||
+ if (lseek (fd, 0x438, SEEK_SET) != 0x438) {
|
||||
+ magic_error:
|
||||
+ error (g, _("%s: cannot read extfs magic in superblock"), appliance);
|
||||
+ close (fd);
|
||||
return NULL;
|
||||
}
|
||||
+ if (read (fd, magic, 2) != 2)
|
||||
+ goto magic_error;
|
||||
+ if (magic[0] != 0x53 || magic[1] != 0xEF) {
|
||||
+ error (g, _("%s: appliance is not an extfs filesystem"), appliance);
|
||||
+ close (fd);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ if (lseek (fd, 0x468, SEEK_SET) != 0x468) {
|
||||
+ super_error:
|
||||
+ error (g, _("%s: cannot read UUID in superblock"), appliance);
|
||||
+ close (fd);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ if (read (fd, uuid, 16) != 16)
|
||||
+ goto super_error;
|
||||
+ close (fd);
|
||||
|
||||
+ /* The UUID is a binary blob, but we must return it as a printable
|
||||
+ * string. The caller frees this.
|
||||
+ */
|
||||
+ ret = safe_asprintf (g,
|
||||
+ "%02x%02x%02x%02x" "-"
|
||||
+ "%02x%02x" "-"
|
||||
+ "%02x%02x" "-"
|
||||
+ "%02x%02x" "-"
|
||||
+ "%02x%02x%02x%02x%02x%02x",
|
||||
+ uuid[0], uuid[1], uuid[2], uuid[3],
|
||||
+ uuid[4], uuid[5],
|
||||
+ uuid[6], uuid[7],
|
||||
+ uuid[8], uuid[9],
|
||||
+ uuid[10], uuid[11], uuid[12], uuid[13],
|
||||
+ uuid[14], uuid[15]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
- * Read the first 256k bytes of the in_file with L<qemu-img(1)> command
|
||||
- * and write them into the out_file. That may be useful to get UUID of
|
||||
- * the QCOW2 disk image with further L<file(1)> command.
|
||||
+ * Read the first 256k bytes of the in_file with L<qemu-img(1)>
|
||||
+ * command and write them into the out_file. That may be useful to get
|
||||
+ * UUID of the QCOW2 disk image with C<get_root_uuid_with_file>.
|
||||
+ *
|
||||
* The function returns zero if successful, otherwise -1.
|
||||
*/
|
||||
static int
|
||||
--
|
||||
2.29.0.rc2
|
||||
|
@ -42,7 +42,7 @@
|
||||
|
||||
# If there are patches which touch autotools files, set this to 1.
|
||||
%if !0%{?rhel}
|
||||
%global patches_touch_autotools 1
|
||||
%global patches_touch_autotools %{nil}
|
||||
%else
|
||||
# On RHEL the downstream patches always touch autotools files.
|
||||
%global patches_touch_autotools 1
|
||||
@ -60,8 +60,8 @@
|
||||
Summary: Access and modify virtual machine disk images
|
||||
Name: libguestfs
|
||||
Epoch: 1
|
||||
Version: 1.45.3
|
||||
Release: 6%{?dist}
|
||||
Version: 1.45.4
|
||||
Release: 1%{?dist}
|
||||
License: LGPLv2+
|
||||
|
||||
# Build only for architectures that have a kernel
|
||||
@ -91,14 +91,6 @@ Source7: libguestfs.keyring
|
||||
# Maintainer script which helps with handling patches.
|
||||
Source8: copy-patches.sh
|
||||
|
||||
# Upstream patches since 1.45.3.
|
||||
Patch0001: 0001-daemon-xfs.c-Fix-error-message.patch
|
||||
Patch0002: 0002-tests-Prefer-xorriso-over-genisoimage-to-generate-te.patch
|
||||
Patch0003: 0003-daemon-Allow-xorriso-as-an-alternative-to-isoinfo.patch
|
||||
Patch0004: 0004-daemon-Read-ISO9660-Primary-Volume-Descriptor-direct.patch
|
||||
# Workaround for file 5.40 which is broken in Fedora Rawhide.
|
||||
Patch0005: 0005-lib-appliance-kcmdline.c-Read-UUID-directly-from-app.patch
|
||||
|
||||
# Downstream (RHEL-only) patches.
|
||||
%if 0%{?rhel}
|
||||
Patch9001: 0001-RHEL-Remove-libguestfs-live-RHBZ-798980.patch
|
||||
@ -1126,6 +1118,9 @@ rm ocaml/html/.gitignore
|
||||
|
||||
|
||||
%changelog
|
||||
* Sat Apr 03 2021 Richard W.M. Jones <rjones@redhat.com> - 1:1.45.4-1
|
||||
- New upstream version 1.45.4.
|
||||
|
||||
* Wed Mar 31 2021 Richard W.M. Jones <rjones@redhat.com> - 1:1.45.3-6
|
||||
- Don't require genisoimage or xorriso for the appliance.
|
||||
- Add workaround for broken "file" utility in Rawhide (RHBZ#1945122).
|
||||
|
4
sources
4
sources
@ -1,2 +1,2 @@
|
||||
SHA512 (libguestfs-1.45.3.tar.gz) = b8f3dc9ffa49b50769f8f11d65cf3c8e645b35ee05ea2563b19daa8bc743e7f3386754cb5ffd2447f55ade4b57e9c4f98e483ecffc548652659e1260bf2e6e0b
|
||||
SHA512 (libguestfs-1.45.3.tar.gz.sig) = bce2ed6fd987baf82ebdd7d97cf1b1a07f62991e07de45d4f22d20c5180120c5b443b690c1db6c00a71cb14fb66b5a950de227d9c7fea2c9ca32afba33818216
|
||||
SHA512 (libguestfs-1.45.4.tar.gz) = 5e4960a0a0a182f1736a9707a84fd11f28b530a31d6a1ac2fca35d284e63bb07f20d2344355f4a626866dfb006e09c3f4a60754512a10b6462d4587e8cdc075e
|
||||
SHA512 (libguestfs-1.45.4.tar.gz.sig) = 860529aa6febf552ba5495f5b56f61daa27bd117fa0bc9a965511646022ee8f8f27f34a9ab1605cb7dea71d66bff2ab9da72d189f559f07ced57dc982929200c
|
||||
|
Loading…
Reference in New Issue
Block a user