]> git.proxmox.com Git - mirror_lxc.git/blobdiff - src/lxc/storage/storage_utils.c
storage_utils: add error handling
[mirror_lxc.git] / src / lxc / storage / storage_utils.c
index b0a19043802ebf2f3ab50219ca922276b4a4bc60..2584b556c716a334cc1c0455edc8beaf0a953671 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#define _GNU_SOURCE
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+#include <ctype.h>
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
-#include <unistd.h>
 #include <sys/mount.h>
 #include <sys/prctl.h>
-#include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/types.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
+#include "config.h"
 #include "log.h"
 #include "nbd.h"
 #include "parse.h"
 #include "storage.h"
 #include "storage_utils.h"
+#include "syscall_wrappers.h"
 #include "utils.h"
 
 #ifndef HAVE_STRLCPY
@@ -148,12 +153,18 @@ int blk_getsize(struct lxc_storage *bdev, uint64_t *size)
        const char *src;
 
        src = lxc_storage_get_path(bdev->src, bdev->type);
-       fd = open(src, O_RDONLY);
-       if (fd < 0)
+
+       fd = open(src, O_RDONLY | O_CLOEXEC);
+       if (fd < 0) {
+               SYSERROR("Failed to open \"%s\"", src);
                return -1;
+       }
 
        /* size of device in bytes */
        ret = ioctl(fd, BLKGETSIZE64, size);
+       if (ret < 0)
+               SYSERROR("Failed to get block size of dev-src");
+
        close(fd);
        return ret;
 }
@@ -181,7 +192,7 @@ int detect_fs(struct lxc_storage *bdev, char *type, int len)
        FILE *f;
        char *sp1, *sp2, *sp3;
        const char *l, *srcdev;
-       char devpath[MAXPATHLEN];
+       char devpath[PATH_MAX];
        char *line = NULL;
 
        if (!bdev || !bdev->src || !bdev->dest)
@@ -190,11 +201,16 @@ int detect_fs(struct lxc_storage *bdev, char *type, int len)
        srcdev = lxc_storage_get_path(bdev->src, bdev->type);
 
        ret = pipe(p);
-       if (ret < 0)
+       if (ret < 0) {
+               SYSERROR("Failed to create pipe");
                return -1;
+       }
 
-       if ((pid = fork()) < 0)
+       pid = fork();
+       if (pid < 0) {
+               SYSERROR("Failed to fork process");
                return -1;
+       }
 
        if (pid > 0) {
                int status;
@@ -404,17 +420,19 @@ const char *linkderef(const char *path, char *dest)
        ssize_t ret;
 
        ret = stat(path, &sbuf);
-       if (ret < 0)
+       if (ret < 0) {
+               SYSERROR("Failed to get status of file - \"%s\"", path);
                return NULL;
+       }
 
        if (!S_ISLNK(sbuf.st_mode))
                return path;
 
-       ret = readlink(path, dest, MAXPATHLEN);
+       ret = readlink(path, dest, PATH_MAX);
        if (ret < 0) {
                SYSERROR("error reading link %s", path);
                return NULL;
-       } else if (ret >= MAXPATHLEN) {
+       } else if (ret >= PATH_MAX) {
                ERROR("link in %s too long", path);
                return NULL;
        }
@@ -457,6 +475,40 @@ bool unpriv_snap_allowed(struct lxc_storage *b, const char *t, bool snap,
        return false;
 }
 
+uint64_t get_fssize(char *s)
+{
+       uint64_t ret;
+       char *end;
+
+       ret = strtoull(s, &end, 0);
+       if (end == s) {
+               ERROR("Invalid blockdev size '%s', using default size", s);
+               return 0;
+       }
+
+       while (isblank(*end))
+               end++;
+
+       if (*end == '\0') {
+               ret *= 1024ULL * 1024ULL; /* MB by default */
+       } else if (*end == 'b' || *end == 'B') {
+               ret *= 1ULL;
+       } else if (*end == 'k' || *end == 'K') {
+               ret *= 1024ULL;
+       } else if (*end == 'm' || *end == 'M') {
+               ret *= 1024ULL * 1024ULL;
+       } else if (*end == 'g' || *end == 'G') {
+               ret *= 1024ULL * 1024ULL * 1024ULL;
+       } else if (*end == 't' || *end == 'T') {
+               ret *= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
+       } else {
+               ERROR("Invalid blockdev unit size '%c' in '%s', using default size", *end, s);
+               return 0;
+       }
+
+       return ret;
+}
+
 bool is_valid_storage_type(const char *type)
 {
        if (strcmp(type, "dir") == 0 ||
@@ -478,20 +530,22 @@ int storage_destroy_wrapper(void *data)
        struct lxc_conf *conf = data;
 
        if (setgid(0) < 0) {
-               ERROR("Failed to setgid to 0");
+               SYSERROR("Failed to setgid to 0");
                return -1;
        }
 
        if (setgroups(0, NULL) < 0)
-               WARN("Failed to clear groups");
+               SYSWARN("Failed to clear groups");
 
        if (setuid(0) < 0) {
-               ERROR("Failed to setuid to 0");
+               SYSERROR("Failed to setuid to 0");
                return -1;
        }
 
-       if (!storage_destroy(conf))
+       if (!storage_destroy(conf)) {
+               ERROR("Failed to destroy storage");
                return -1;
+       }
 
        return 0;
 }