]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - mount/lomount.c
1 /* Taken from Ted's losetup.c - Mitch <m.dsouza@mrc-apu.cam.ac.uk> */
2 /* Added vfs mount options - aeb - 960223 */
3 /* Removed lomount - aeb - 960224 */
5 /* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
6 * - added Native Language Support
7 * Sun Mar 21 1999 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
8 * - fixed strerr(errno) in gettext calls
11 #define PROC_DEVICES "/proc/devices"
14 * losetup.c - setup and control loop devices
24 #include <sys/ioctl.h>
33 extern char *xstrdup (const char *s
); /* not: #include "sundries.h" */
34 extern void error (const char *fmt
, ...); /* idem */
37 struct crypt_type_struct
{
40 } crypt_type_tbl
[] = {
41 { LO_CRYPT_NONE
, "no" },
42 { LO_CRYPT_NONE
, "none" },
43 { LO_CRYPT_XOR
, "xor" },
44 { LO_CRYPT_DES
, "DES" },
49 crypt_type (const char *name
) {
53 for (i
= 0; crypt_type_tbl
[i
].id
!= -1; i
++)
54 if (!strcasecmp (name
, crypt_type_tbl
[i
].name
))
55 return crypt_type_tbl
[i
].id
;
65 for (i
= 0; crypt_type_tbl
[i
].id
!= -1; i
++)
66 if (id
== crypt_type_tbl
[i
].id
)
67 return crypt_type_tbl
[i
].name
;
72 show_loop (char *device
) {
73 struct loop_info loopinfo
;
76 if ((fd
= open (device
, O_RDONLY
)) < 0) {
78 fprintf(stderr
, _("loop: can't open device %s: %s\n"),
79 device
, strerror (errsv
));
82 if (ioctl (fd
, LOOP_GET_STATUS
, &loopinfo
) < 0) {
84 fprintf(stderr
, _("loop: can't get info on device %s: %s\n"),
85 device
, strerror (errsv
));
89 printf (_("%s: [%04x]:%ld (%s) offset %d, %s encryption\n"),
90 device
, loopinfo
.lo_device
, loopinfo
.lo_inode
,
91 loopinfo
.lo_name
, loopinfo
.lo_offset
,
92 crypt_name (loopinfo
.lo_encrypt_type
));
100 is_loop_device (const char *device
) {
110 if ((procdev
= fopen(PROC_DEVICES
, "r")) != NULL
) {
111 while (fgets (line
, sizeof(line
), procdev
)) {
112 if ((cp
= strstr (line
, " loop\n")) != NULL
) {
114 loopmajor
=atoi(line
);
121 return (loopmajor
&& stat(device
, &statbuf
) == 0 &&
122 S_ISBLK(statbuf
.st_mode
) &&
123 (statbuf
.st_rdev
>>8) == loopmajor
);
126 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
129 find_unused_loop_device (void) {
130 /* Just creating a device, say in /tmp, is probably a bad idea -
131 people might have problems with backup or so.
132 So, we just try /dev/loop[0-7]. */
134 char *loop_formats
[] = { "/dev/loop%d", "/dev/loop/%d" };
135 int i
, j
, fd
, somedev
= 0, someloop
= 0, loop_known
= 0;
137 struct loop_info loopinfo
;
140 for (j
= 0; j
< SIZE(loop_formats
); j
++) {
141 for(i
= 0; i
< 256; i
++) {
142 sprintf(dev
, loop_formats
[j
], i
);
143 if (stat (dev
, &statbuf
) == 0 && S_ISBLK(statbuf
.st_mode
)) {
145 fd
= open (dev
, O_RDONLY
);
147 if(ioctl (fd
, LOOP_GET_STATUS
, &loopinfo
) == 0)
148 someloop
++; /* in use */
149 else if (errno
== ENXIO
) {
151 return xstrdup(dev
);/* probably free */
155 continue;/* continue trying as long as devices exist */
161 /* Nothing found. Why not? */
162 if ((procdev
= fopen(PROC_DEVICES
, "r")) != NULL
) {
164 while (fgets (line
, sizeof(line
), procdev
))
165 if (strstr (line
, " loop\n")) {
175 error(_("mount: could not find any device /dev/loop#"));
179 "mount: Could not find any loop device.\n"
180 " Maybe /dev/loop# has a wrong major number?"));
181 else if (loop_known
== -1)
183 "mount: Could not find any loop device, and, according to %s,\n"
184 " this kernel does not know about the loop device.\n"
185 " (If so, then recompile or `insmod loop.o'.)"),
189 "mount: Could not find any loop device. Maybe this kernel does not know\n"
190 " about the loop device (then recompile or `insmod loop.o'), or\n"
191 " maybe /dev/loop# has the wrong major number?"));
193 error(_("mount: could not find any free loop device"));
198 set_loop (const char *device
, const char *file
, int offset
,
199 const char *encryption
, int *loopro
) {
200 struct loop_info loopinfo
;
201 int fd
, ffd
, mode
, i
;
204 mode
= (*loopro
? O_RDONLY
: O_RDWR
);
205 if ((ffd
= open (file
, mode
)) < 0) {
206 if (!*loopro
&& errno
== EROFS
)
207 ffd
= open (file
, mode
= O_RDONLY
);
213 if ((fd
= open (device
, mode
)) < 0) {
217 *loopro
= (mode
== O_RDONLY
);
219 memset (&loopinfo
, 0, sizeof (loopinfo
));
220 strncpy (loopinfo
.lo_name
, file
, LO_NAME_SIZE
);
221 loopinfo
.lo_name
[LO_NAME_SIZE
- 1] = 0;
222 if (encryption
&& (loopinfo
.lo_encrypt_type
= crypt_type (encryption
))
224 fprintf (stderr
, _("Unsupported encryption type %s\n"),
228 loopinfo
.lo_offset
= offset
;
232 * Oh-oh, sensitive data coming up. Better lock into memory to prevent
233 * passwd etc being swapped out and left somewhere on disk.
236 if(mlockall(MCL_CURRENT
|MCL_FUTURE
)) {
238 fprintf(stderr
, _("Couldn't lock into memory, exiting.\n"));
243 switch (loopinfo
.lo_encrypt_type
) {
245 loopinfo
.lo_encrypt_key_size
= 0;
248 pass
= getpass (_("Password: "));
249 strncpy (loopinfo
.lo_encrypt_key
, pass
, LO_KEY_SIZE
);
250 loopinfo
.lo_encrypt_key
[LO_KEY_SIZE
- 1] = 0;
251 loopinfo
.lo_encrypt_key_size
= strlen(loopinfo
.lo_encrypt_key
);
254 pass
= getpass (_("Password: "));
255 strncpy (loopinfo
.lo_encrypt_key
, pass
, 8);
256 loopinfo
.lo_encrypt_key
[8] = 0;
257 loopinfo
.lo_encrypt_key_size
= 8;
258 pass
= getpass (_("Init (up to 16 hex digits): "));
259 for (i
= 0; i
< 16 && pass
[i
]; i
++)
260 if (isxdigit (pass
[i
])) {
261 loopinfo
.lo_init
[i
>> 3] |= (pass
[i
] > '9' ?
262 (islower (pass
[i
]) ? toupper (pass
[i
]) :
263 pass
[i
])-'A'+10 : pass
[i
]-'0') << (i
&7) * 4;
265 fprintf (stderr
, _("Non-hex digit '%c'.\n"),
272 _("Don't know how to get key for encryption system %d\n"),
273 loopinfo
.lo_encrypt_type
);
276 if (ioctl (fd
, LOOP_SET_FD
, ffd
) < 0) {
277 perror ("ioctl: LOOP_SET_FD");
280 if (ioctl (fd
, LOOP_SET_STATUS
, &loopinfo
) < 0) {
281 (void) ioctl (fd
, LOOP_CLR_FD
, 0);
282 perror ("ioctl: LOOP_SET_STATUS");
288 printf(_("set_loop(%s,%s,%d): success\n"),
289 device
, file
, offset
);
294 del_loop (const char *device
) {
297 if ((fd
= open (device
, O_RDONLY
)) < 0) {
299 fprintf(stderr
, _("loop: can't delete device %s: %s\n"),
300 device
, strerror (errsv
));
303 if (ioctl (fd
, LOOP_CLR_FD
, 0) < 0) {
304 perror ("ioctl: LOOP_CLR_FD");
309 printf(_("del_loop(%s): success\n"), device
);
313 #else /* no LOOP_SET_FD defined */
317 _("This mount was compiled without loop support. "
318 "Please recompile.\n"));
322 set_loop (const char *device
, const char *file
, int offset
,
323 const char *encryption
, int *loopro
) {
329 del_loop (const char *device
) {
335 find_unused_loop_device (void) {
350 static char *progname
;
354 fprintf(stderr
, _("usage:\n\
355 %s loop_device # give info\n\
356 %s -d loop_device # delete\n\
357 %s [ -e encryption ] [ -o offset ] loop_device file # setup\n"),
358 progname
, progname
, progname
);
363 xstrdup (const char *s
) {
372 fprintf(stderr
, _("not enough memory"));
380 error (const char *fmt
, ...) {
383 va_start (args
, fmt
);
384 vfprintf (stderr
, fmt
, args
);
386 fprintf (stderr
, "\n");
390 main(int argc
, char **argv
) {
391 char *offset
, *encryption
;
396 setlocale(LC_ALL
, "");
397 bindtextdomain(PACKAGE
, LOCALEDIR
);
401 offset
= encryption
= NULL
;
403 while ((c
= getopt(argc
,argv
,"de:o:v")) != EOF
) {
421 if (argc
== 1) usage();
422 if ((delete && (argc
!= optind
+1 || encryption
|| offset
)) ||
423 (!delete && (argc
< optind
+1 || argc
> optind
+2)))
425 if (argc
== optind
+1) {
427 res
= del_loop(argv
[optind
]);
429 res
= show_loop(argv
[optind
]);
431 if (offset
&& sscanf(offset
,"%d",&off
) != 1)
433 res
= set_loop(argv
[optind
],argv
[optind
+1],off
,encryption
,&ro
);
438 #else /* LOOP_SET_FD not defined */
441 main(int argc
, char **argv
) {
443 _("No loop support was available at compile time. "
444 "Please recompile.\n"));