Change License from GPLv2 only to GPLv2+ ("or any later").
[platform/upstream/cryptsetup.git] / lib / utils_device.c
index 3008ff3..44282a6 100644 (file)
@@ -4,10 +4,12 @@
  * Copyright (C) 2004, Christophe Saout <christophe@saout.de>
  * Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
  * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2012, Milan Broz
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -44,20 +46,16 @@ static int device_ready(const char *device)
        int devfd, r = 0;
        struct stat st;
 
-       if(stat(device, &st) < 0) {
-               log_err(NULL, _("Device %s doesn't exist or access denied.\n"), device);
-               return -EINVAL;
-       }
-
-       if (!S_ISBLK(st.st_mode))
-               return S_ISREG(st.st_mode) ? -ENOTBLK : -EINVAL;
-
        log_dbg("Trying to open and read device %s.", device);
        devfd = open(device, O_RDONLY | O_DIRECT | O_SYNC);
-       if(devfd < 0) {
-               log_err(NULL, _("Cannot open device %s.\n"), device);
+       if (devfd < 0) {
+               log_err(NULL, _("Device %s doesn't exist or access denied.\n"), device);
                return -EINVAL;
        }
+       if (fstat(devfd, &st) < 0)
+               r = -EINVAL;
+       else if (!S_ISBLK(st.st_mode))
+               r = S_ISREG(st.st_mode) ? -ENOTBLK : -EINVAL;
 
        close(devfd);
        return r;
@@ -282,6 +280,7 @@ static int device_info(struct device *device,
                flags |= O_EXCL;
 
        /* Try to open read-write to check whether it is a read-only device */
+       /* coverity[toctou] */
        fd = open(device->path, O_RDWR | flags);
        if (fd == -1 && errno == EROFS) {
                *readonly = 1;
@@ -326,11 +325,15 @@ static int device_internal_prepare(struct crypt_device *cd, struct device *devic
        if (device->init_done)
                return 0;
 
-       log_dbg("Allocating free loop device.");
+       log_dbg("Allocating free loop device.");
        loop_device = crypt_loop_get_device();
        if (!loop_device) {
-               log_err(cd, _("Cannot find a free loopback device.\n"));
-               return -EINVAL;
+               if (getuid() || geteuid())
+                       log_err(cd, _("Cannot use a loopback device, "
+                                     "running as non-root user.\n"));
+               else
+                       log_err(cd, _("Cannot find a free loopback device.\n"));
+               return -ENOTSUP;
        }
 
        /* Keep the loop open, dettached on last close. */
@@ -417,3 +420,9 @@ int device_block_adjust(struct crypt_device *cd,
                *size, real_readonly ? "RO" : "RW", device_offset);
        return 0;
 }
+
+size_t size_round_up(size_t size, unsigned int block)
+{
+       size_t s = (size + (block - 1)) / block;
+       return s * block;
+}