New API: guestfs_canonical_device_name.

This API makes device names canonical, eg. /dev/vda1 -> /dev/sda1.
This commit is contained in:
Richard W.M. Jones
2012-06-13 20:36:40 +01:00
parent 998ebc333d
commit 46ed232dc2
12 changed files with 117 additions and 122 deletions

View File

@@ -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. */

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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 (

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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

View File

@@ -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. *)

View File

@@ -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 (

View File

@@ -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

View File

@@ -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 */
}

View File

@@ -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