]> sourceware.org Git - dm.git/commitdiff
Attempt to fix /dev/mapper/control transparently if it's wrong.
authorAlasdair Kergon <agk@redhat.com>
Thu, 6 Jan 2005 18:22:43 +0000 (18:22 +0000)
committerAlasdair Kergon <agk@redhat.com>
Thu, 6 Jan 2005 18:22:43 +0000 (18:22 +0000)
WHATS_NEW
include/.symlinks
include/intl.h [new file with mode: 0644]
include/lib.h [new file with mode: 0644]
lib/Makefile.in
lib/ioctl/libdm-iface.c
lib/libdm-common.c
lib/libdm-common.h.in
lib/libdm-file.c [new file with mode: 0644]
lib/libdm-file.h [new file with mode: 0644]

index 05808537da83125de3ba1d4d02c58e667f76594b..722e94869b60adaed19549817c51f950138f726b 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
 Version 1.00.20 -
 =============================
+  Attempt to fix /dev/mapper/control transparently if it's wrong.
   Configuration-time option for setting uid/gid/mode for /dev/mapper nodes.
   Update kernel patches for 2.4.27/2.4.28-pre-4 (includes minor fixes).
   Add --noheadings columns option for colon-separated dmsetup output.
index d6da3b438b29356c9e288f7ef47f003cf21cffc5..01c6fdcf39dd6be289a710d71eb15ffea802be82 100644 (file)
@@ -1,2 +1,3 @@
 ../lib/libdevmapper.h
+../lib/libdm-file.h
 ../po/pogen.h
diff --git a/include/intl.h b/include/intl.h
new file mode 100644 (file)
index 0000000..ed6335d
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LVM_INTL_H
+#define _LVM_INTL_H
+
+#ifdef INTL_PACKAGE
+#  include <libintl.h>
+#  define _(String) dgettext(INTL_PACKAGE, (String))
+#else
+#  define _(String) (String)
+#endif
+
+#endif
diff --git a/include/lib.h b/include/lib.h
new file mode 100644 (file)
index 0000000..9b779dc
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * This file must be included first by every library source file.
+ */
+#ifndef _LVM_LIB_H
+#define _LVM_LIB_H
+
+#define _REENTRANT
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include "log.h"
+#include "intl.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#endif
index 5f5309e415deeaee88c37cf43dd5adecb9f54077..2d7c23a216ea86976c9c7a297ce33a8cce11017b 100644 (file)
@@ -1,6 +1,6 @@
 #
 # Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
-# Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+# Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
 #
 # This file is part of the device-mapper userspace tools.
 #
@@ -17,7 +17,7 @@ top_srcdir = @top_srcdir@
 VPATH = @srcdir@
 interface = @interface@
 
-SOURCES = libdm-common.c $(interface)/libdm-iface.c
+SOURCES = libdm-common.c libdm-file.c $(interface)/libdm-iface.c
 
 INCLUDES = -I$(interface)
 
index 555cdf6272c96d0fac18afb8f2f6011d6fde38a8..460a7d2fb6e526dad13454e5c2c168bb2032eaa2 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
  *
  * This file is part of the device-mapper userspace tools.
  *
  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include "lib.h"
 #include "libdm-targets.h"
 #include "libdm-common.h"
-#include "log.h"
+#include "libdm-file.h"
 
 #ifdef DM_COMPAT
 #  include "libdm-compat.h"
 #endif
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
 #include <fcntl.h>
 #include <dirent.h>
-#include <errno.h>
-#include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <limits.h>
 
 #error The version of dm-ioctl.h included is incompatible.
 #endif
 
+/* FIXME This should be exported in device-mapper.h */
+#define DM_NAME "device-mapper"
+
+#define PROC_MISC "/proc/misc"
+#define PROC_DEVICES "/proc/devices"
+#define MISC_NAME "misc"
+
 /* dm major version no for running kernel */
 static int _dm_version = DM_VERSION_MAJOR;
 static int _log_suppress = 0;
@@ -114,22 +116,144 @@ static void *_align(void *ptr, unsigned int a)
        return (void *) (((unsigned long) ptr + agn) & ~agn);
 }
 
