mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
daemon: Use a private copy of /etc/lvm so we don't modify the real config.
In the libguestfs live case we need to be careful not to modify the real /etc/lvm/lvm.conf file (when setting the filter rule). When the daemon starts, make a complete copy of /etc/lvm in a temporary directory, and adjust LVM_SYSTEM_DIR to point to the copy. All changes are made in the temporary copy.
This commit is contained in:
@@ -134,6 +134,9 @@ extern int e2prog (char *name); /* Massive hack for RHEL 5. */
|
||||
/*-- in lvm.c --*/
|
||||
extern int lv_canonical (const char *device, char **ret);
|
||||
|
||||
/*-- in lvm-filter.c --*/
|
||||
extern void copy_lvm (void);
|
||||
|
||||
/*-- in proto.c --*/
|
||||
extern void main_loop (int sock) __attribute__((noreturn));
|
||||
|
||||
|
||||
@@ -239,6 +239,11 @@ main (int argc, char *argv[])
|
||||
_umask (0);
|
||||
#endif
|
||||
|
||||
/* Make a private copy of /etc/lvm so we can change the config (see
|
||||
* daemon/lvm-filter.c).
|
||||
*/
|
||||
copy_lvm ();
|
||||
|
||||
/* Connect to virtio-serial channel. */
|
||||
int sock = open (VIRTIO_SERIAL_CHANNEL, O_RDWR | O_CLOEXEC);
|
||||
if (sock == -1) {
|
||||
|
||||
@@ -23,11 +23,79 @@
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "c-ctype.h"
|
||||
#include "ignore-value.h"
|
||||
|
||||
#include "daemon.h"
|
||||
#include "c-ctype.h"
|
||||
#include "actions.h"
|
||||
|
||||
/* This runs during daemon start up and creates a complete copy of
|
||||
* /etc/lvm so that we can modify it as we desire. We set
|
||||
* LVM_SYSTEM_DIR to point to the copy.
|
||||
*/
|
||||
static char lvm_system_dir[] = "/tmp/lvmXXXXXX";
|
||||
|
||||
static void rm_lvm_system_dir (void);
|
||||
|
||||
void
|
||||
copy_lvm (void)
|
||||
{
|
||||
struct stat statbuf;
|
||||
char cmd[64];
|
||||
int r;
|
||||
|
||||
/* If /etc/lvm directory doesn't exist (or isn't a directory) assume
|
||||
* that this system doesn't support LVM and do nothing.
|
||||
*/
|
||||
r = stat ("/etc/lvm", &statbuf);
|
||||
if (r == -1) {
|
||||
perror ("copy_lvm: stat: /etc/lvm");
|
||||
return;
|
||||
}
|
||||
if (! S_ISDIR (statbuf.st_mode)) {
|
||||
fprintf (stderr, "copy_lvm: warning: /etc/lvm is not a directory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mkdtemp (lvm_system_dir) == NULL) {
|
||||
perror (lvm_system_dir);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Hopefully no dotfiles in there ... XXX */
|
||||
snprintf (cmd, sizeof cmd, "cp -a /etc/lvm/* %s", lvm_system_dir);
|
||||
r = system (cmd);
|
||||
if (r == -1) {
|
||||
perror (cmd);
|
||||
rmdir (lvm_system_dir);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (WEXITSTATUS (r) != 0) {
|
||||
fprintf (stderr, "cp command failed with return code %d\n",
|
||||
WEXITSTATUS (r));
|
||||
rmdir (lvm_system_dir);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Set environment variable so we use the copy. */
|
||||
setenv ("LVM_SYSTEM_DIR", lvm_system_dir, 1);
|
||||
|
||||
/* Set a handler to remove the temporary directory at exit. */
|
||||
atexit (rm_lvm_system_dir);
|
||||
}
|
||||
|
||||
static void
|
||||
rm_lvm_system_dir (void)
|
||||
{
|
||||
char cmd[64];
|
||||
|
||||
snprintf (cmd, sizeof cmd, "rm -rf %s", lvm_system_dir);
|
||||
ignore_value (system (cmd));
|
||||
}
|
||||
|
||||
/* Does the current line match the regexp /^\s*filter\s*=/ */
|
||||
static int
|
||||
is_filter_line (const char *line)
|
||||
@@ -52,18 +120,24 @@ is_filter_line (const char *line)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Rewrite the 'filter = [ ... ]' line in /etc/lvm/lvm.conf. */
|
||||
/* Rewrite the 'filter = [ ... ]' line in lvm.conf. */
|
||||
static int
|
||||
set_filter (const char *filter)
|
||||
{
|
||||
FILE *ifp = fopen ("/etc/lvm/lvm.conf", "r");
|
||||
char lvm_conf[64];
|
||||
snprintf (lvm_conf, sizeof lvm_conf, "%s/lvm.conf", lvm_system_dir);
|
||||
|
||||
char lvm_conf_new[64];
|
||||
snprintf (lvm_conf_new, sizeof lvm_conf, "%s/lvm.conf.new", lvm_system_dir);
|
||||
|
||||
FILE *ifp = fopen (lvm_conf, "r");
|
||||
if (ifp == NULL) {
|
||||
reply_with_perror ("open: /etc/lvm/lvm.conf");
|
||||
reply_with_perror ("open: %s", lvm_conf);
|
||||
return -1;
|
||||
}
|
||||
FILE *ofp = fopen ("/etc/lvm/lvm.conf.new", "w");
|
||||
FILE *ofp = fopen (lvm_conf_new, "w");
|
||||
if (ofp == NULL) {
|
||||
reply_with_perror ("open: /etc/lvm/lvm.conf.new");
|
||||
reply_with_perror ("open: %s", lvm_conf_new);
|
||||
fclose (ifp);
|
||||
return -1;
|
||||
}
|
||||
@@ -79,11 +153,11 @@ set_filter (const char *filter)
|
||||
}
|
||||
if (r < 0) {
|
||||
/* NB. fprintf doesn't set errno on error. */
|
||||
reply_with_error ("/etc/lvm/lvm.conf.new: write failed");
|
||||
reply_with_error ("%s: write failed", lvm_conf_new);
|
||||
fclose (ifp);
|
||||
fclose (ofp);
|
||||
free (line);
|
||||
unlink ("/etc/lvm/lvm.conf.new");
|
||||
unlink (lvm_conf_new);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -91,20 +165,20 @@ set_filter (const char *filter)
|
||||
free (line);
|
||||
|
||||
if (fclose (ifp) == EOF) {
|
||||
reply_with_perror ("/etc/lvm/lvm.conf.new");
|
||||
unlink ("/etc/lvm/lvm.conf.new");
|
||||
reply_with_perror ("close: %s", lvm_conf);
|
||||
unlink (lvm_conf_new);
|
||||
fclose (ofp);
|
||||
return -1;
|
||||
}
|
||||
if (fclose (ofp) == EOF) {
|
||||
reply_with_perror ("/etc/lvm/lvm.conf.new");
|
||||
unlink ("/etc/lvm/lvm.conf.new");
|
||||
reply_with_perror ("close: %s", lvm_conf_new);
|
||||
unlink (lvm_conf_new);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rename ("/etc/lvm/lvm.conf.new", "/etc/lvm/lvm.conf") == -1) {
|
||||
reply_with_perror ("rename: /etc/lvm/lvm.conf");
|
||||
unlink ("/etc/lvm/lvm.conf.new");
|
||||
if (rename (lvm_conf_new, lvm_conf) == -1) {
|
||||
reply_with_perror ("rename: %s", lvm_conf);
|
||||
unlink (lvm_conf_new);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -144,7 +218,10 @@ reactivate (void)
|
||||
static int
|
||||
rescan (void)
|
||||
{
|
||||
unlink ("/etc/lvm/cache/.cache");
|
||||
char lvm_cache[64];
|
||||
snprintf (lvm_cache, sizeof lvm_cache, "%s/cache/.cache", lvm_system_dir);
|
||||
|
||||
unlink (lvm_cache);
|
||||
|
||||
char *err;
|
||||
int r = command (NULL, &err, "lvm", "vgscan", NULL);
|
||||
|
||||
Reference in New Issue
Block a user