#include "nls.h"
#include "strutils.h"
#include "loopdev.h"
-#include "xgetpass.h"
+#include "closestream.h"
+#include "optutils.h"
enum {
A_CREATE = 1, /* setup a new device */
int fd = loopcxt_get_fd(lc);
if (fd < 0)
- warn(_("%s: open failed"), loopcxt_get_device(lc));
+ warn(_("cannot open %s"), loopcxt_get_device(lc));
else if (ioctl(fd, LOOP_SET_CAPACITY) != 0)
warnx(_("%s: set capacity failed"), loopcxt_get_device(lc));
else
" -j, --associated <file> list all devices associated with <file>\n"), out);
fputs(USAGE_SEPARATOR, out);
- fputs(_(" -e, --encryption <type> enable encryption with specified <name/num>\n"
- " -o, --offset <num> start at offset <num> into file\n"
+ fputs(_(" -o, --offset <num> start at offset <num> into file\n"
" --sizelimit <num> device limited to <num> bytes of the file\n"
- " -p, --pass-fd <num> read passphrase from file descriptor <num>\n"
" -P, --partscan create partitioned loop device\n"
" -r, --read-only setup read-only loop device\n"
" --show print device name after setup (with -f)\n"
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
+static void warn_size(const char *filename, uint64_t size)
+{
+ struct stat st;
+
+ if (!size) {
+ if (stat(filename, &st))
+ return;
+ size = st.st_size;
+ }
+
+ if (size < 512)
+ warnx(_("%s: warning: file smaller than 512 bytes, the loop device "
+ "maybe be useless or invisible for system tools."),
+ filename);
+ else if (size % 512)
+ warnx(_("%s: warning: file does not fit into a 512-byte sector "
+ "the end of the file will be ignored."),
+ filename);
+}
+
int main(int argc, char **argv)
{
struct loopdev_cxt lc;
- int act = 0, flags = 0, passfd = -1, c;
- char *file = NULL, *encryption = NULL;
+ int act = 0, flags = 0, c;
+ char *file = NULL;
uint64_t offset = 0, sizelimit = 0;
int res = 0, showdev = 0, lo_flags = 0;
{ NULL, 0, 0, 0 }
};
+ static const ul_excl_t excl[] = { /* rows and cols in ASCII order */
+ { 'D','a','c','d','f','j' },
+ { 0 }
+ };
+ int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
+
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
+ atexit(close_stdout);
+
+ if (loopcxt_init(&lc, 0))
+ err(EXIT_FAILURE, _("failed to initialize loopcxt"));
- loopcxt_init(&lc, 0);
loopcxt_enable_debug(&lc, getenv("LOOPDEV_DEBUG") ? TRUE : FALSE);
while ((c = getopt_long(argc, argv, "ac:d:De:E:fhj:o:p:PrvV",
longopts, NULL)) != -1) {
- if (act && strchr("acdDfj", c))
- errx(EXIT_FAILURE,
- _("the options %s are mutually exclusive"),
- "--{all,associated,set-capacity,detach,detach-all,find}");
+ err_exclusive_options(c, longopts, excl, excl_st);
switch (c) {
case 'a':
break;
case 'c':
act = A_SET_CAPACITY;
- loopcxt_set_device(&lc, optarg);
+ if (loopcxt_set_device(&lc, optarg))
+ err(EXIT_FAILURE, _("%s: failed to use device"),
+ optarg);
break;
case 'r':
lo_flags |= LO_FLAGS_READ_ONLY;
break;
case 'd':
act = A_DELETE;
- loopcxt_set_device(&lc, optarg);
+ if (loopcxt_set_device(&lc, optarg))
+ err(EXIT_FAILURE, _("%s: failed to use device"),
+ optarg);
break;
case 'D':
act = A_DELETE_ALL;
break;
case 'E':
case 'e':
- encryption = optarg;
+ errx(EXIT_FAILURE, _("encryption not supported, use cryptsetup(8) instead"));
break;
case 'f':
act = A_FIND_FREE;
flags |= LOOPDEV_FL_OFFSET;
break;
case 'p':
- passfd = strtol_or_err(optarg,
- _("invalid passphrase file descriptor"));
+ warn(_("--pass-fd is no longer supported"));
break;
case 'P':
lo_flags |= LO_FLAGS_PARTSCAN;
* losetup <device>
*/
act = A_SHOW_ONE;
- loopcxt_set_device(&lc, argv[optind++]);
+ if (loopcxt_set_device(&lc, argv[optind]))
+ err(EXIT_FAILURE, _("%s: failed to use device"),
+ argv[optind]);
+ optind++;
}
if (!act) {
/*
if (optind >= argc)
errx(EXIT_FAILURE, _("no loop device specified"));
- loopcxt_set_device(&lc, argv[optind++]);
+ if (loopcxt_set_device(&lc, argv[optind]))
+ err(EXIT_FAILURE, _("%s: failed to use device"),
+ argv[optind]);
+ optind++;
if (optind >= argc)
errx(EXIT_FAILURE, _("no file specified"));
}
if (act != A_CREATE &&
- (encryption || sizelimit || passfd != -1 || lo_flags || showdev))
+ (sizelimit || lo_flags || showdev))
errx(EXIT_FAILURE,
_("the options %s are allowed to loop device setup only"),
- "--{encryption,sizelimit,pass-fd,read-only,show}");
+ "--{sizelimit,read-only,show}");
if ((flags & LOOPDEV_FL_OFFSET) &&
act != A_CREATE && (act != A_SHOW || !file))
switch (act) {
case A_CREATE:
{
- char *pass = NULL;
int hasdev = loopcxt_has_device(&lc);
- if (encryption) {
-#ifdef MCL_FUTURE
- if(mlockall(MCL_CURRENT | MCL_FUTURE))
- err(EXIT_FAILURE, _("couldn't lock into memory"));
-#endif
- pass = xgetpass(passfd, _("Password: "));
- }
do {
/* Note that loopcxt_{find_unused,set_device}() resets
* loopcxt struct.
warnx(_("not found unused device"));
break;
}
- if (encryption && pass)
- loopcxt_set_encryption(&lc, encryption, pass);
if (flags & LOOPDEV_FL_OFFSET)
loopcxt_set_offset(&lc, offset);
if (flags & LOOPDEV_FL_SIZELIMIT)
if (res == 0)
break; /* success */
if (errno != EBUSY) {
- warn(_("failed to setup loop device"));
+ warn(_("%s: failed to setup loop device"),
+ hasdev && loopcxt_get_fd(&lc) < 0 ?
+ loopcxt_get_device(&lc) : file);
break;
}
} while (hasdev == 0);
- free(pass);
-
- if (showdev && res == 0)
- printf("%s\n", loopcxt_get_device(&lc));
+ if (res == 0) {
+ if (showdev)
+ printf("%s\n", loopcxt_get_device(&lc));
+ warn_size(file, sizelimit);
+ }
break;
}
case A_DELETE:
res = delete_loop(&lc);
while (optind < argc) {
- loopcxt_set_device(&lc, argv[optind++]);
+ if (loopcxt_set_device(&lc, argv[optind]))
+ warn(_("%s: failed to use device"),
+ argv[optind]);
+ optind++;
res += delete_loop(&lc);
}
break;