+static int _get_proc_number(const char *file, const char *name,
+                           uint32_t *number)
+{
+       FILE *fl;
+       char nm[256];
+       int c;
+
+       if (!(fl = fopen(file, "r"))) {
+               log_error("%s: fopen failed: %s", file, strerror(errno));
+               return 0;
+       }
+
+       while (!feof(fl)) {
+               if (fscanf(fl, "%d %255s\n", number, &nm[0]) == 2) {
+                       if (!strcmp(name, nm)) {
+                               fclose(fl);
+                               return 1;
+                       }
+               }
+               do {
+                       c = fgetc(fl);
+               } while (c != EOF && c != '\n');
+       }
+       fclose(fl);
+
+       log_error("%s: No entry for %s found", file, name);
+       return 0;
+}
+
+static int _control_device_number(uint32_t *major, uint32_t *minor)
+{
+       if (!_get_proc_number(PROC_DEVICES, MISC_NAME, major) ||
+           !_get_proc_number(PROC_MISC, DM_NAME, minor)) {
+               *major = 0;
+               return 0;
+       }
+
+       return 1;
+}
+
+/*
+ * Returns 1 if exists; 0 if it doesn't; -1 if it's wrong
+ */
+static int _control_exists(const char *control, uint32_t major, uint32_t minor)
+{
+       struct stat buf;
+
+       if (stat(control, &buf) < 0) {
+               if (errno != ENOENT)
+                       log_error("%s: stat failed: %s", control,
+                                 strerror(errno));
+               return 0;
+       }
+
+       if (!S_ISCHR(buf.st_mode)) {
+               log_verbose("%s: Wrong inode type", control);
+               if (!unlink(control))
+                       return 0;
+               log_error("%s: unlink failed: %s", control,
+                         strerror(errno));
+               return -1;
+       }
+
+       if (major && buf.st_rdev != MKDEV(major, minor)) {
+               log_verbose("%s: Wrong device number: (%u, %u) instead of "
+                           "(%u, %u)", control,
+                           MAJOR(buf.st_mode), MINOR(buf.st_mode),
+                           major, minor);
+               if (!unlink(control))
+                       return 0;
+               log_error("%s: unlink failed: %s", control,
+                         strerror(errno));
+               return -1;
+       }
+
+       return 1;
+}
+
+static int _create_control(const char *control, uint32_t major, uint32_t minor)
+{
+       int ret;
+       mode_t old_umask;
+
+       if (!major)
+               return 0;
+
+       old_umask = umask(0022);
+       ret = create_dir(dm_dir());
+       umask(old_umask);
+
+       if (!ret)
+               return 0;
+
+       log_verbose("Creating device %s (%u, %u)", control, major, minor);
+
+       if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR,
+                 MKDEV(major, minor)) < 0)  {
+               log_error("%s: mknod failed: %s", control, strerror(errno));
+               return 0;
+       }
+
+#ifdef HAVE_SELINUX
+        if (!set_selinux_context(control)) {
+                stack;
+                return 0;
+        }
+#endif
+
+       return 1;
+}
+
 static int _open_control(void)
 {
        char control[PATH_MAX];
+       uint32_t major = 0, minor;
 
        if (_control_fd != -1)
                return 1;
 
        snprintf(control, sizeof(control), "%s/control", dm_dir());
 
+       if (!_control_device_number(&major, &minor))
+               log_error("Is device-mapper driver missing from kernel?");
+
+       if (!_control_exists(control, major, minor) &&
+           !_create_control(control, major, minor))
+               goto error;
+
        if ((_control_fd = open(control, O_RDWR)) < 0) {
                log_error("%s: open failed: %s", control, strerror(errno));
-               log_error("Is device-mapper driver missing from kernel?");
-               return 0;
+               goto error;
        }
 
        return 1;
+
+error:
+       log_error("Failure to communicate with kernel device-mapper driver.");
+       return 0;
 }
 
 void dm_task_destroy(struct dm_task *dmt)
