mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
Add followsymlinks flag to is-file, is-dir, is-blockdev, is-chardev, is-fifo and is-socket APIs.
This adds an extra optional boolean 'followsymlinks' flag to those 6 is-* APIs. If the flag is true, then symlinks are followed, ie. we use stat instead of lstat in the test. For the rationale behind this change, see: https://bugzilla.redhat.com/show_bug.cgi?id=974489
This commit is contained in:
72
daemon/is.c
72
daemon/is.c
@@ -1,5 +1,5 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2010 Red Hat Inc.
|
||||
* Copyright (C) 2010-2013 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
|
||||
@@ -41,49 +41,79 @@ do_exists (const char *path)
|
||||
return r == 0;
|
||||
}
|
||||
|
||||
static int get_mode (const char *path, mode_t *mode);
|
||||
static int get_mode (const char *path, mode_t *mode, int followsymlinks);
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_is_file (const char *path)
|
||||
do_is_file (const char *path, int followsymlinks)
|
||||
{
|
||||
mode_t mode;
|
||||
int r = get_mode (path, &mode);
|
||||
int r;
|
||||
|
||||
if (!(optargs_bitmask & GUESTFS_IS_FILE_FOLLOWSYMLINKS_BITMASK))
|
||||
followsymlinks = 0;
|
||||
|
||||
r = get_mode (path, &mode, followsymlinks);
|
||||
if (r <= 0) return r;
|
||||
return S_ISREG (mode);
|
||||
}
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_is_dir (const char *path)
|
||||
do_is_dir (const char *path, int followsymlinks)
|
||||
{
|
||||
mode_t mode;
|
||||
int r = get_mode (path, &mode);
|
||||
int r;
|
||||
|
||||
if (!(optargs_bitmask & GUESTFS_IS_DIR_FOLLOWSYMLINKS_BITMASK))
|
||||
followsymlinks = 0;
|
||||
|
||||
r = get_mode (path, &mode, followsymlinks);
|
||||
if (r <= 0) return r;
|
||||
return S_ISDIR (mode);
|
||||
}
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_is_chardev (const char *path)
|
||||
do_is_chardev (const char *path, int followsymlinks)
|
||||
{
|
||||
mode_t mode;
|
||||
int r = get_mode (path, &mode);
|
||||
int r;
|
||||
|
||||
if (!(optargs_bitmask & GUESTFS_IS_CHARDEV_FOLLOWSYMLINKS_BITMASK))
|
||||
followsymlinks = 0;
|
||||
|
||||
r = get_mode (path, &mode, followsymlinks);
|
||||
if (r <= 0) return r;
|
||||
return S_ISCHR (mode);
|
||||
}
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_is_blockdev (const char *path)
|
||||
do_is_blockdev (const char *path, int followsymlinks)
|
||||
{
|
||||
mode_t mode;
|
||||
int r = get_mode (path, &mode);
|
||||
int r;
|
||||
|
||||
if (!(optargs_bitmask & GUESTFS_IS_BLOCKDEV_FOLLOWSYMLINKS_BITMASK))
|
||||
followsymlinks = 0;
|
||||
|
||||
r = get_mode (path, &mode, followsymlinks);
|
||||
if (r <= 0) return r;
|
||||
return S_ISBLK (mode);
|
||||
}
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_is_fifo (const char *path)
|
||||
do_is_fifo (const char *path, int followsymlinks)
|
||||
{
|
||||
mode_t mode;
|
||||
int r = get_mode (path, &mode);
|
||||
int r;
|
||||
|
||||
if (!(optargs_bitmask & GUESTFS_IS_FIFO_FOLLOWSYMLINKS_BITMASK))
|
||||
followsymlinks = 0;
|
||||
|
||||
r = get_mode (path, &mode, followsymlinks);
|
||||
if (r <= 0) return r;
|
||||
return S_ISFIFO (mode);
|
||||
}
|
||||
@@ -92,28 +122,36 @@ int
|
||||
do_is_symlink (const char *path)
|
||||
{
|
||||
mode_t mode;
|
||||
int r = get_mode (path, &mode);
|
||||
int r;
|
||||
|
||||
r = get_mode (path, &mode, 0);
|
||||
if (r <= 0) return r;
|
||||
return S_ISLNK (mode);
|
||||
}
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_is_socket (const char *path)
|
||||
do_is_socket (const char *path, int followsymlinks)
|
||||
{
|
||||
mode_t mode;
|
||||
int r = get_mode (path, &mode);
|
||||
int r;
|
||||
|
||||
if (!(optargs_bitmask & GUESTFS_IS_SOCKET_FOLLOWSYMLINKS_BITMASK))
|
||||
followsymlinks = 0;
|
||||
|
||||
r = get_mode (path, &mode, followsymlinks);
|
||||
if (r <= 0) return r;
|
||||
return S_ISSOCK (mode);
|
||||
}
|
||||
|
||||
static int
|
||||
get_mode (const char *path, mode_t *mode)
|
||||
get_mode (const char *path, mode_t *mode, int followsymlinks)
|
||||
{
|
||||
int r;
|
||||
struct stat buf;
|
||||
|
||||
CHROOT_IN;
|
||||
r = lstat (path, &buf);
|
||||
r = (!followsymlinks ? lstat : stat) (path, &buf);
|
||||
CHROOT_OUT;
|
||||
|
||||
if (r == -1) {
|
||||
|
||||
@@ -3471,7 +3471,7 @@ command." };
|
||||
tests = [
|
||||
InitScratchFS, Always, TestResultTrue
|
||||
[["mkdir"; "/mkdir"];
|
||||
["is_dir"; "/mkdir"]];
|
||||
["is_dir"; "/mkdir"; ""]];
|
||||
InitScratchFS, Always, TestLastFail
|
||||
[["mkdir"; "/mkdir2/foo/bar"]]
|
||||
];
|
||||
@@ -3486,13 +3486,13 @@ Create a directory named C<path>." };
|
||||
tests = [
|
||||
InitScratchFS, Always, TestResultTrue
|
||||
[["mkdir_p"; "/mkdir_p/foo/bar"];
|
||||
["is_dir"; "/mkdir_p/foo/bar"]];
|
||||
["is_dir"; "/mkdir_p/foo/bar"; ""]];
|
||||
InitScratchFS, Always, TestResultTrue
|
||||
[["mkdir_p"; "/mkdir_p2/foo/bar"];
|
||||
["is_dir"; "/mkdir_p2/foo"]];
|
||||
["is_dir"; "/mkdir_p2/foo"; ""]];
|
||||
InitScratchFS, Always, TestResultTrue
|
||||
[["mkdir_p"; "/mkdir_p3/foo/bar"];
|
||||
["is_dir"; "/mkdir_p3"]];
|
||||
["is_dir"; "/mkdir_p3"; ""]];
|
||||
(* Regression tests for RHBZ#503133: *)
|
||||
InitScratchFS, Always, TestRun
|
||||
[["mkdir"; "/mkdir_p4"];
|
||||
@@ -3554,13 +3554,16 @@ See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>." };
|
||||
|
||||
{ defaults with
|
||||
name = "is_file";
|
||||
style = RBool "fileflag", [Pathname "path"], [];
|
||||
style = RBool "fileflag", [Pathname "path"], [OBool "followsymlinks"];
|
||||
proc_nr = Some 37;
|
||||
once_had_no_optargs = true;
|
||||
tests = [
|
||||
InitISOFS, Always, TestResultTrue (
|
||||
[["is_file"; "/known-1"]]);
|
||||
[["is_file"; "/known-1"; ""]]);
|
||||
InitISOFS, Always, TestResultFalse (
|
||||
[["is_file"; "/directory"]])
|
||||
[["is_file"; "/directory"; ""]]);
|
||||
InitISOFS, Always, TestResultTrue (
|
||||
[["is_file"; "/abssymlink"; "true"]])
|
||||
];
|
||||
shortdesc = "test if a regular file";
|
||||
longdesc = "\
|
||||
@@ -3568,17 +3571,22 @@ This returns C<true> if and only if there is a regular file
|
||||
with the given C<path> name. Note that it returns false for
|
||||
other objects like directories.
|
||||
|
||||
If the optional flag C<followsymlinks> is true, then a symlink
|
||||
(or chain of symlinks) that ends with a file also causes the
|
||||
function to return true.
|
||||
|
||||
See also C<guestfs_stat>." };
|
||||
|
||||
{ defaults with
|
||||
name = "is_dir";
|
||||
style = RBool "dirflag", [Pathname "path"], [];
|
||||
style = RBool "dirflag", [Pathname "path"], [OBool "followsymlinks"];
|
||||
proc_nr = Some 38;
|
||||
once_had_no_optargs = true;
|
||||
tests = [
|
||||
InitISOFS, Always, TestResultFalse (
|
||||
[["is_dir"; "/known-3"]]);
|
||||
[["is_dir"; "/known-3"; ""]]);
|
||||
InitISOFS, Always, TestResultTrue (
|
||||
[["is_dir"; "/directory"]])
|
||||
[["is_dir"; "/directory"; ""]])
|
||||
];
|
||||
shortdesc = "test if a directory";
|
||||
longdesc = "\
|
||||
@@ -3586,6 +3594,10 @@ This returns C<true> if and only if there is a directory
|
||||
with the given C<path> name. Note that it returns false for
|
||||
other objects like files.
|
||||
|
||||
If the optional flag C<followsymlinks> is true, then a symlink
|
||||
(or chain of symlinks) that ends with a directory also causes the
|
||||
function to return true.
|
||||
|
||||
See also C<guestfs_stat>." };
|
||||
|
||||
{ defaults with
|
||||
@@ -4796,7 +4808,7 @@ C<guestfs_is_zero_device>" };
|
||||
[["mkdir_p"; "/boot/grub"];
|
||||
["write"; "/boot/grub/device.map"; "(hd0) /dev/sda"];
|
||||
["grub_install"; "/"; "/dev/sda"];
|
||||
["is_dir"; "/boot"]])
|
||||
["is_dir"; "/boot"; ""]])
|
||||
];
|
||||
shortdesc = "install GRUB 1";
|
||||
longdesc = "\
|
||||
@@ -4850,7 +4862,7 @@ replacing C</dev/vda> with the name of the installation device.
|
||||
[["mkdir"; "/cp2"];
|
||||
["write"; "/cp2/old"; "file content"];
|
||||
["cp"; "/cp2/old"; "/cp2/new"];
|
||||
["is_file"; "/cp2/old"]]);
|
||||
["is_file"; "/cp2/old"; ""]]);
|
||||
InitScratchFS, Always, TestResultString (
|
||||
[["mkdir"; "/cp3"];
|
||||
["write"; "/cp3/old"; "file content"];
|
||||
@@ -4894,7 +4906,7 @@ recursively using the C<cp -a> command." };
|
||||
[["mkdir"; "/mv2"];
|
||||
["write"; "/mv2/old"; "file content"];
|
||||
["mv"; "/mv2/old"; "/mv2/new"];
|
||||
["is_file"; "/mv2/old"]])
|
||||
["is_file"; "/mv2/old"; ""]])
|
||||
];
|
||||
shortdesc = "move a file";
|
||||
longdesc = "\
|
||||
@@ -8373,56 +8385,71 @@ To find the label of a filesystem, use C<guestfs_vfs_label>." };
|
||||
|
||||
{ defaults with
|
||||
name = "is_chardev";
|
||||
style = RBool "flag", [Pathname "path"], [];
|
||||
style = RBool "flag", [Pathname "path"], [OBool "followsymlinks"];
|
||||
proc_nr = Some 267;
|
||||
once_had_no_optargs = true;
|
||||
tests = [
|
||||
InitISOFS, Always, TestResultFalse (
|
||||
[["is_chardev"; "/directory"]]);
|
||||
[["is_chardev"; "/directory"; ""]]);
|
||||
InitScratchFS, Always, TestResultTrue (
|
||||
[["mknod_c"; "0o777"; "99"; "66"; "/is_chardev"];
|
||||
["is_chardev"; "/is_chardev"]])
|
||||
["is_chardev"; "/is_chardev"; ""]])
|
||||
];
|
||||
shortdesc = "test if character device";
|
||||
longdesc = "\
|
||||
This returns C<true> if and only if there is a character device
|
||||
with the given C<path> name.
|
||||
|
||||
If the optional flag C<followsymlinks> is true, then a symlink
|
||||
(or chain of symlinks) that ends with a chardev also causes the
|
||||
function to return true.
|
||||
|
||||
See also C<guestfs_stat>." };
|
||||
|
||||
{ defaults with
|
||||
name = "is_blockdev";
|
||||
style = RBool "flag", [Pathname "path"], [];
|
||||
style = RBool "flag", [Pathname "path"], [OBool "followsymlinks"];
|
||||
proc_nr = Some 268;
|
||||
once_had_no_optargs = true;
|
||||
tests = [
|
||||
InitISOFS, Always, TestResultFalse (
|
||||
[["is_blockdev"; "/directory"]]);
|
||||
[["is_blockdev"; "/directory"; ""]]);
|
||||
InitScratchFS, Always, TestResultTrue (
|
||||
[["mknod_b"; "0o777"; "99"; "66"; "/is_blockdev"];
|
||||
["is_blockdev"; "/is_blockdev"]])
|
||||
["is_blockdev"; "/is_blockdev"; ""]])
|
||||
];
|
||||
shortdesc = "test if block device";
|
||||
longdesc = "\
|
||||
This returns C<true> if and only if there is a block device
|
||||
with the given C<path> name.
|
||||
|
||||
If the optional flag C<followsymlinks> is true, then a symlink
|
||||
(or chain of symlinks) that ends with a block device also causes the
|
||||
function to return true.
|
||||
|
||||
See also C<guestfs_stat>." };
|
||||
|
||||
{ defaults with
|
||||
name = "is_fifo";
|
||||
style = RBool "flag", [Pathname "path"], [];
|
||||
style = RBool "flag", [Pathname "path"], [OBool "followsymlinks"];
|
||||
proc_nr = Some 269;
|
||||
once_had_no_optargs = true;
|
||||
tests = [
|
||||
InitISOFS, Always, TestResultFalse (
|
||||
[["is_fifo"; "/directory"]]);
|
||||
[["is_fifo"; "/directory"; ""]]);
|
||||
InitScratchFS, Always, TestResultTrue (
|
||||
[["mkfifo"; "0o777"; "/is_fifo"];
|
||||
["is_fifo"; "/is_fifo"]])
|
||||
["is_fifo"; "/is_fifo"; ""]])
|
||||
];
|
||||
shortdesc = "test if FIFO (named pipe)";
|
||||
longdesc = "\
|
||||
This returns C<true> if and only if there is a FIFO (named pipe)
|
||||
with the given C<path> name.
|
||||
|
||||
If the optional flag C<followsymlinks> is true, then a symlink
|
||||
(or chain of symlinks) that ends with a FIFO also causes the
|
||||
function to return true.
|
||||
|
||||
See also C<guestfs_stat>." };
|
||||
|
||||
{ defaults with
|
||||
@@ -8444,18 +8471,23 @@ See also C<guestfs_stat>." };
|
||||
|
||||
{ defaults with
|
||||
name = "is_socket";
|
||||
style = RBool "flag", [Pathname "path"], [];
|
||||
style = RBool "flag", [Pathname "path"], [OBool "followsymlinks"];
|
||||
proc_nr = Some 271;
|
||||
once_had_no_optargs = true;
|
||||
(* XXX Need a positive test for sockets. *)
|
||||
tests = [
|
||||
InitISOFS, Always, TestResultFalse (
|
||||
[["is_socket"; "/directory"]])
|
||||
[["is_socket"; "/directory"; ""]])
|
||||
];
|
||||
shortdesc = "test if socket";
|
||||
longdesc = "\
|
||||
This returns C<true> if and only if there is a Unix domain socket
|
||||
with the given C<path> name.
|
||||
|
||||
If the optional flag C<followsymlinks> is true, then a symlink
|
||||
(or chain of symlinks) that ends with a socket also causes the
|
||||
function to return true.
|
||||
|
||||
See also C<guestfs_stat>." };
|
||||
|
||||
{ defaults with
|
||||
@@ -11039,7 +11071,7 @@ for other partition types." };
|
||||
[["mkdir"; "/rename"];
|
||||
["write"; "/rename/old"; "file content"];
|
||||
["rename"; "/rename/old"; "/rename/new"];
|
||||
["is_file"; "/rename/old"]])
|
||||
["is_file"; "/rename/old"; ""]])
|
||||
];
|
||||
shortdesc = "rename a file on the same filesystem";
|
||||
longdesc = "\
|
||||
|
||||
@@ -51,11 +51,17 @@ guestfs_gobject_headers= \
|
||||
include/guestfs-gobject/optargs-inspect_get_icon.h \
|
||||
include/guestfs-gobject/optargs-mount_local.h \
|
||||
include/guestfs-gobject/optargs-umount_local.h \
|
||||
include/guestfs-gobject/optargs-is_file.h \
|
||||
include/guestfs-gobject/optargs-is_dir.h \
|
||||
include/guestfs-gobject/optargs-umount.h \
|
||||
include/guestfs-gobject/optargs-tar_in.h \
|
||||
include/guestfs-gobject/optargs-tar_out.h \
|
||||
include/guestfs-gobject/optargs-mkswap.h \
|
||||
include/guestfs-gobject/optargs-grep.h \
|
||||
include/guestfs-gobject/optargs-is_chardev.h \
|
||||
include/guestfs-gobject/optargs-is_blockdev.h \
|
||||
include/guestfs-gobject/optargs-is_fifo.h \
|
||||
include/guestfs-gobject/optargs-is_socket.h \
|
||||
include/guestfs-gobject/optargs-mkfs.h \
|
||||
include/guestfs-gobject/optargs-mount_9p.h \
|
||||
include/guestfs-gobject/optargs-ntfsresize.h \
|
||||
@@ -118,11 +124,17 @@ guestfs_gobject_sources= \
|
||||
src/optargs-inspect_get_icon.c \
|
||||
src/optargs-mount_local.c \
|
||||
src/optargs-umount_local.c \
|
||||
src/optargs-is_file.c \
|
||||
src/optargs-is_dir.c \
|
||||
src/optargs-umount.c \
|
||||
src/optargs-tar_in.c \
|
||||
src/optargs-tar_out.c \
|
||||
src/optargs-mkswap.c \
|
||||
src/optargs-grep.c \
|
||||
src/optargs-is_chardev.c \
|
||||
src/optargs-is_blockdev.c \
|
||||
src/optargs-is_fifo.c \
|
||||
src/optargs-is_socket.c \
|
||||
src/optargs-mkfs.c \
|
||||
src/optargs-mount_9p.c \
|
||||
src/optargs-ntfsresize.c \
|
||||
|
||||
@@ -165,6 +165,12 @@ gobject/src/optargs-inspect_get_icon.c
|
||||
gobject/src/optargs-internal_test.c
|
||||
gobject/src/optargs-internal_test_63_optargs.c
|
||||
gobject/src/optargs-internal_test_only_optargs.c
|
||||
gobject/src/optargs-is_blockdev.c
|
||||
gobject/src/optargs-is_chardev.c
|
||||
gobject/src/optargs-is_dir.c
|
||||
gobject/src/optargs-is_fifo.c
|
||||
gobject/src/optargs-is_file.c
|
||||
gobject/src/optargs-is_socket.c
|
||||
gobject/src/optargs-md_create.c
|
||||
gobject/src/optargs-mke2fs.c
|
||||
gobject/src/optargs-mkfs.c
|
||||
|
||||
@@ -77,7 +77,7 @@ WantedBy=default.target
|
||||
let failed fs =
|
||||
ksprintf (fun msg -> failwith (s_"firstboot: failed: " ^ msg)) fs
|
||||
|
||||
let rec install_service g distro =
|
||||
let rec install_service (g : Guestfs.guestfs) distro =
|
||||
g#mkdir_p firstboot_dir;
|
||||
g#mkdir_p (sprintf "%s/scripts" firstboot_dir);
|
||||
g#write (sprintf "%s/firstboot.sh" firstboot_dir) firstboot_sh;
|
||||
@@ -145,7 +145,7 @@ and install_sysvinit_debian g =
|
||||
g#ln_sf "/etc/init.d/virt-sysprep-firstboot"
|
||||
"/etc/rc5.d/S99virt-sysprep-firstboot"
|
||||
|
||||
let add_firstboot_script g root id content =
|
||||
let add_firstboot_script (g : Guestfs.guestfs) root id content =
|
||||
let typ = g#inspect_get_type root in
|
||||
let distro = g#inspect_get_distro root in
|
||||
match typ, distro with
|
||||
|
||||
@@ -21,7 +21,7 @@ open Common_gettext.Gettext
|
||||
|
||||
module G = Guestfs
|
||||
|
||||
let cron_spool_perform g root =
|
||||
let cron_spool_perform (g : Guestfs.guestfs) root =
|
||||
Array.iter g#rm_rf (g#glob_expand "/var/spool/cron/*");
|
||||
Array.iter g#rm (g#glob_expand "/var/spool/atjobs/*");
|
||||
Array.iter g#rm (g#glob_expand "/var/spool/atjobs/.SEQ");
|
||||
|
||||
@@ -26,7 +26,7 @@ module G = Guestfs
|
||||
|
||||
let hostname = ref "localhost.localdomain"
|
||||
|
||||
let hostname_perform g root =
|
||||
let hostname_perform (g : Guestfs.guestfs) root =
|
||||
let typ = g#inspect_get_type root in
|
||||
let distro = g#inspect_get_distro root in
|
||||
let major_version = g#inspect_get_major_version root in
|
||||
|
||||
@@ -21,7 +21,7 @@ open Common_gettext.Gettext
|
||||
|
||||
module G = Guestfs
|
||||
|
||||
let random_seed_perform g root =
|
||||
let random_seed_perform (g : Guestfs.guestfs) root =
|
||||
let typ = g#inspect_get_type root in
|
||||
if typ = "linux" then (
|
||||
let files = [
|
||||
|
||||
Reference in New Issue
Block a user