]> sourceware.org Git - dm.git/commitdiff
Added error handling and changed some parts to behave same as ioctl version.
authorAlasdair Kergon <agk@redhat.com>
Tue, 4 Dec 2001 23:19:04 +0000 (23:19 +0000)
committerAlasdair Kergon <agk@redhat.com>
Tue, 4 Dec 2001 23:19:04 +0000 (23:19 +0000)
dmsetup/Makefile.in
lib/fs/libdevmapper.c

index f7c7f49a3686971ae060d3a8ca682e7dfefc3273..437942476967eb7e8bdfd0e086b2fbe326fcbf0b 100644 (file)
@@ -13,6 +13,6 @@ TARGETS=dmsetup
 
 include ../make.tmpl
 
-dmsetup: dmsetup.o $(interfacedir)/libdevmapper.so
+dmsetup: $(OBJECTS) $(interfacedir)/libdevmapper.so
        $(CC) -o dmsetup dmsetup.o $(LD_FLAGS) -ldevmapper
 
index f66a3b0e1360f871a7c2dd32259d3a77c9efacfa..924461f60bb122ffd25fada152b906906717f3e7 100644 (file)
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/uio.h>
+#include <sys/param.h>
 #include <errno.h>
+#include <linux/kdev_t.h>
 
 #define DEV_DIR "/dev/"
-#define DM_DIR "device-mapper"
-#define ALIGNMENT sizeof(int)
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
 
-#define MKDEV(x,y) ((x) << 8 | (y))
+/* FIXME Obtain from kernel header */
+#define DM_DIR "device-mapper"
 
 static char _dm_dir[PATH_MAX] = DEV_DIR DM_DIR;
 
