1 /* vi: set sw=4 ts=4: */
5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6 * Copyright (C) 2005 by Rob Landley <rob@landley.net>
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
11 #include <linux/version.h>
13 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
15 /* For 2.6, use the cleaned up header to get the 64 bit API. */
16 // Commented out per Rob's request
17 //# include "fix_u32.h" /* some old toolchains need __u64 for linux/loop.h */
18 # include <linux/loop.h>
19 typedef struct loop_info64 bb_loop_info
;
20 # define BB_LOOP_SET_STATUS LOOP_SET_STATUS64
21 # define BB_LOOP_GET_STATUS LOOP_GET_STATUS64
25 /* For 2.4 and earlier, use the 32 bit API (and don't trust the headers) */
26 /* Stuff stolen from linux/loop.h for 2.4 and earlier kernels */
27 # include <linux/posix_types.h>
28 # define LO_NAME_SIZE 64
29 # define LO_KEY_SIZE 32
30 # define LOOP_SET_FD 0x4C00
31 # define LOOP_CLR_FD 0x4C01
32 # define BB_LOOP_SET_STATUS 0x4C02
33 # define BB_LOOP_GET_STATUS 0x4C03
36 __kernel_dev_t lo_device
;
37 unsigned long lo_inode
;
38 __kernel_dev_t lo_rdevice
;
41 int lo_encrypt_key_size
;
43 char lo_file_name
[LO_NAME_SIZE
];
44 unsigned char lo_encrypt_key
[LO_KEY_SIZE
];
45 unsigned long lo_init
[2];
50 char* FAST_FUNC
query_loop(const char *device
)
53 bb_loop_info loopinfo
;
56 fd
= open(device
, O_RDONLY
);
58 if (ioctl(fd
, BB_LOOP_GET_STATUS
, &loopinfo
) == 0) {
59 dev
= xasprintf("%"OFF_FMT
"u %s", (off_t
) loopinfo
.lo_offset
,
60 (char *)loopinfo
.lo_file_name
);
68 int FAST_FUNC
del_loop(const char *device
)
72 fd
= open(device
, O_RDONLY
);
75 rc
= ioctl(fd
, LOOP_CLR_FD
, 0);
81 /* Returns 0 if mounted RW, 1 if mounted read-only, <0 for error.
82 *device is loop device to use, or if *device==NULL finds a loop device to
83 mount it on and sets *device to a strdup of that loop device name. This
84 search will re-use an existing loop device already bound to that
85 file/offset if it finds one.
87 int FAST_FUNC
set_loop(char **device
, const char *file
, unsigned long long offset
, int ro
)
89 char dev
[LOOP_NAMESIZE
];
91 bb_loop_info loopinfo
;
93 int i
, dfd
, ffd
, mode
, rc
= -1;
95 /* Open the file. Barf if this doesn't work. */
96 mode
= ro
? O_RDONLY
: O_RDWR
;
97 ffd
= open(file
, mode
);
99 if (mode
!= O_RDONLY
) {
101 ffd
= open(file
, mode
);
107 /* Find a loop device. */
108 try = *device
? *device
: dev
;
109 /* 1048575 is a max possible minor number in Linux circa 2010 */
110 for (i
= 0; rc
&& i
< 1048576; i
++) {
111 sprintf(dev
, LOOP_FORMAT
, i
);
113 IF_FEATURE_MOUNT_LOOP_CREATE(errno
= 0;)
114 if (stat(try, &statbuf
) != 0 || !S_ISBLK(statbuf
.st_mode
)) {
115 if (ENABLE_FEATURE_MOUNT_LOOP_CREATE
119 /* Node doesn't exist, try to create it. */
120 if (mknod(dev
, S_IFBLK
|0644, makedev(7, i
)) == 0)
123 /* Ran out of block devices, return failure. */
128 /* Open the sucker and check its loopiness. */
129 dfd
= open(try, mode
);
130 if (dfd
< 0 && errno
== EROFS
) {
132 dfd
= open(try, mode
);
137 rc
= ioctl(dfd
, BB_LOOP_GET_STATUS
, &loopinfo
);
139 /* If device is free, claim it. */
140 if (rc
&& errno
== ENXIO
) {
141 memset(&loopinfo
, 0, sizeof(loopinfo
));
142 safe_strncpy((char *)loopinfo
.lo_file_name
, file
, LO_NAME_SIZE
);
143 loopinfo
.lo_offset
= offset
;
144 /* Associate free loop device with file. */
145 if (ioctl(dfd
, LOOP_SET_FD
, ffd
) == 0) {
146 if (ioctl(dfd
, BB_LOOP_SET_STATUS
, &loopinfo
) == 0)
149 ioctl(dfd
, LOOP_CLR_FD
, 0);
152 /* If this block device already set up right, re-use it.
153 * (Yes this is racy, but associating two loop devices with the same
154 * file isn't pretty either. In general, mounting the same file twice
155 * without using losetup manually is problematic.)
158 if (strcmp(file
, (char *)loopinfo
.lo_file_name
) != 0
159 || offset
!= loopinfo
.lo_offset
170 *device
= xstrdup(dev
);
171 return (mode
== O_RDONLY
); /* 1:ro, 0:rw */