index 2e9b05f27d35f2d6965b6100dc80a33456cf019f..44f4dfe8c9c5618feec4aa81b84330f4929aea77 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
  *
  * This file is part of the device-mapper userspace tools.
  *
  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include "lib.h"
 #include "libdm-targets.h"
 #include "libdm-common.h"
 #include "list.h"
-#include "log.h"
 #include "kdev_t.h"
 
-#include <stdio.h>
-#include <stdlib.h>
 #include <stdarg.h>
-#include <string.h>
 #include <sys/param.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
 #include <linux/dm-ioctl.h>
 
 #ifdef HAVE_SELINUX
@@ -100,14 +94,14 @@ struct dm_task *dm_task_create(int type)
 {
        struct dm_task *dmt = malloc(sizeof(*dmt));
 
-       if (!dm_check_version())
-               return NULL;
-
        if (!dmt) {
                log_error("dm_task_create: malloc(%d) failed", sizeof(*dmt));
                return NULL;
        }
 
+       if (!dm_check_version())
+               return NULL;
+
        memset(dmt, 0, sizeof(*dmt));
 
        dmt->type = type;
@@ -205,7 +199,7 @@ int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size,
 }
 
 #ifdef HAVE_SELINUX
-static int _set_selinux_context(const char *path)
+int set_selinux_context(const char *path)
 {
        security_context_t scontext;
 
@@ -270,7 +264,7 @@ static int _add_dev_node(const char *dev_name, uint32_t major, uint32_t minor,
        }
 
 #ifdef HAVE_SELINUX
-       if (!_set_selinux_context(path))
+       if (!set_selinux_context(path))
                return 0;
 #endif
 
index c2a97e962ae2f6e85844cd4c1db67ab475b0500a..5129e45766b986ca637ce6dbcb9c7341c0ae512e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
  *
  * This file is part of the device-mapper userspace tools.
  *
@@ -28,6 +28,8 @@ int rm_dev_node(const char *dev_name);
 int rename_dev_node(const char *old_name, const char *new_name);
 void update_devs(void);
 
+int set_selinux_context(const char *path);
+
 #define DM_LIB_VERSION @DM_LIB_VERSION@
 
 #endif
diff --git a/lib/libdm-file.c b/lib/libdm-file.c
new file mode 100644 (file)
index 0000000..5295b9e
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "libdm-file.h"
+
+#include <sys/file.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <malloc.h>
+
+static int _create_dir_recursive(const char *dir)
+{
+       char *orig, *s;
+       int rc;
+
+       log_verbose("Creating directory \"%s\"", dir);
+       /* Create parent directories */
+       orig = s = strdup(dir);
+       while ((s = strchr(s, '/')) != NULL) {
+               *s = '\0';
+               if (*orig) {
+                       rc = mkdir(orig, 0777);
+                       if (rc < 0 && errno != EEXIST) {
+                               log_error("%s: mkdir failed: %s", orig,
+                                         strerror(errno));
+                               free(orig);
+                               return 0;
+                       }
+               }
+               *s++ = '/';
+       }
+       free(orig);
+
+       /* Create final directory */
+       rc = mkdir(dir, 0777);
+       if (rc < 0 && errno != EEXIST) {
+               log_error("%s: mkdir failed: %s", orig,
+                         strerror(errno));
+               return 0;
+       }
+       return 1;
+}
+
+int create_dir(const char *dir)
+{
+       struct stat info;
+
+       if (!*dir)
+               return 1;
+
+       if (stat(dir, &info) < 0)
+               return _create_dir_recursive(dir);
+
+       if (S_ISDIR(info.st_mode))
+               return 1;
+
+       log_error("Directory \"%s\" not found", dir);
+       return 0;
+}
+
diff --git a/lib/libdm-file.h b/lib/libdm-file.h
new file mode 100644 (file)
index 0000000..b2d48e2
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.  
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of the device-mapper userspace tools.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef LIB_DMFILE_H
+#define LIB_DMFILE_H
+
+/*
+ * Create directory (recursively) if necessary.  Return 1
+ * if directory was successfully created (or already exists), else 0.
+ */
+int create_dir(const char *dir);
+
+#endif
This page took 0.045359 seconds and 5 git commands to generate.