+typedef enum {
+       DIR_CREATE,
+       DIR_REMOVE
+} do_newold_t;
+
 /*
  * Library users can provide their own logging
  * function.
@@ -69,42 +72,42 @@ struct dm_task {
 
 #define NR_ARGS 16
 
-static char *mkpath(int n, char *base, ...)
+/*
+ * Join n path components together with /'s.
+ */
+static char *mkpath(int n, ...)
 {
        va_list va;
-       char *args[NR_ARGS];
-       int len = strlen(base) + 1;
-       int i = 0;
-       char *str;
+       int len = 0, i;
+       char *str, *r;
 
-       if (n > NR_ARGS)
-               return NULL;
+       va_start(va, n);
+       for (i = 0; i < n; i++)
+               len += strlen(va_arg(va, char *)) + 1;
 
-       va_start(va, base);
-       for(i = 0; i < n; i++) {
-               args[i] = (char *)va_arg(va, char *);
-               len += strlen(args[i]);
-               len++;
-       }
        va_end(va);
 
-       str = malloc(len);
-       if (str) {
-               strcpy(str, base);
-               for(i = 0; i < n; i++) {
-                       strcat(str, "/");
-                       strcat(str, args[i]);
-               }
+       if (!(r = str = malloc(len))) {
+               log("mkpath: malloc(%d) failed", len);
+               return NULL;
        }
-       return str;
+
+       va_start(va, n);
+       for (i = 0; i < n; i++)
+               str += sprintf(str, "%s%s", i ? "/" : "", va_arg(va, char *));
+       va_end(va);
+
+       return r;
 }
 
 struct dm_task *dm_task_create(int type)
 {
        struct dm_task *dmt = malloc(sizeof(*dmt));
 
-       if (!dmt)
+       if (!dmt) {
+               log("dm_task_create: malloc(%d) failed", sizeof(*dmt));
                return NULL;
+       }
 
        memset(dmt, 0, sizeof(*dmt));
 
@@ -147,19 +150,24 @@ static struct target *_create_target(unsigned long long start,
        int size = strlen(params) + strlen(type);
        int ret;
 
-       size += 64; /* Guess at max size of start and len */
+       size += 64;             /* Guess at max size of start and len */
 
        t = malloc(size + sizeof(struct target));
-       if (!t)
+       if (!t) {
+               log("_create_target: malloc(%d) failed",
+                   size + sizeof(struct target));
                return NULL;
+       }
+
        memset(t, 0, size + sizeof(struct target));
-       t->str = (char *)(t + 1);
+       t->str = (char *) (t + 1);
 
        ret = sprintf(t->str, "%Lu %Lu %s %s\n", start, len, type, params);
        if (ret > size) {
                /* This should be impossible, but check anyway */
-               log("Internal error - ran out of buffer space");
-               exit(-1);
+               log("_create_target internal error: Ran out of buffer space");
+               free(t);
+               return NULL;
        }
 
        return t;
@@ -168,8 +176,7 @@ static struct target *_create_target(unsigned long long start,
 int dm_task_add_target(struct dm_task *dmt,
                       unsigned long long start,
                       unsigned long long size,
-                      const char *ttype,
-                      const char *params)
+                      const char *ttype, const char *params)
 {
        struct target *t = _create_target(start, size, ttype, params);
 
@@ -242,181 +249,206 @@ static int _rm_dev_node(const char *dev_name)
 
 static int do_suspend(char *mnt, char *name, int on)
 {
-       char *path = mkpath(2, mnt, name, "suspend");
-       int ret = -1;
-
-       if (path) {
-               FILE *fp = fopen(path, "rw");
-               if (fp) {
-                       if (fprintf(fp, "%d\n", on) > 0)
-                               ret = 0;
-                       fclose(fp);
-               }
-               free(path);
-       }
+       char *path;
+       FILE *fp;
+       int ret = 0;
+
+       if (!(path = mkpath(3, mnt, name, "suspend")))
+               return 0;
+
+       if ((fp = fopen(path, "rw"))) {
+               if (fprintf(fp, "%d\n", on) > 0)
+                       ret = 1;
+               else
+                       log("%s: fprintf failed: %s", path, strerror(errno));
+               fclose(fp);
+       } else
+               log("%s: fopen failed: %s", path, strerror(errno));
+
+       free(path);
 
        return ret;
 }
 
-static int do_newold(char *mnt, char *name, int create)
+static int do_newold(char *mnt, char *name, do_newold_t create)
 {
-       char *path = mkpath(1, mnt, name);
-       int ret = -1;
+       char *path = mkpath(2, mnt, name);
+       int ret;
 
-       if (path) {
-               if (create)
-                       ret = mkdir(path, 0750);
-               else
-                       ret = rmdir(path);
-               free(path);
-       }
+       if (!path)
+               return 0;
 
-       return ret;
+       if (create == DIR_CREATE) {
+               if ((ret = mkdir(path, 0750)) < 0)
+                       log("%s: mkdir failed: %s", path, strerror(errno));
+       } else if ((ret = rmdir(path)) < 0)
+               log("%s: rmdir failed: %s", path, strerror(errno));
+
+       free(path);
+
+       return (ret < 0) ? 0 : 1;
 }
 
 static int do_device(char *mnt, char *name, struct dm_info *info)
 {
-       char *path = mkpath(2, mnt, name, "device");
-       int ret = -1;
-       if (path) {
-               struct stat st;
-               if (stat(path, &st) == 0) {
-                       info->major = st.st_rdev >> 8;
-                       info->minor = st.st_rdev & 0xff;
-               }
-               free(path);
-       }
-       return ret;
+       char *path;
+       struct stat st;
+
+       if (!(path = mkpath(3, mnt, name, "device")))
+               return 0;
+
+       if (!stat(path, &st)) {
+               info->major = MAJOR(st.st_rdev);
+               info->minor = MINOR(st.st_rdev);
+               info->exists = 1;
+       } else
+               info->exists = 0;
+
+       free(path);
+       return 1;
 }
 
 static int do_suspend_state(char *mnt, char *name, struct dm_info *info)
 {
-       char *path = mkpath(2, mnt, name, "suspend");
-       int ret = -1;
-       if (path) {
-               FILE *fp = fopen(path, "r");
-               if (fp) {
-                       int state;
-                       if (fscanf(fp, "%d", &state) == 1) {
-                               info->suspended = state;
-                               ret = 0;
-                       }
-                       fclose(fp);
-               }
-               free(path);
-       }
+       char *path;
+       FILE *fp;
+       int ret = 0;
+
+       if (!(path = mkpath(3, mnt, name, "suspend")))
+               return 0;
+
+       if ((fp = fopen(path, "r"))) {
+               if (fscanf(fp, "%d", &info->suspended) == 1)
+                       ret = 1;
+               else
+                       log("%s fscanf failed: %s", path, strerror(errno));
+               fclose(fp);
+       } else
+               log("%s: fopen failed: %s", path, strerror(errno));
+
+       free(path);
+
        return ret;
 }
 
 static int do_info(char *mnt, char *name, struct dm_info *info)
 {
-       int ret;
-
        memset(info, 0, sizeof(struct dm_info));
 
-       ret = do_device(mnt, name, info);
-       if (ret < 0)
-               goto out;
-       ret = do_suspend_state(mnt, name, info);
-       if (ret < 0)
-               goto out;
-       info->exists = 1;
-out:
-       return ret;
+       if (!do_device(mnt, name, info))
+               return 0;
+
+       if (info->exists && !do_suspend_state(mnt, name, info))
+               return 0;
+
+       return 1;
 }
 
-static int write_data(int fd, struct dm_task *dmt)
+/*
+ * Writes a buffer out to a file, returns 0 on failure.
+ */
+static int write_buffer(int fd, const void *buf, size_t count)
 {
-       struct target *tmp = dmt->head;
-       int n = 0;
-       struct iovec *iov;
-       int ret = -1;
-
-       while(tmp) {
-               n++;
-               tmp = tmp->next;
-       }
+       size_t n = 0;
+       int tot = 0;
 
-       iov = malloc(n * sizeof(struct iovec));
-       if (iov) {
-               tmp = dmt->head;
-               n = 0;
-               while(tmp) {
-                       iov[n].iov_base = tmp->str;
-                       iov[n].iov_len = strlen(tmp->str);
-                       n++;
-                       tmp = tmp->next;
-               }
+       while (tot < count) {
+               do
+                       n = write(fd, buf, count - tot);
+               while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN)));
+
+               if (n <= 0)
+                       return 0;
 
-               ret = writev(fd, iov, n);
-               free(iov);
+               tot += n;
+               buf += n;
        }
 
-       return ret;
+       return 1;
+}
+
+static int write_data(int fd, struct dm_task *dmt)
+{
+       struct target *t;
+
+       for (t = dmt->head; t; t = t->next)
+               if (!write_buffer(fd, t->str, strlen(t->str)))
+                       return 0;
+
+       return 1;
 }
 
 static int do_load(char *mnt, char *name, struct dm_task *dmt)
 {
-       char *path = mkpath(2, mnt, name, "table");
-       int ret = -1;
-       if (path) {
-               int fd = open(path, O_RDWR);
-               if (fd >= 0) {
-                       ret = write_data(fd, dmt);
-                       close(fd);
-               }
+       char *path;
+       int fd, ret = 0;
+
+       if (!(path = mkpath(3, mnt, name, "table")))
+               return 0;
+
+       if ((fd = open(path, O_RDWR)) != -1) {
+               if (!(ret = write_data(fd, dmt)))
+                       log("%s: write failed: %s", path, strerror(errno));
+               close(fd);
        }
+
+       free(path);
+
        return ret;
 }
 
 static void strip_nl(char *str)
 {
-       while(*str && *str != '\n' && *str != '\r')
+       while (*str && *str != '\n' && *str != '\r')
                str++;
        *str = 0;
 }
 
 static int do_error_check(char *mnt, char *name)
 {
-       char *path = mkpath(2, mnt, name, "error");
-       int ret = -1;
-       if (path) {
-               FILE *fp = fopen(path, "r");
-               if (fp) {
-                       char buf[1024];
-                       ret = 0;
-                       while(fgets(buf, 1023, fp)) {
-                               buf[1023] = 0;
-                               strip_nl(buf);
-                               log(buf);
-                               ret = -1;
-                       }
-                       fclose(fp);
-               }
+       char *path;
+       FILE *fp;
+       int ret = 1;
+       char buf[1024];
+
+       if (!(path = mkpath(3, mnt, name, "error")))
+               return 0;
+
+       if (!(fp = fopen(path, "r"))) {
+               log("%s: fopen failed: %s", path, strerror(errno));
                free(path);
+               return 0;
+       }
+
+       while (fgets(buf, sizeof(buf), fp)) {
+               strip_nl(buf);
+               log(buf);
+               ret = 0;
        }
+
+       fclose(fp);
+       free(path);
        return ret;
 }
 
 static char *find_mount_point(void)
 {
-       FILE *fp = fopen("/proc/mounts", "r");
-static char mpoint[4096];
-       if (fp) {
-               int fsdump, fspass;
-               char device[1024];
-               char fstype[30];
-               char fsoptions[4096];
-               while(fscanf(fp, "%1024s %4096s %30s %4096s %d %d", device, mpoint, fstype, fsoptions, &fsdump, &fspass) == 6) {
-                       if (strlen(fstype) != 4)
-                               continue;
-                       if (strcmp(fstype, "dmfs"))
-                               continue;
+       FILE *fp;
+       static char mpoint[4096];
+       char fstype[30];
+
+       if ((fp = fopen("/proc/mounts", "r")) < 0) {
+               log("/proc/mounts: fopen failed: %s", strerror(errno));
+               return NULL;
+       }
+
+       while (fscanf(fp, "%*s%4096s%30s%*s%*d%*d", mpoint, fstype) == 2) {
+               if (!strcmp(fstype, "dmfs")) {
                        fclose(fp);
                        return mpoint;
                }
-               fclose(fp);
        }
+       fclose(fp);
        return NULL;
 }
 
@@ -425,59 +457,60 @@ int dm_task_run(struct dm_task *dmt)
        char *mnt = find_mount_point();
 
        if (mnt == NULL) {
+               /* FIXME Mount it temporarily if not mounted */
                log("Cannot find mount point for dmfs or dmfs not mounted");
-               goto bad;
+               return 0;
+       }
+
+       if (!dmt->dev_name || !*dmt->dev_name) {
+               log("dm_task_run: Device name not supplied");
+               return 0;
        }
 
        switch (dmt->type) {
        case DM_DEVICE_CREATE:
-               do_newold(mnt, dmt->dev_name, 1);
-               do_info(mnt, dmt->dev_name, &dmt->info);
+               if (!do_newold(mnt, dmt->dev_name, DIR_CREATE) ||
+                   !do_load(mnt, dmt->dev_name, dmt) ||
+                   !do_error_check(mnt, dmt->dev_name) ||
+                   !do_info(mnt, dmt->dev_name, &dmt->info))
+                       return 0;
+               _add_dev_node(dmt->dev_name,
+                             MKDEV(dmt->info.major, dmt->info.minor));
                break;
 
        case DM_DEVICE_RELOAD:
-               do_load(mnt, dmt->dev_name, dmt);
-               do_error_check(mnt, dmt->dev_name);
+               if (!do_load(mnt, dmt->dev_name, dmt) ||
+                   !do_error_check(mnt, dmt->dev_name)) return 0;
                break;
 
        case DM_DEVICE_REMOVE:
-               do_newold(mnt, dmt->dev_name, 1);
-               dmt->info.exists = 0;
+               if (!do_newold(mnt, dmt->dev_name, DIR_REMOVE) ||
+                   !do_info(mnt, dmt->dev_name, &dmt->info))
+                       return 0;
+               _rm_dev_node(dmt->dev_name);
                break;
 
        case DM_DEVICE_SUSPEND:
-               do_suspend(mnt, dmt->dev_name, 1);
+               if (!do_suspend(mnt, dmt->dev_name, 1))
+                       return 0;
                break;
 
        case DM_DEVICE_RESUME:
-               do_suspend(mnt, dmt->dev_name, 0);
+               if (!do_suspend(mnt, dmt->dev_name, 0))
+                       return 0;
                break;
 
        case DM_DEVICE_INFO:
-               do_info(mnt, dmt->dev_name, &dmt->info);
+               if (!do_info(mnt, dmt->dev_name, &dmt->info))
+                       return 0;
                break;
 
        default:
-               log("Internal error: unknown device-mapper task %d",
-                   dmt->type);
-               goto bad;
-       }
-
-       switch (dmt->type) {
-       case DM_DEVICE_CREATE:
-               _add_dev_node(dmt->dev_name,
-                             MKDEV(dmt->info.major, dmt->info.minor));
-               break;
-
-       case DM_DEVICE_REMOVE:
-               _rm_dev_node(dmt->dev_name);
-               break;
+               log("Internal error: unknown device-mapper task %d", dmt->type);
+               return 0;
        }
 
        return 1;
-
- bad:
-       return 0;
 }
 
 int dm_set_dev_dir(const char *dir)
This page took 0.078424 seconds and 5 git commands to generate.