]>
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@pld.ORG.PL>
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>
34 extern char *xstrdup (const char *s
); /* not: #include "sundries.h" */
35 extern void error (const char *fmt
, ...); /* idem */
38 struct crypt_type_struct
{
41 } crypt_type_tbl
[] = {
42 { LO_CRYPT_NONE
, "no" },
43 { LO_CRYPT_NONE
, "none" },
44 { LO_CRYPT_XOR
, "xor" },
45 { LO_CRYPT_DES
, "DES" },
50 crypt_type (const char *name
) {
54 for (i
= 0; crypt_type_tbl
[i
].id
!= -1; i
++)
55 if (!strcasecmp (name
, crypt_type_tbl
[i
].name
))
56 return crypt_type_tbl
[i
].id
;
66 for (i
= 0; crypt_type_tbl
[i
].id
!= -1; i
++)
67 if (id
== crypt_type_tbl
[i
].id
)
68 return crypt_type_tbl
[i
].name
;
73 show_loop (char *device
) {
74 struct loop_info loopinfo
;
77 if ((fd
= open (device
, O_RDONLY
)) < 0) {
79 fprintf(stderr
, _("loop: can't open device %s: %s\n"),
80 device
, strerror (errsv
));
83 if (ioctl (fd
, LOOP_GET_STATUS
, &loopinfo
) < 0) {
85 fprintf(stderr
, _("loop: can't get info on device %s: %s\n"),
86 device
, strerror (errsv
));
90 printf (_("%s: [%04x]:%ld (%s) offset %d, %s encryption\n"),
91 device
, loopinfo
.lo_device
, loopinfo
.lo_inode
,
92 loopinfo
.lo_name
, loopinfo
.lo_offset
,
93 crypt_name (loopinfo
.lo_encrypt_type
));
101 is_loop_device (const char *device
) {
111 if ((procdev
= fopen(PROC_DEVICES
, "r")) != NULL
) {
112 while (fgets (line
, sizeof(line
), procdev
)) {
113 if ((cp
= strstr (line
, " loop\n")) != NULL
) {
115 loopmajor
=atoi(line
);
122 return (loopmajor
&& stat(device
, &statbuf
) == 0 &&
123 S_ISBLK(statbuf
.st_mode
) &&
124 (statbuf
.st_rdev
>>8) == loopmajor
);
127 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
130 find_unused_loop_device (void) {
131 /* Just creating a device, say in /tmp, is probably a bad idea -
132 people might have problems with backup or so.
133 So, we just try /dev/loop[0-7]. */
135 char *loop_formats
[] = { "/dev/loop%d", "/dev/loop/%d" };
136 int i
, j
, fd
, somedev
= 0, someloop
= 0, loop_known
= 0;
138 struct loop_info loopinfo
;
141 for (j
= 0; j
< SIZE(loop_formats
); j
++) {
142 for(i
= 0; i
< 256; i
++) {
143 sprintf(dev
, loop_formats
[j
], i
);
144 if (stat (dev
, &statbuf
) == 0 && S_ISBLK(statbuf
.st_mode
)) {
146 fd
= open (dev
, O_RDONLY
);
148 if(ioctl (fd
, LOOP_GET_STATUS
, &loopinfo
) == 0)
149 someloop
++; /* in use */
150 else if (errno
== ENXIO
) {
152 return xstrdup(dev
);/* probably free */
156 continue;/* continue trying as long as devices exist */
162 /* Nothing found. Why not? */
163 if ((procdev
= fopen(PROC_DEVICES
, "r")) != NULL
) {
165 while (fgets (line
, sizeof(line
), procdev
))
166 if (strstr (line
, " loop\n")) {
176 error(_("mount: could not find any device /dev/loop#"));
180 "mount: Could not find any loop device.\n"
181 " Maybe /dev/loop# has a wrong major number?"));
182 else if (loop_known
== -1)
184 "mount: Could not find any loop device, and, according to %s,\n"
185 " this kernel does not know about the loop device.\n"
186 " (If so, then recompile or `insmod loop.o'.)"),
190 "mount: Could not find any loop device. Maybe this kernel does not know\n"
191 " about the loop device (then recompile or `insmod loop.o'), or\n"
192 " maybe /dev/loop# has the wrong major number?"));
194 error(_("mount: could not find any free loop device"));
199 set_loop (const char *device
, const char *file
, int offset
,
200 const char *encryption
, int *loopro
) {
201 struct loop_info loopinfo
;
202 int fd
, ffd
, mode
, i
;
205 mode
= (*loopro
? O_RDONLY
: O_RDWR
);
206 if ((ffd
= open (file
, mode
)) < 0) {
207 if (!*loopro
&& errno
== EROFS
)
208 ffd
= open (file
, mode
= O_RDONLY
);
214 if ((fd
= open (device
, mode
)) < 0) {
218 *loopro
= (mode
== O_RDONLY
);
220 memset (&loopinfo
, 0, sizeof (loopinfo
));
221 xstrncpy (loopinfo
.lo_name
, file
, LO_NAME_SIZE
);
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 xstrncpy (loopinfo
.lo_encrypt_key
, pass
, LO_KEY_SIZE
);
250 loopinfo
.lo_encrypt_key_size
= strlen(loopinfo
.lo_encrypt_key
);
253 pass
= getpass (_("Password: "));
254 strncpy (loopinfo
.lo_encrypt_key
, pass
, 8);
255 loopinfo
.lo_encrypt_key
[8] = 0;
256 loopinfo
.lo_encrypt_key_size
= 8;
257 pass
= getpass (_("Init (up to 16 hex digits): "));
258 for (i
= 0; i
< 16 && pass
[i
]; i
++)
259 if (isxdigit (pass
[i
])) {
260 loopinfo
.lo_init
[i
>> 3] |= (pass
[i
] > '9' ?
261 (islower (pass
[i
]) ? toupper (pass
[i
]) :
262 pass
[i
])-'A'+10 : pass
[i
]-'0') << (i
&7) * 4;
264 fprintf (stderr
, _("Non-hex digit '%c'.\n"),
271 _("Don't know how to get key for encryption system %d\n"),
272 loopinfo
.lo_encrypt_type
);
275 if (ioctl (fd
, LOOP_SET_FD
, ffd
) < 0) {
276 perror ("ioctl: LOOP_SET_FD");
279 if (ioctl (fd
, LOOP_SET_STATUS
, &loopinfo
) < 0) {
280 (void) ioctl (fd
, LOOP_CLR_FD
, 0);
281 perror ("ioctl: LOOP_SET_STATUS");
287 printf(_("set_loop(%s,%s,%d): success\n"),
288 device
, file
, offset
);
293 del_loop (const char *device
) {
296 if ((fd
= open (device
, O_RDONLY
)) < 0) {
298 fprintf(stderr
, _("loop: can't delete device %s: %s\n"),
299 device
, strerror (errsv
));
302 if (ioctl (fd
, LOOP_CLR_FD
, 0) < 0) {
303 perror ("ioctl: LOOP_CLR_FD");
308 printf(_("del_loop(%s): success\n"), device
);
312 #else /* no LOOP_SET_FD defined */
316 _("This mount was compiled without loop support. "
317 "Please recompile.\n"));
321 set_loop (const char *device
, const char *file
, int offset
,
322 const char *encryption
, int *loopro
) {
328 del_loop (const char *device
) {
334 find_unused_loop_device (void) {
349 static char *progname
;
353 fprintf(stderr
, _("usage:\n\
354 %s loop_device # give info\n\
355 %s -d loop_device # delete\n\
356 %s [ -e encryption ] [ -o offset ] loop_device file # setup\n"),
357 progname
, progname
, progname
);
362 xstrdup (const char *s
) {
371 fprintf(stderr
, _("not enough memory"));
379 error (const char *fmt
, ...) {
382 va_start (args
, fmt
);
383 vfprintf (stderr
, fmt
, args
);
385 fprintf (stderr
, "\n");
389 main(int argc
, char **argv
) {
390 char *offset
, *encryption
;
395 setlocale(LC_ALL
, "");
396 bindtextdomain(PACKAGE
, LOCALEDIR
);
400 offset
= encryption
= NULL
;
402 while ((c
= getopt(argc
,argv
,"de:o:v")) != -1) {
420 if (argc
== 1) usage();
421 if ((delete && (argc
!= optind
+1 || encryption
|| offset
)) ||
422 (!delete && (argc
< optind
+1 || argc
> optind
+2)))
424 if (argc
== optind
+1) {
426 res
= del_loop(argv
[optind
]);
428 res
= show_loop(argv
[optind
]);
430 if (offset
&& sscanf(offset
,"%d",&off
) != 1)
432 res
= set_loop(argv
[optind
],argv
[optind
+1],off
,encryption
,&ro
);
437 #else /* LOOP_SET_FD not defined */
440 main(int argc
, char **argv
) {
442 _("No loop support was available at compile time. "
443 "Please recompile.\n"));