#include "stat-util.h"
#include "stdio-util.h"
+static void cleanup_clear_loop_close(int *fd) {
+ if (*fd >= 0) {
+ (void) ioctl(*fd, LOOP_CLR_FD);
+ (void) safe_close(*fd);
+ }
+}
+
int loop_device_make_full(
int fd,
int open_flags,
uint32_t loop_flags,
LoopDevice **ret) {
- _cleanup_close_ int control = -1, loop = -1;
_cleanup_free_ char *loopdev = NULL;
- unsigned n_attempts = 0;
struct loop_info64 info;
LoopDevice *d = NULL;
struct stat st;
d = new(LoopDevice, 1);
if (!d)
return -ENOMEM;
-
*d = (LoopDevice) {
.fd = TAKE_FD(copy),
.nr = nr,
return r;
}
+ _cleanup_close_ int control = -1;
+ _cleanup_(cleanup_clear_loop_close) int loop_with_fd = -1;
+
control = open("/dev/loop-control", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
if (control < 0)
return -errno;
/* Loop around LOOP_CTL_GET_FREE, since at the moment we attempt to open the returned device it might
* be gone already, taken by somebody else racing against us. */
- for (;;) {
+ for (unsigned n_attempts = 0;;) {
+ _cleanup_close_ int loop = -1;
+
nr = ioctl(control, LOOP_CTL_GET_FREE);
if (nr < 0)
return -errno;
loop = open(loopdev, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|open_flags);
if (loop < 0)
return -errno;
- if (ioctl(loop, LOOP_SET_FD, fd) < 0) {
- if (errno != EBUSY)
- return -errno;
-
- if (++n_attempts >= 64) /* Give up eventually */
- return -EBUSY;
- } else
+ if (ioctl(loop, LOOP_SET_FD, fd) >= 0) {
+ loop_with_fd = TAKE_FD(loop);
break;
+ }
+ if (errno != EBUSY)
+ return -errno;
+ if (++n_attempts >= 64) /* Give up eventually */
+ return -EBUSY;
loopdev = mfree(loopdev);
- loop = safe_close(loop);
}
info = (struct loop_info64) {
.lo_sizelimit = size == UINT64_MAX ? 0 : size,
};
- if (ioctl(loop, LOOP_SET_STATUS64, &info) < 0) {
- r = -errno;
- goto fail;
- }
+ if (ioctl(loop_with_fd, LOOP_SET_STATUS64, &info) < 0)
+ return -errno;
d = new(LoopDevice, 1);
- if (!d) {
- r = -ENOMEM;
- goto fail;
- }
-
+ if (!d)
+ return -ENOMEM;
*d = (LoopDevice) {
- .fd = TAKE_FD(loop),
+ .fd = TAKE_FD(loop_with_fd),
.node = TAKE_PTR(loopdev),
.nr = nr,
};
*ret = d;
- return d->fd;
-
-fail:
- if (fd >= 0)
- (void) ioctl(fd, LOOP_CLR_FD);
- if (d && d->fd >= 0)
- (void) ioctl(d->fd, LOOP_CLR_FD);
-
- return r;
+ return 0;
}
int loop_device_make_by_path(const char *path, int open_flags, uint32_t loop_flags, LoopDevice **ret) {