mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
New API: guestfs_canonical_device_name.
This API makes device names canonical, eg. /dev/vda1 -> /dev/sda1.
This commit is contained in:
12
align/scan.c
12
align/scan.c
@@ -246,7 +246,7 @@ main (int argc, char *argv[])
|
||||
void
|
||||
scan (size_t *worst_alignment, const char *prefix)
|
||||
{
|
||||
char **devices;
|
||||
char **devices, *p;
|
||||
size_t i, j;
|
||||
size_t alignment;
|
||||
uint64_t start;
|
||||
@@ -262,11 +262,11 @@ scan (size_t *worst_alignment, const char *prefix)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
/* Canonicalize the name of the device for printing. */
|
||||
if (STRPREFIX (devices[i], "/dev/") &&
|
||||
(devices[i][5] == 'h' || devices[i][5] == 'v') &&
|
||||
devices[i][6] == 'd' &&
|
||||
c_isalpha (devices[i][7]))
|
||||
devices[i][5] = 's';
|
||||
p = guestfs_canonical_device_name (g, devices[i]);
|
||||
if (p == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
free (devices[i]);
|
||||
devices[i] = p;
|
||||
|
||||
for (j = 0; j < parts->len; ++j) {
|
||||
/* Start offset of the partition in bytes. */
|
||||
|
||||
@@ -82,8 +82,6 @@ static int output = 0;
|
||||
#define NR_COLUMNS 8
|
||||
static int columns;
|
||||
|
||||
static char *canonical_device (const char *dev);
|
||||
|
||||
static void do_output_title (void);
|
||||
static void do_output (void);
|
||||
static void do_output_end (void);
|
||||
@@ -466,7 +464,9 @@ do_output_filesystems (void)
|
||||
(STREQ (fses[i+1], "swap") || STREQ (fses[i+1], "unknown")))
|
||||
goto next;
|
||||
|
||||
dev = canonical_device (fses[i]);
|
||||
dev = guestfs_canonical_device_name (g, fses[i]);
|
||||
if (dev == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
/* Only bother to look these up if we will be displaying them,
|
||||
* otherwise pass them as NULL.
|
||||
@@ -639,7 +639,9 @@ do_output_pvs (void)
|
||||
char uuid[33];
|
||||
const char *parents[1] = { NULL };
|
||||
|
||||
dev = canonical_device (pvs->val[i].pv_name);
|
||||
dev = guestfs_canonical_device_name (g, pvs->val[i].pv_name);
|
||||
if (!dev)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
memcpy (uuid, pvs->val[i].pv_uuid, 32);
|
||||
uuid[32] = '\0';
|
||||
@@ -693,7 +695,9 @@ do_output_partitions (void)
|
||||
int64_t size = -1;
|
||||
int mbr_id = -1;
|
||||
|
||||
dev = canonical_device (parts[i]);
|
||||
dev = guestfs_canonical_device_name (g, parts[i]);
|
||||
if (!dev)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
if ((columns & COLUMN_SIZE)) {
|
||||
size = guestfs_blockdev_getsize64 (g, parts[i]);
|
||||
@@ -708,7 +712,9 @@ do_output_partitions (void)
|
||||
if ((columns & COLUMN_MBR))
|
||||
mbr_id = get_mbr_id (parts[i], parent_name);
|
||||
|
||||
char *p = canonical_device (parent_name);
|
||||
char *p = guestfs_canonical_device_name (g, parent_name);
|
||||
if (!p)
|
||||
exit (EXIT_FAILURE);
|
||||
free (parent_name);
|
||||
parent_name = p;
|
||||
|
||||
@@ -742,7 +748,9 @@ do_output_blockdevs (void)
|
||||
char *dev;
|
||||
char **parents;
|
||||
|
||||
dev = canonical_device (devices[i]);
|
||||
dev = guestfs_canonical_device_name (g, devices[i]);
|
||||
if (!dev)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
if ((columns & COLUMN_SIZE)) {
|
||||
size = guestfs_blockdev_getsize64 (g, devices[i]);
|
||||
@@ -766,26 +774,6 @@ do_output_blockdevs (void)
|
||||
free (devices);
|
||||
}
|
||||
|
||||
/* /dev/vda1 -> /dev/sda. Returns a string which the caller must free. */
|
||||
static char *
|
||||
canonical_device (const char *dev)
|
||||
{
|
||||
char *ret = strdup (dev);
|
||||
if (ret == NULL) {
|
||||
perror ("strdup");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (STRPREFIX (ret, "/dev/") &&
|
||||
(ret[5] == 'h' || ret[5] == 'v') &&
|
||||
ret[6] == 'd' &&
|
||||
c_isalpha (ret[7]) &&
|
||||
(c_isdigit (ret[8]) || ret[8] == '\0'))
|
||||
ret[5] = 's';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Returns an empty list of parents. Note this must be freed using
|
||||
* free_strings.
|
||||
*/
|
||||
@@ -841,8 +829,11 @@ parents_of_md (char *device)
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (i = 0; i < stats->len; ++i)
|
||||
ret[i] = canonical_device (stats->val[i].mdstat_device);
|
||||
for (i = 0; i < stats->len; ++i) {
|
||||
ret[i] = guestfs_canonical_device_name (g, stats->val[i].mdstat_device);
|
||||
if (!ret[i])
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret[stats->len] = NULL;
|
||||
|
||||
@@ -902,8 +893,11 @@ parents_of_vg (char *vg)
|
||||
break;
|
||||
}
|
||||
|
||||
if (j < pvs->len)
|
||||
ret[i] = canonical_device (pvs->val[j].pv_name);
|
||||
if (j < pvs->len) {
|
||||
ret[i] = guestfs_canonical_device_name (g, pvs->val[j].pv_name);
|
||||
if (!ret[i])
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
else {
|
||||
fprintf (stderr, "%s: warning: unknown PV UUID ignored\n", __func__);
|
||||
ret[i] = strndup (pvuuids[i], 32);
|
||||
|
||||
@@ -105,7 +105,6 @@ add_drives (struct drv *drv, char next_drive)
|
||||
}
|
||||
|
||||
static void display_mountpoints_on_failure (const char *mp_device, const char *user_supplied_options);
|
||||
static void canonical_device_name (char *dev);
|
||||
|
||||
/* List is built in reverse order, so mount them in reverse order. */
|
||||
void
|
||||
@@ -139,7 +138,7 @@ static void
|
||||
display_mountpoints_on_failure (const char *mp_device,
|
||||
const char *user_supplied_options)
|
||||
{
|
||||
char **fses;
|
||||
char **fses, *p;
|
||||
size_t i;
|
||||
|
||||
fses = guestfs_list_filesystems (g);
|
||||
@@ -162,8 +161,10 @@ display_mountpoints_on_failure (const char *mp_device,
|
||||
program_name);
|
||||
|
||||
for (i = 0; fses[i] != NULL; i += 2) {
|
||||
canonical_device_name (fses[i]);
|
||||
fprintf (stderr, "%s: \t%s (%s)\n", program_name, fses[i], fses[i+1]);
|
||||
p = guestfs_canonical_device_name (g, fses[i]);
|
||||
fprintf (stderr, "%s: \t%s (%s)\n", program_name,
|
||||
p ? p : fses[i], fses[i+1]);
|
||||
free (p);
|
||||
free (fses[i]);
|
||||
free (fses[i+1]);
|
||||
}
|
||||
@@ -171,17 +172,6 @@ display_mountpoints_on_failure (const char *mp_device,
|
||||
free (fses);
|
||||
}
|
||||
|
||||
static void
|
||||
canonical_device_name (char *dev)
|
||||
{
|
||||
if (STRPREFIX (dev, "/dev/") &&
|
||||
(dev[5] == 'h' || dev[5] == 'v') &&
|
||||
dev[6] == 'd' &&
|
||||
c_isalpha (dev[7]) &&
|
||||
(c_isdigit (dev[8]) || dev[8] == '\0'))
|
||||
dev[5] = 's';
|
||||
}
|
||||
|
||||
void
|
||||
free_drives (struct drv *drv)
|
||||
{
|
||||
|
||||
@@ -1734,6 +1734,34 @@ versions of libguestfs the limit was 25.
|
||||
See L<guestfs(3)/MAXIMUM NUMBER OF DISKS> for additional
|
||||
information on this topic.");
|
||||
|
||||
("canonical_device_name", (RString "canonical", [String "device"], []), -1, [],
|
||||
[],
|
||||
"return canonical device name",
|
||||
"\
|
||||
This utility function is useful when displaying device names to
|
||||
the user. It takes a number of irregular device names and
|
||||
returns them in a consistent format:
|
||||
|
||||
=over 4
|
||||
|
||||
=item C</dev/hdX>
|
||||
|
||||
=item C</dev/vdX>
|
||||
|
||||
These are returned as C</dev/sdX>. Note this works for device
|
||||
names and partition names. This is approximately the reverse of
|
||||
the algorithm described in L<guestfs(3)/BLOCK DEVICE NAMING>.
|
||||
|
||||
=item C</dev/mapper/VG-LV>
|
||||
|
||||
=item C</dev/dm-N>
|
||||
|
||||
Converted to C</dev/VG/LV> form using C<guestfs_lvm_canonical_lvm_name>.
|
||||
|
||||
=back
|
||||
|
||||
Other strings are returned unmodified.");
|
||||
|
||||
]
|
||||
|
||||
(* daemon_functions are any functions which cause some action
|
||||
@@ -6132,7 +6160,7 @@ is converted to C</dev/VG/LV>.
|
||||
This command returns an error if the C<lvname> parameter does
|
||||
not refer to a logical volume.
|
||||
|
||||
See also C<guestfs_is_lv>.");
|
||||
See also C<guestfs_is_lv>, C<guestfs_canonical_device_name>.");
|
||||
|
||||
("mkfs_opts", (RErr, [String "fstype"; Device "device"], [OInt "blocksize"; OString "features"; OInt "inode"; OInt "sectorsize"]), 278, [],
|
||||
[InitEmpty, Always, TestOutput (
|
||||
|
||||
@@ -60,7 +60,6 @@ static void output_mountpoints (xmlTextWriterPtr xo, char *root);
|
||||
static void output_filesystems (xmlTextWriterPtr xo, char *root);
|
||||
static void output_drive_mappings (xmlTextWriterPtr xo, char *root);
|
||||
static void output_applications (xmlTextWriterPtr xo, char *root);
|
||||
static void canonicalize (char *dev);
|
||||
static void free_strings (char **argv);
|
||||
static size_t count_strings (char *const*argv);
|
||||
static void do_xpath (const char *query);
|
||||
@@ -363,15 +362,17 @@ output_root (xmlTextWriterPtr xo, char *root)
|
||||
char *str;
|
||||
int i, r;
|
||||
char buf[32];
|
||||
char canonical_root[strlen (root) + 1];
|
||||
char *canonical_root;
|
||||
size_t size;
|
||||
|
||||
XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "operatingsystem"));
|
||||
|
||||
strcpy (canonical_root, root);
|
||||
canonicalize (canonical_root);
|
||||
canonical_root = guestfs_canonical_device_name (g, root);
|
||||
if (canonical_root == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
XMLERROR (-1,
|
||||
xmlTextWriterWriteElement (xo, BAD_CAST "root", BAD_CAST canonical_root));
|
||||
free (canonical_root);
|
||||
|
||||
str = guestfs_inspect_get_type (g, root);
|
||||
if (!str) exit (EXIT_FAILURE);
|
||||
@@ -560,7 +561,7 @@ compare_keys_len (const void *p1, const void *p2)
|
||||
static void
|
||||
output_mountpoints (xmlTextWriterPtr xo, char *root)
|
||||
{
|
||||
char **mountpoints;
|
||||
char **mountpoints, *p;
|
||||
size_t i;
|
||||
|
||||
mountpoints = guestfs_inspect_get_mountpoints (g, root);
|
||||
@@ -576,16 +577,19 @@ output_mountpoints (xmlTextWriterPtr xo, char *root)
|
||||
XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "mountpoints"));
|
||||
|
||||
for (i = 0; mountpoints[i] != NULL; i += 2) {
|
||||
canonicalize (mountpoints[i+1]);
|
||||
p = guestfs_canonical_device_name (g, mountpoints[i+1]);
|
||||
if (!p)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
XMLERROR (-1,
|
||||
xmlTextWriterStartElement (xo, BAD_CAST "mountpoint"));
|
||||
XMLERROR (-1,
|
||||
xmlTextWriterWriteAttribute (xo, BAD_CAST "dev",
|
||||
BAD_CAST mountpoints[i+1]));
|
||||
xmlTextWriterWriteAttribute (xo, BAD_CAST "dev", BAD_CAST p));
|
||||
XMLERROR (-1,
|
||||
xmlTextWriterWriteString (xo, BAD_CAST mountpoints[i]));
|
||||
XMLERROR (-1, xmlTextWriterEndElement (xo));
|
||||
|
||||
free (p);
|
||||
}
|
||||
|
||||
XMLERROR (-1, xmlTextWriterEndElement (xo));
|
||||
@@ -611,12 +615,14 @@ output_filesystems (xmlTextWriterPtr xo, char *root)
|
||||
XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "filesystems"));
|
||||
|
||||
for (i = 0; filesystems[i] != NULL; ++i) {
|
||||
canonicalize (filesystems[i]);
|
||||
str = guestfs_canonical_device_name (g, filesystems[i]);
|
||||
if (!str)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "filesystem"));
|
||||
XMLERROR (-1,
|
||||
xmlTextWriterWriteAttribute (xo, BAD_CAST "dev",
|
||||
BAD_CAST filesystems[i]));
|
||||
xmlTextWriterWriteAttribute (xo, BAD_CAST "dev", BAD_CAST str));
|
||||
free (str);
|
||||
|
||||
DISABLE_GUESTFS_ERRORS_FOR (
|
||||
str = guestfs_vfs_type (g, filesystems[i]);
|
||||
@@ -657,6 +663,7 @@ static void
|
||||
output_drive_mappings (xmlTextWriterPtr xo, char *root)
|
||||
{
|
||||
char **drive_mappings = NULL;
|
||||
char *str;
|
||||
size_t i;
|
||||
|
||||
DISABLE_GUESTFS_ERRORS_FOR (
|
||||
@@ -678,7 +685,9 @@ output_drive_mappings (xmlTextWriterPtr xo, char *root)
|
||||
XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "drive_mappings"));
|
||||
|
||||
for (i = 0; drive_mappings[i] != NULL; i += 2) {
|
||||
canonicalize (drive_mappings[i+1]);
|
||||
str = guestfs_canonical_device_name (g, drive_mappings[i+1]);
|
||||
if (!str)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
XMLERROR (-1,
|
||||
xmlTextWriterStartElement (xo, BAD_CAST "drive_mapping"));
|
||||
@@ -686,8 +695,10 @@ output_drive_mappings (xmlTextWriterPtr xo, char *root)
|
||||
xmlTextWriterWriteAttribute (xo, BAD_CAST "name",
|
||||
BAD_CAST drive_mappings[i]));
|
||||
XMLERROR (-1,
|
||||
xmlTextWriterWriteString (xo, BAD_CAST drive_mappings[i+1]));
|
||||
xmlTextWriterWriteString (xo, BAD_CAST str));
|
||||
XMLERROR (-1, xmlTextWriterEndElement (xo));
|
||||
|
||||
free (str);
|
||||
}
|
||||
|
||||
XMLERROR (-1, xmlTextWriterEndElement (xo));
|
||||
@@ -773,20 +784,6 @@ output_applications (xmlTextWriterPtr xo, char *root)
|
||||
guestfs_free_application_list (apps);
|
||||
}
|
||||
|
||||
/* "/dev/vda1" -> "/dev/sda1"
|
||||
* See BLOCK DEVICE NAMING in guestfs(3).
|
||||
*/
|
||||
static void
|
||||
canonicalize (char *dev)
|
||||
{
|
||||
if (STRPREFIX (dev, "/dev/") &&
|
||||
(dev[5] == 'h' || dev[5] == 'v') &&
|
||||
dev[6] == 'd' &&
|
||||
c_isalpha (dev[7]) &&
|
||||
(c_isdigit (dev[8]) || dev[8] == '\0'))
|
||||
dev[5] = 's';
|
||||
}
|
||||
|
||||
static void
|
||||
free_strings (char **argv)
|
||||
{
|
||||
|
||||
@@ -348,7 +348,7 @@ let get_partition_content =
|
||||
| [] ->
|
||||
error (f_"%s: physical volume not returned by pvs_full")
|
||||
dev
|
||||
| pv :: _ when canonicalize pv.G.pv_name = dev ->
|
||||
| pv :: _ when g#canonical_device_name pv.G.pv_name = dev ->
|
||||
ContentPV pv.G.pv_size
|
||||
| _ :: pvs -> loop pvs
|
||||
in
|
||||
@@ -529,7 +529,7 @@ let find_partition =
|
||||
"/dev/" ^ name
|
||||
else
|
||||
name in
|
||||
let name = canonicalize name in
|
||||
let name = g#canonical_device_name name in
|
||||
|
||||
let partition =
|
||||
try Hashtbl.find hash name
|
||||
|
||||
@@ -84,20 +84,6 @@ let error fs =
|
||||
in
|
||||
ksprintf display fs
|
||||
|
||||
(* The reverse of device name translation, see
|
||||
* BLOCK DEVICE NAMING in guestfs(3).
|
||||
*)
|
||||
let canonicalize dev =
|
||||
if String.length dev >= 8 &&
|
||||
dev.[0] = '/' && dev.[1] = 'd' && dev.[2] = 'e' && dev.[3] = 'v' &&
|
||||
dev.[4] = '/' && (dev.[5] = 'h' || dev.[5] = 'v') && dev.[6] = 'd' then (
|
||||
let dev = String.copy dev in
|
||||
dev.[5] <- 's';
|
||||
dev
|
||||
)
|
||||
else
|
||||
dev
|
||||
|
||||
let feature_available (g : Guestfs.guestfs) names =
|
||||
try g#available names; true
|
||||
with G.Error _ -> false
|
||||
|
||||
@@ -25,15 +25,6 @@ let () =
|
||||
assert (int_of_le32 "\x80\x60\x40\x20" = 0x20406080L);
|
||||
assert (le32_of_int 0x20406080L = "\x80\x60\x40\x20")
|
||||
|
||||
(* Test Utils.canonicalize. *)
|
||||
let () =
|
||||
assert (canonicalize "/dev/vda" = "/dev/sda");
|
||||
assert (canonicalize "/dev/hda3" = "/dev/sda3");
|
||||
assert (canonicalize "/dev/sda4" = "/dev/sda4");
|
||||
assert (canonicalize "/dev/hdaa" = "/dev/sdaa");
|
||||
assert (canonicalize "/dev/sdaa" = "/dev/sdaa");
|
||||
assert (canonicalize "/dev/cciss/c0d0p1" = "/dev/cciss/c0d0p1")
|
||||
|
||||
(* Test Utils.parse_size. *)
|
||||
let () =
|
||||
(* For absolute sizes, oldsize is ignored. *)
|
||||
|
||||
@@ -214,8 +214,8 @@ let () =
|
||||
let filesystems = List.sort compare filesystems in
|
||||
|
||||
let is_ignored fs =
|
||||
let fs = canonicalize fs in
|
||||
List.exists (fun fs' -> fs = canonicalize fs') ignores
|
||||
let fs = g#canonical_device_name fs in
|
||||
List.exists (fun fs' -> fs = g#canonical_device_name fs') ignores
|
||||
in
|
||||
|
||||
List.iter (
|
||||
|
||||
@@ -112,20 +112,6 @@ let error fs =
|
||||
in
|
||||
ksprintf display fs
|
||||
|
||||
(* The reverse of device name translation, see
|
||||
* BLOCK DEVICE NAMING in guestfs(3).
|
||||
*)
|
||||
let canonicalize dev =
|
||||
if String.length dev >= 8 &&
|
||||
dev.[0] = '/' && dev.[1] = 'd' && dev.[2] = 'e' && dev.[3] = 'v' &&
|
||||
dev.[4] = '/' && (dev.[5] = 'h' || dev.[5] = 'v') && dev.[6] = 'd' then (
|
||||
let dev = String.copy dev in
|
||||
dev.[5] <- 's';
|
||||
dev
|
||||
)
|
||||
else
|
||||
dev
|
||||
|
||||
let feature_available (g : Guestfs.guestfs) names =
|
||||
try g#available names; true
|
||||
with G.Error _ -> false
|
||||
|
||||
@@ -996,3 +996,26 @@ guestfs___free_drives (struct drive **drives)
|
||||
i = next;
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
guestfs__canonical_device_name (guestfs_h *g, const char *device)
|
||||
{
|
||||
char *ret;
|
||||
|
||||
if (STRPREFIX (device, "/dev/hd") ||
|
||||
STRPREFIX (device, "/dev/vd")) {
|
||||
ret = safe_strdup (g, device);
|
||||
ret[5] = 's';
|
||||
}
|
||||
else if (STRPREFIX (device, "/dev/mapper/") ||
|
||||
STRPREFIX (device, "/dev/dm-")) {
|
||||
/* XXX hide errors */
|
||||
ret = guestfs_lvm_canonical_lv_name (g, device);
|
||||
if (ret == NULL)
|
||||
ret = safe_strdup (g, device);
|
||||
}
|
||||
else
|
||||
ret = safe_strdup (g, device);
|
||||
|
||||
return ret; /* caller frees */
|
||||
}
|
||||
|
||||
@@ -1158,7 +1158,7 @@ C</dev/hda2> transparently.
|
||||
Note that this I<only> applies to parameters. The
|
||||
L</guestfs_list_devices>, L</guestfs_list_partitions> and similar calls
|
||||
return the true names of the devices and partitions as known to the
|
||||
appliance.
|
||||
appliance, but see L</guestfs_canonical_device_name>.
|
||||
|
||||
=head3 ALGORITHM FOR BLOCK DEVICE NAME TRANSLATION
|
||||
|
||||
|
||||
Reference in New Issue
Block a user