-int device_ready(struct crypt_device *cd, const char *device, int mode)
-{
- int devfd, r = 0;
- ssize_t s;
- struct stat st;
- char buf[512];
-
- if(stat(device, &st) < 0) {
- log_err(cd, _("Device %s doesn't exist or access denied.\n"), device);
- return -EINVAL;
- }
-
- if (!S_ISBLK(st.st_mode))
- return -ENOTBLK;
-
- log_dbg("Trying to open and read device %s.", device);
- devfd = open(device, mode | O_DIRECT | O_SYNC);
- if(devfd < 0) {
- log_err(cd, _("Cannot open device %s for %s%s access.\n"), device,
- (mode & O_EXCL) ? _("exclusive ") : "",
- (mode & O_RDWR) ? _("writable") : _("read-only"));
- return -EINVAL;
- }
-
- /* Try to read first sector */
- s = read_blockwise(devfd, buf, sizeof(buf));
- if (s < 0 || s != sizeof(buf)) {
- log_verbose(cd, _("Cannot read device %s.\n"), device);
- r = -EIO;
- }
-
- memset(buf, 0, sizeof(buf));
- close(devfd);
-
- return r;
-}
-
-int device_size(const char *device, uint64_t *size)
-{
- int devfd, r = 0;
-
- devfd = open(device, O_RDONLY);
- if(devfd == -1)
- return -EINVAL;
-
- if (ioctl(devfd, BLKGETSIZE64, size) < 0)
- r = -EINVAL;
-
- close(devfd);
- return r;
-}
-
-static int get_device_infos(const char *device, enum devcheck device_check,
- int *readonly, uint64_t *size)
-{
- struct stat st;
- unsigned long size_small;
- int fd, r = -1;
- int flags = 0;
-
- *readonly = 0;
- *size = 0;
-
- if (stat(device, &st) < 0)
- return -EINVAL;
-
- /* never wipe header on mounted device */
- if (device_check == DEV_EXCL && S_ISBLK(st.st_mode))
- flags |= O_EXCL;
-
- /* Try to open read-write to check whether it is a read-only device */
- fd = open(device, O_RDWR | flags);
- if (fd == -1 && errno == EROFS) {
- *readonly = 1;
- fd = open(device, O_RDONLY | flags);
- }
-
- if (fd == -1 && device_check == DEV_EXCL && errno == EBUSY)
- return -EBUSY;
-
- if (fd == -1)
- return -EINVAL;
-
- /* If the device can be opened read-write, i.e. readonly is still 0, then
- * check whether BKROGET says that it is read-only. E.g. read-only loop
- * devices may be openend read-write but are read-only according to BLKROGET
- */
- if (*readonly == 0 && (r = ioctl(fd, BLKROGET, readonly)) < 0)
- goto out;
-
- if (ioctl(fd, BLKGETSIZE64, size) >= 0) {
- *size >>= SECTOR_SHIFT;
- r = 0;
- goto out;
- }
-
- if (ioctl(fd, BLKGETSIZE, &size_small) >= 0) {
- *size = (uint64_t)size_small;
- r = 0;
- goto out;
- }
-
- r = -EINVAL;
-out:
- close(fd);
- return r;
-}
-
-int device_check_and_adjust(struct crypt_device *cd,
- const char *device,
- enum devcheck device_check,
- uint64_t *size,
- uint64_t *offset,
- uint32_t *flags)
-{
- int r, real_readonly;
- uint64_t real_size;
-
- if (!device)
- return -ENOTBLK;
-
- r = get_device_infos(device, device_check, &real_readonly, &real_size);
- if (r < 0) {
- if (r == -EBUSY)
- log_err(cd, _("Cannot use device %s which is in use "
- "(already mapped or mounted).\n"),
- device);
- else
- log_err(cd, _("Cannot get info about device %s.\n"),
- device);
- return r;
- }
-
- if (*offset >= real_size) {
- log_err(cd, _("Requested offset is beyond real size of device %s.\n"),
- device);
- return -EINVAL;
- }
-
- if (!*size) {
- *size = real_size;
- if (!*size) {
- log_err(cd, _("Device %s has zero size.\n"), device);
- return -ENOTBLK;
- }
- *size -= *offset;
- }
-
- /* in case of size is set by parameter */
- if ((real_size - *offset) < *size) {
- log_dbg("Device %s: offset = %" PRIu64 " requested size = %" PRIu64
- ", backing device size = %" PRIu64,
- device, *offset, *size, real_size);
- log_err(cd, _("Device %s is too small.\n"), device);
- return -EINVAL;
- }
-
- if (real_readonly)
- *flags |= CRYPT_ACTIVATE_READONLY;
-
- log_dbg("Calculated device size is %" PRIu64 " sectors (%s), offset %" PRIu64 ".",
- *size, real_readonly ? "RO" : "RW", *offset);
- return 0;
-}
-