]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/loop-util.c
2 This file is part of systemd.
4 Copyright 2016 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <linux/loop.h>
22 #include <sys/ioctl.h>
25 #include "alloc-util.h"
27 #include "loop-util.h"
29 int loop_device_make(int fd
, int open_flags
, LoopDevice
**ret
) {
30 const struct loop_info64 info
= {
31 .lo_flags
= LO_FLAGS_AUTOCLEAR
|LO_FLAGS_PARTSCAN
|(open_flags
== O_RDONLY
? LO_FLAGS_READ_ONLY
: 0),
34 _cleanup_close_
int control
= -1, loop
= -1;
35 _cleanup_free_
char *loopdev
= NULL
;
42 assert(IN_SET(open_flags
, O_RDWR
, O_RDONLY
));
44 if (fstat(fd
, &st
) < 0)
47 if (S_ISBLK(st
.st_mode
)) {
50 /* If this is already a block device, store a copy of the fd as it is */
52 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
56 d
= new0(LoopDevice
, 1);
70 if (!S_ISREG(st
.st_mode
))
73 control
= open("/dev/loop-control", O_RDWR
|O_CLOEXEC
|O_NOCTTY
|O_NONBLOCK
);
77 nr
= ioctl(control
, LOOP_CTL_GET_FREE
);
81 if (asprintf(&loopdev
, "/dev/loop%i", nr
) < 0)
84 loop
= open(loopdev
, O_CLOEXEC
|O_NONBLOCK
|O_NOCTTY
|open_flags
);
88 if (ioctl(loop
, LOOP_SET_FD
, fd
) < 0)
91 if (ioctl(loop
, LOOP_SET_STATUS64
, &info
) < 0)
94 d
= new(LoopDevice
, 1);
112 int loop_device_make_by_path(const char *path
, int open_flags
, LoopDevice
**ret
) {
113 _cleanup_close_
int fd
= -1;
117 assert(IN_SET(open_flags
, O_RDWR
, O_RDONLY
));
119 fd
= open(path
, O_CLOEXEC
|O_NONBLOCK
|O_NOCTTY
|open_flags
);
123 return loop_device_make(fd
, open_flags
, ret
);
126 LoopDevice
* loop_device_unref(LoopDevice
*d
) {
133 if (ioctl(d
->fd
, LOOP_CLR_FD
) < 0)
134 log_debug_errno(errno
, "Failed to clear loop device: %m");
142 _cleanup_close_
int control
= -1;
144 control
= open("/dev/loop-control", O_RDWR
|O_CLOEXEC
|O_NOCTTY
|O_NONBLOCK
);
146 log_debug_errno(errno
, "Failed to open loop control device: %m");
148 if (ioctl(control
, LOOP_CTL_REMOVE
, d
->nr
) < 0)
149 log_debug_errno(errno
, "Failed to remove loop device: %m");