diff options
| author | Manuel Bentele | 2020-10-23 15:18:01 +0200 |
|---|---|---|
| committer | Manuel Bentele | 2020-10-23 15:18:01 +0200 |
| commit | dbb41ce2b7f309d394054a6bd1e33afd578798a5 (patch) | |
| tree | 6a31092063d9f2fb5ac5720ec6759040e793c3d5 /utils/sys-utils | |
| parent | Set Linux kernel version to unknown if it is not detectable (diff) | |
| download | xloop-dbb41ce2b7f309d394054a6bd1e33afd578798a5.tar.gz xloop-dbb41ce2b7f309d394054a6bd1e33afd578798a5.tar.xz xloop-dbb41ce2b7f309d394054a6bd1e33afd578798a5.zip | |
Move the source code of all xloop components to the common 'src' directory
Diffstat (limited to 'utils/sys-utils')
| -rw-r--r-- | utils/sys-utils/CMakeLists.txt | 19 | ||||
| -rw-r--r-- | utils/sys-utils/xlosetup.8 | 215 | ||||
| -rw-r--r-- | utils/sys-utils/xlosetup.c | 931 |
3 files changed, 0 insertions, 1165 deletions
diff --git a/utils/sys-utils/CMakeLists.txt b/utils/sys-utils/CMakeLists.txt deleted file mode 100644 index 01295d9..0000000 --- a/utils/sys-utils/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -cmake_minimum_required(VERSION 3.10) - -# set the project name -project(xloop-utils-sys-utils) - -# add xlosetup executable -add_executable(xlosetup ${CMAKE_CURRENT_SOURCE_DIR}/xlosetup.c) -target_link_libraries(xlosetup LINK_PUBLIC libcommon libsmartcols) -target_include_directories(xlosetup PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../lib ${CMAKE_CURRENT_SOURCE_DIR}/../libsmartcols) -install(TARGETS xlosetup DESTINATION bin - COMPONENT main) - -# install xlosetup man page -# NOTE: installation is done via a directory install with file matching pattern to support CPackRPM's automatic compression of man pages -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ - DESTINATION share/man/man8 - COMPONENT main - USE_SOURCE_PERMISSIONS - FILES_MATCHING PATTERN *.8*) diff --git a/utils/sys-utils/xlosetup.8 b/utils/sys-utils/xlosetup.8 deleted file mode 100644 index 4e063e6..0000000 --- a/utils/sys-utils/xlosetup.8 +++ /dev/null @@ -1,215 +0,0 @@ -.TH XLOSETUP 8 "September 2020" "util-linux" "System Administration" -.SH NAME -xlosetup \- set up and control xloop devices -.SH SYNOPSIS -.ad l -Get info: -.sp -.in +5 -.B xlosetup -[\fIxloopdev\fP] -.sp -.B xlosetup \-l -.RB [ \-a ] -.sp -.B xlosetup \-j -.I file -.RB [ \-o -.IR offset ] -.sp -.in -5 -Detach a xloop device: -.sp -.in +5 -.B "xlosetup \-d" -.IR xloopdev ... -.sp -.in -5 -Detach all associated xloop devices: -.sp -.in +5 -.B "xlosetup \-D" -.sp -.in -5 -Set up a xloop device: -.sp -.in +5 -.B xlosetup -.RB [ \-o -.IR offset ] -.RB [ \-\-sizelimit -.IR size ] -.RB [ \-\-sector\-size -.IR size ] -.in +8 -.RB [ \-Pr ] -.RB [ \-\-show ] " \-f" | \fIxloopdev\fP -.I file -.sp -.in -13 -Resize a xloop device: -.sp -.in +5 -.B "xlosetup \-c" -.I xloopdev -.in -5 -.ad b -.SH DESCRIPTION -.B xlosetup -is used to associate xloop devices with regular files or block devices, -to detach xloop devices, and to query the status of a xloop device. If only the -\fIxloopdev\fP argument is given, the status of the corresponding xloop -device is shown. If no option is given, all xloop devices are shown. -.sp -Note that the old output format (i.e., \fBxlosetup \-a\fR) with comma-delimited -strings is deprecated in favour of the \fB\-\-list\fR output format. -.sp -It's possible to create more independent xloop devices for the same backing -file. -.B This setup may be dangerous, can cause data loss, corruption and overwrites. -Use \fB\-\-nooverlap\fR with \fB\-\-find\fR during setup to avoid this problem. - -.SH OPTIONS -The \fIsize\fR and \fIoffset\fR -arguments may be followed by the multiplicative suffixes KiB (=1024), -MiB (=1024*1024), and so on for GiB, TiB, PiB, EiB, ZiB and YiB (the "iB" is -optional, e.g., "K" has the same meaning as "KiB") or the suffixes -KB (=1000), MB (=1000*1000), and so on for GB, TB, PB, EB, ZB and YB. - -.TP -.BR \-a , " \-\-all" -Show the status of all xloop devices. Note that not all information is accessible -for non-root users. See also \fB\-\-list\fR. The old output format (as printed -without \fB\-\-list)\fR is deprecated. -.TP -.BR \-d , " \-\-detach " \fIxloopdev\fR... -Detach the file or device associated with the specified xloop device(s). Note -that since Linux v3.7 kernel uses "lazy device destruction". The detach -operation does not return EBUSY error anymore if device is actively used by -system, but it is marked by autoclear flag and destroyed later. -.TP -.BR \-D , " \-\-detach\-all" -Detach all associated xloop devices. -.TP -.BR \-f , " \-\-find " "\fR[\fIfile\fR]" -Find the first unused xloop device. If a \fIfile\fR argument is present, use -the found device as xloop device. Otherwise, just print its name. -.IP "\fB\-\-show\fP" -Display the name of the assigned xloop device if the \fB\-f\fP option and a -\fIfile\fP argument are present. -.TP -.BR \-L , " \-\-nooverlap" -Check for conflicts between xloop devices to avoid situation when the same -backing file is shared between more xloop devices. If the file is already used -by another device then re-use the device rather than a new one. The option -makes sense only with \fB\-\-find\fP. -.TP -.BR \-j , " \-\-associated " \fIfile\fR " \fR[\fB\-o \fIoffset\fR]" -Show the status of all xloop devices associated with the given \fIfile\fR. -.TP -.BR \-o , " \-\-offset " \fIoffset -The data start is moved \fIoffset\fP bytes into the specified file or device. The \fIoffset\fP -may be followed by the multiplicative suffixes; see above. -.IP "\fB\-\-sizelimit \fIsize\fP" -The data end is set to no more than \fIsize\fP bytes after the data start. The \fIsize\fP -may be followed by the multiplicative suffixes; see above. -.TP -.BR \-b , " \-\-sector-size " \fIsize -Set the logical sector size of the xloop device in bytes (since Linux 4.14). The -option may be used when create a new xloop device as well as stand-alone command -to modify sector size of the already existing xloop device. -.TP -.BR \-c , " \-\-set\-capacity " \fIxloopdev -Force the xloop driver to reread the size of the file associated with the -specified xloop device. -.TP -.BR \-P , " \-\-partscan" -Force the kernel to scan the partition table on a newly created xloop device. Note that the -partition table parsing depends on sector sizes. The default is sector size is 512 bytes, -otherwise you need to use the option \fB\-\-sector\-size\fR together with \fB\-\-partscan\fR. -.TP -.BR \-r , " \-\-read\-only" -Set up a read-only xloop device. -.TP -.BR \-\-direct\-io [ =on | off ] -Enable or disable direct I/O for the backing file. The optional argument -can be either \fBon\fR or \fBoff\fR. If the argument is omitted, it defaults -to \fBoff\fR. -.TP -.BR \-t , " \-\-type \fIformat\fR" -Set the file format type of the xloop device. If no file format type is specified, -the RAW file format is used by default. Valid file formats are: \fBRAW\fR, -\fBQCOW\fR, \fBVDI\fR, \fBVMDK\fR. -.TP -.BR \-v , " \-\-verbose" -Verbose mode. -.TP -.BR \-l , " \-\-list" -If a xloop device or the \fB\-a\fR option is specified, print the default columns -for either the specified xloop device or all xloop devices; the default is to -print info about all devices. See also \fB\-\-output\fP, \fB\-\-noheadings\fP, -\fB\-\-raw\fP, and \fB\-\-json\fP. -.TP -.BR \-O , " \-\-output " \fIcolumn\fR[,\fIcolumn\fR]... -Specify the columns that are to be printed for the \fB\-\-list\fP output. -Use \fB\-\-help\fR to get a list of all supported columns. -.TP -.B \-\-output\-all -Output all available columns. -.TP -.BR \-n , " \-\-noheadings" -Don't print headings for \fB\-\-list\fP output format. -.IP "\fB\-\-raw\fP" -Use the raw \fB\-\-list\fP output format. -.TP -.BR \-J , " \-\-json" -Use JSON format for \fB\-\-list\fP output. -.TP -.BR \-V , " \-\-version" -Display version information and exit. -.TP -.BR \-h , " \-\-help" -Display help text and exit. - -.SH ENCRYPTION -.B Cryptoloop is no longer supported in favor of dm-crypt. -.B For more details see cryptsetup(8). - -.SH EXIT STATUS -.B xlosetup -returns 0 on success, nonzero on failure. When -.B xlosetup -displays the status of a xloop device, it returns 1 if the device -is not configured and 2 if an error occurred which prevented -determining the status of the device. - -.SH ENVIRONMENT -.IP XLOOPDEV_DEBUG=all -enables debug output. - -.SH FILES -.TP -.I /dev/xloop[0..N] -xloop block devices -.TP -.I /dev/xloop-control -xloop control device -.SH EXAMPLE -The following commands can be used as an example of using the xloop device. -.nf -.IP -# dd if=/dev/zero of=~/file.img bs=1024k count=10 -# xlosetup \-\-find \-\-show ~/file.img -/dev/xloop0 -# mkfs \-t ext2 /dev/xloop0 -# mount /dev/xloop0 /mnt - ... -# umount /dev/xloop0 -# xlosetup \-\-detach /dev/xloop0 -.fi -.SH AUTHORS -Karel Zak <kzak@redhat.com>, based on the original version from -Theodore Ts'o <tytso@athena.mit.edu> -.SH AVAILABILITY -The xlosetup command is part of the util-linux package and is available from -https://www.kernel.org/pub/linux/utils/util-linux/. diff --git a/utils/sys-utils/xlosetup.c b/utils/sys-utils/xlosetup.c deleted file mode 100644 index 60fa0ba..0000000 --- a/utils/sys-utils/xlosetup.c +++ /dev/null @@ -1,931 +0,0 @@ -/* - * Copyright (C) 2011 Karel Zak <kzak@redhat.com> - * Originally from Ted's losetup.c - * - * xlosetup.c - setup and control xloop devices - */ -#include <assert.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <inttypes.h> -#include <getopt.h> - -#include <libsmartcols.h> - -#include "c.h" -#include "nls.h" -#include "strutils.h" -#include "loopdev.h" -#include "closestream.h" -#include "optutils.h" -#include "xalloc.h" -#include "canonicalize.h" -#include "pathnames.h" - -enum { - A_CREATE = 1, /* setup a new device */ - A_DELETE, /* delete given device(s) */ - A_DELETE_ALL, /* delete all devices */ - A_SHOW, /* list devices */ - A_SHOW_ONE, /* print info about one device */ - A_FIND_FREE, /* find first unused */ - A_SET_CAPACITY, /* set device capacity */ - A_SET_DIRECT_IO, /* set accessing backing file by direct io */ - A_SET_BLOCKSIZE, /* set logical block size of the xloop device */ -}; - -enum { - COL_NAME = 0, - COL_AUTOCLR, - COL_BACK_FILE, - COL_FILE_FMT_TYPE, - COL_BACK_INO, - COL_BACK_MAJMIN, - COL_MAJMIN, - COL_OFFSET, - COL_PARTSCAN, - COL_RO, - COL_SIZELIMIT, - COL_DIO, - COL_LOGSEC, -}; - -/* basic output flags */ -static int no_headings; -static int raw; -static int json; - -struct colinfo { - const char *name; - double whint; - int flags; - const char *help; - - int json_type; /* default is string */ -}; - -static struct colinfo infos[] = { - [COL_AUTOCLR] = { "AUTOCLEAR", 1, SCOLS_FL_RIGHT, N_("autoclear flag set"), SCOLS_JSON_BOOLEAN}, - [COL_BACK_FILE] = { "BACK-FILE", 0.3, 0, N_("device backing file")}, - [COL_FILE_FMT_TYPE] = { "FILE-FORMAT", 1, 0, N_("backing file format")}, - [COL_BACK_INO] = { "BACK-INO", 4, SCOLS_FL_RIGHT, N_("backing file inode number"), SCOLS_JSON_NUMBER}, - [COL_BACK_MAJMIN] = { "BACK-MAJ:MIN", 6, 0, N_("backing file major:minor device number")}, - [COL_NAME] = { "NAME", 0.25, 0, N_("xloop device name")}, - [COL_OFFSET] = { "OFFSET", 5, SCOLS_FL_RIGHT, N_("offset from the beginning"), SCOLS_JSON_NUMBER}, - [COL_PARTSCAN] = { "PARTSCAN", 1, SCOLS_FL_RIGHT, N_("partscan flag set"), SCOLS_JSON_BOOLEAN}, - [COL_RO] = { "RO", 1, SCOLS_FL_RIGHT, N_("read-only device"), SCOLS_JSON_BOOLEAN}, - [COL_SIZELIMIT] = { "SIZELIMIT", 5, SCOLS_FL_RIGHT, N_("size limit of the file in bytes"), SCOLS_JSON_NUMBER}, - [COL_MAJMIN] = { "MAJ:MIN", 3, 0, N_("xloop device major:minor number")}, - [COL_DIO] = { "DIO", 1, SCOLS_FL_RIGHT, N_("access backing file with direct-io"), SCOLS_JSON_BOOLEAN}, - [COL_LOGSEC] = { "LOG-SEC", 4, SCOLS_FL_RIGHT, N_("logical sector size in bytes"), SCOLS_JSON_NUMBER}, -}; - -static int columns[ARRAY_SIZE(infos) * 2] = {-1}; -static size_t ncolumns; - -static int get_column_id(int num) -{ - assert(num >= 0); - assert((size_t) num < ncolumns); - assert(columns[num] < (int) ARRAY_SIZE(infos)); - return columns[num]; -} - -static struct colinfo *get_column_info(int num) -{ - return &infos[ get_column_id(num) ]; -} - -static int column_name_to_id(const char *name, size_t namesz) -{ - size_t i; - - for (i = 0; i < ARRAY_SIZE(infos); i++) { - const char *cn = infos[i].name; - - if (!strncasecmp(name, cn, namesz) && !*(cn + namesz)) - return i; - } - warnx(_("unknown column: %s"), name); - return -1; -} - -static int printf_loopdev(struct loopdev_cxt *lc) -{ - uint64_t x; - dev_t dev = 0; - ino_t ino = 0; - char *fname; - uint32_t type; - char *file_fmt_str; - - fname = loopcxt_get_backing_file(lc); - if (!fname) - return -EINVAL; - - file_fmt_str = loopcxt_get_file_fmt_type_string(lc); - if (!file_fmt_str) - return -EINVAL; - - if (loopcxt_get_backing_devno(lc, &dev) == 0) - loopcxt_get_backing_inode(lc, &ino); - - if (!dev && !ino) { - /* - * Probably non-root user (no permissions to - * call LOOP_GET_STATUS ioctls). - */ - printf("%s: []: (%s)", - loopcxt_get_device(lc), fname); - - if (loopcxt_get_offset(lc, &x) == 0 && x) - printf(_(", offset %ju"), x); - - if (loopcxt_get_sizelimit(lc, &x) == 0 && x) - printf(_(", sizelimit %ju"), x); - - printf(_(", file-format %s"), file_fmt_str); - - goto done; - } - - printf("%s: [%04d]:%" PRIu64 " (%s)", - loopcxt_get_device(lc), (int) dev, ino, fname); - - if (loopcxt_get_offset(lc, &x) == 0 && x) - printf(_(", offset %ju"), x); - - if (loopcxt_get_sizelimit(lc, &x) == 0 && x) - printf(_(", sizelimit %ju"), x); - - if (loopcxt_get_encrypt_type(lc, &type) == 0) { - const char *e = loopcxt_get_crypt_name(lc); - - if ((!e || !*e) && type == 1) - e = "XOR"; - if (e && *e) - printf(_(", encryption %s (type %u)"), e, type); - } - - printf(_(", file-format %s"), file_fmt_str); - -done: - free(fname); - printf("\n"); - return 0; -} - -static int show_all_loops(struct loopdev_cxt *lc, const char *file, - uint64_t offset, int flags) -{ - struct stat sbuf, *st = &sbuf; - char *cn_file = NULL; - - if (loopcxt_init_iterator(lc, LOOPITER_FL_USED)) - return -1; - - if (!file || stat(file, st)) - st = NULL; - - while (loopcxt_next(lc) == 0) { - if (file) { - int used; - const char *bf = cn_file ? cn_file : file; - - used = loopcxt_is_used(lc, st, bf, offset, 0, flags); - if (!used && !cn_file) { - bf = cn_file = canonicalize_path(file); - used = loopcxt_is_used(lc, st, bf, offset, 0, flags); - } - if (!used) - continue; - } - printf_loopdev(lc); - } - loopcxt_deinit_iterator(lc); - free(cn_file); - return 0; -} - -static int delete_loop(struct loopdev_cxt *lc) -{ - if (loopcxt_delete_device(lc)) - warn(_("%s: detach failed"), loopcxt_get_device(lc)); - else - return 0; - - return -1; -} - -static int delete_all_loops(struct loopdev_cxt *lc) -{ - int res = 0; - - if (loopcxt_init_iterator(lc, LOOPITER_FL_USED)) - return -1; - - while (loopcxt_next(lc) == 0) - res += delete_loop(lc); - - loopcxt_deinit_iterator(lc); - return res; -} - -static int set_scols_data(struct loopdev_cxt *lc, struct libscols_line *ln) -{ - size_t i; - - for (i = 0; i < ncolumns; i++) { - const char *p = NULL; /* external data */ - char *np = NULL; /* allocated here */ - uint64_t x = 0; - int rc = 0; - - switch(get_column_id(i)) { - case COL_NAME: - p = loopcxt_get_device(lc); - break; - case COL_BACK_FILE: - p = loopcxt_get_backing_file(lc); - break; - case COL_FILE_FMT_TYPE: - p = loopcxt_get_file_fmt_type_string(lc); - break; - case COL_OFFSET: - if (loopcxt_get_offset(lc, &x) == 0) - xasprintf(&np, "%jd", x); - break; - case COL_SIZELIMIT: - if (loopcxt_get_sizelimit(lc, &x) == 0) - xasprintf(&np, "%jd", x); - break; - case COL_BACK_MAJMIN: - { - dev_t dev = 0; - if (loopcxt_get_backing_devno(lc, &dev) == 0 && dev) - xasprintf(&np, "%8u:%-3u", major(dev), minor(dev)); - break; - } - case COL_MAJMIN: - { - struct stat st; - - if (loopcxt_get_device(lc) - && stat(loopcxt_get_device(lc), &st) == 0 - && S_ISBLK(st.st_mode) - && major(st.st_rdev) == LOOPDEV_MAJOR) - xasprintf(&np, "%3u:%-3u", major(st.st_rdev), - minor(st.st_rdev)); - break; - } - case COL_BACK_INO: - { - ino_t ino = 0; - if (loopcxt_get_backing_inode(lc, &ino) == 0 && ino) - xasprintf(&np, "%ju", ino); - break; - } - case COL_AUTOCLR: - p = loopcxt_is_autoclear(lc) ? "1" : "0"; - break; - case COL_RO: - p = loopcxt_is_readonly(lc) ? "1" : "0"; - break; - case COL_DIO: - p = loopcxt_is_dio(lc) ? "1" : "0"; - break; - case COL_PARTSCAN: - p = loopcxt_is_partscan(lc) ? "1" : "0"; - break; - case COL_LOGSEC: - if (loopcxt_get_blocksize(lc, &x) == 0) - xasprintf(&np, "%jd", x); - break; - default: - return -EINVAL; - } - - - if (p) - rc = scols_line_set_data(ln, i, p); /* calls strdup() */ - else if (np) - rc = scols_line_refer_data(ln, i, np); /* only refers */ - - if (rc) - err(EXIT_FAILURE, _("failed to add output data")); - } - - return 0; -} - -static int show_table(struct loopdev_cxt *lc, - const char *file, - uint64_t offset, - int flags) -{ - struct stat sbuf, *st = &sbuf; - struct libscols_table *tb; - struct libscols_line *ln; - int rc = 0; - size_t i; - - scols_init_debug(0); - - if (!(tb = scols_new_table())) - err(EXIT_FAILURE, _("failed to allocate output table")); - scols_table_enable_raw(tb, raw); - scols_table_enable_json(tb, json); - scols_table_enable_noheadings(tb, no_headings); - - if (json) - scols_table_set_name(tb, "xloopdevices"); - - for (i = 0; i < ncolumns; i++) { - struct colinfo *ci = get_column_info(i); - struct libscols_column *cl; - - cl = scols_table_new_column(tb, ci->name, ci->whint, ci->flags); - if (!cl) - err(EXIT_FAILURE, _("failed to allocate output column")); - if (json) - scols_column_set_json_type(cl, ci->json_type); - } - - /* only one xloopdev requested (already assigned to loopdev_cxt) */ - if (loopcxt_get_device(lc)) { - ln = scols_table_new_line(tb, NULL); - if (!ln) - err(EXIT_FAILURE, _("failed to allocate output line")); - rc = set_scols_data(lc, ln); - - /* list all xloopdevs */ - } else { - char *cn_file = NULL; - - rc = loopcxt_init_iterator(lc, LOOPITER_FL_USED); - if (rc) - goto done; - if (!file || stat(file, st)) - st = NULL; - - while (loopcxt_next(lc) == 0) { - if (file) { - int used; - const char *bf = cn_file ? cn_file : file; - - used = loopcxt_is_used(lc, st, bf, offset, 0, flags); - if (!used && !cn_file) { - bf = cn_file = canonicalize_path(file); - used = loopcxt_is_used(lc, st, bf, offset, 0, flags); - } - if (!used) - continue; - } - - ln = scols_table_new_line(tb, NULL); - if (!ln) - err(EXIT_FAILURE, _("failed to allocate output line")); - rc = set_scols_data(lc, ln); - if (rc) - break; - } - - loopcxt_deinit_iterator(lc); - free(cn_file); - } -done: - if (rc == 0) - rc = scols_print_table(tb); - scols_unref_table(tb); - return rc; -} - -static void __attribute__((__noreturn__)) usage(void) -{ - FILE *out = stdout; - size_t i; - - fputs(USAGE_HEADER, out); - - fprintf(out, - _(" %1$s [options] [<xloopdev>]\n" - " %1$s [options] -f | <xloopdev> <file>\n"), - program_invocation_short_name); - - fputs(USAGE_SEPARATOR, out); - fputs(_("Set up and control xloop devices.\n"), out); - - /* commands */ - fputs(USAGE_OPTIONS, out); - fputs(_(" -a, --all list all used devices\n"), out); - fputs(_(" -d, --detach <xloopdev>... detach one or more devices\n"), out); - fputs(_(" -D, --detach-all detach all used devices\n"), out); - fputs(_(" -f, --find find first unused device\n"), out); - fputs(_(" -c, --set-capacity <xloopdev> resize the device\n"), out); - fputs(_(" -j, --associated <file> list all devices associated with <file>\n"), out); - fputs(_(" -L, --nooverlap avoid possible conflict between devices\n"), out); - - /* commands options */ - fputs(USAGE_SEPARATOR, out); - fputs(_(" -o, --offset <num> start at offset <num> into file\n"), out); - fputs(_(" --sizelimit <num> device is limited to <num> bytes of the file\n"), out); - fputs(_(" -b, --sector-size <num> set the logical sector size to <num>\n"), out); - fputs(_(" -P, --partscan create a partitioned xloop device\n"), out); - fputs(_(" -r, --read-only set up a read-only xloop device\n"), out); - fputs(_(" --direct-io[=<on|off>] open backing file with O_DIRECT\n"), out); - fputs(_(" --show print device name after setup (with -f)\n"), out); - fputs(_(" -t, --type set file format type of the loop device\n"), out); - fputs(_(" -v, --verbose verbose mode\n"), out); - - /* output options */ - fputs(USAGE_SEPARATOR, out); - fputs(_(" -J, --json use JSON --list output format\n"), out); - fputs(_(" -l, --list list info about all or specified (default)\n"), out); - fputs(_(" -n, --noheadings don't print headings for --list output\n"), out); - fputs(_(" -O, --output <cols> specify columns to output for --list\n"), out); - fputs(_(" --output-all output all columns\n"), out); - fputs(_(" --raw use raw --list output format\n"), out); - - fputs(USAGE_SEPARATOR, out); - printf(USAGE_HELP_OPTIONS(31)); - - fputs(USAGE_COLUMNS, out); - for (i = 0; i < ARRAY_SIZE(infos); i++) - fprintf(out, " %12s %s\n", infos[i].name, _(infos[i].help)); - - printf(USAGE_MAN_TAIL("xlosetup(8)")); - - exit(EXIT_SUCCESS); -} - -static int create_loop(struct loopdev_cxt *lc, - int nooverlap, int lo_flags, int flags, - const char *file, uint64_t offset, uint64_t sizelimit, - uint64_t blocksize, uint32_t file_fmt_type) -{ - int hasdev = loopcxt_has_device(lc); - int rc = 0; - - /* xlosetup --find --noverlap file.img */ - if (!hasdev && nooverlap) { - rc = loopcxt_find_overlap(lc, file, offset, sizelimit); - switch (rc) { - case 0: /* not found */ - break; - - case 1: /* overlap */ - loopcxt_deinit(lc); - errx(EXIT_FAILURE, _("%s: overlapping xloop device exists"), file); - - case 2: /* overlap -- full size and offset match (reuse) */ - { - uint32_t lc_encrypt_type; - - /* Once a xloop is initialized RO, there is no - * way to change its parameters. */ - if (loopcxt_is_readonly(lc) - && !(lo_flags & LO_FLAGS_READ_ONLY)) { - loopcxt_deinit(lc); - errx(EXIT_FAILURE, _("%s: overlapping read-only xloop device exists"), file); - } - - /* This is no more supported, but check to be safe. */ - if (loopcxt_get_encrypt_type(lc, &lc_encrypt_type) == 0 - && lc_encrypt_type != LO_CRYPT_NONE) { - loopcxt_deinit(lc); - errx(EXIT_FAILURE, _("%s: overlapping encrypted xloop device exists"), file); - } - - lc->info.lo_flags &= ~LO_FLAGS_AUTOCLEAR; - if (loopcxt_ioctl_status(lc)) { - loopcxt_deinit(lc); - errx(EXIT_FAILURE, _("%s: failed to re-use xloop device"), file); - } - return 0; /* success, re-use */ - } - default: /* error */ - loopcxt_deinit(lc); - errx(EXIT_FAILURE, _("failed to inspect xloop devices")); - return -errno; - } - } - - if (hasdev && !is_loopdev(loopcxt_get_device(lc))) - loopcxt_add_device(lc); - - /* xlosetup --noverlap /dev/xloopN file.img */ - if (hasdev && nooverlap) { - struct loopdev_cxt lc2; - - if (loopcxt_init(&lc2, 0)) { - loopcxt_deinit(lc); - err(EXIT_FAILURE, _("failed to initialize loopcxt")); - } - rc = loopcxt_find_overlap(&lc2, file, offset, sizelimit); - loopcxt_deinit(&lc2); - - if (rc) { - loopcxt_deinit(lc); - if (rc > 0) - errx(EXIT_FAILURE, _("%s: overlapping xloop device exists"), file); - err(EXIT_FAILURE, _("%s: failed to check for conflicting xloop devices"), file); - } - } - - /* Create a new device */ - do { - const char *errpre; - - /* Note that loopcxt_{find_unused,set_device}() resets - * loopcxt struct. - */ - if (!hasdev && (rc = loopcxt_find_unused(lc))) { - warnx(_("cannot find an unused xloop device")); - break; - } - if (flags & LOOPDEV_FL_OFFSET) - loopcxt_set_offset(lc, offset); - if (flags & LOOPDEV_FL_SIZELIMIT) - loopcxt_set_sizelimit(lc, sizelimit); - if (lo_flags) - loopcxt_set_flags(lc, lo_flags); - if (blocksize > 0) - loopcxt_set_blocksize(lc, blocksize); - - if ((rc = loopcxt_set_backing_file(lc, file))) { - warn(_("%s: failed to use backing file"), file); - break; - } - - if ((rc = loopcxt_set_file_fmt_type(lc, file_fmt_type))) { - warn(_("failed to use backing file format type")); - break; - } - - errno = 0; - rc = loopcxt_setup_device(lc); - if (rc == 0) - break; /* success */ - if (errno == EBUSY && !hasdev) - continue; - - /* errors */ - errpre = hasdev && loopcxt_get_fd(lc) < 0 ? - loopcxt_get_device(lc) : file; - warn(_("%s: failed to set up xloop device"), errpre); - break; - } while (hasdev == 0); - - return rc; -} - -int main(int argc, char **argv) -{ - struct loopdev_cxt lc; - int act = 0, flags = 0, no_overlap = 0, c; - char *file = NULL; - uint64_t offset = 0, sizelimit = 0, blocksize = 0; - int res = 0, showdev = 0, lo_flags = 0; - char *outarg = NULL; - int list = 0; - unsigned long use_dio = 0, set_dio = 0, set_blocksize = 0; - int use_file_fmt_type = 0; - uint32_t file_fmt_type = 0; - - enum { - OPT_SIZELIMIT = CHAR_MAX + 1, - OPT_SHOW, - OPT_RAW, - OPT_DIO, - OPT_OUTPUT_ALL - }; - static const struct option longopts[] = { - { "all", no_argument, NULL, 'a' }, - { "set-capacity", required_argument, NULL, 'c' }, - { "detach", required_argument, NULL, 'd' }, - { "detach-all", no_argument, NULL, 'D' }, - { "find", no_argument, NULL, 'f' }, - { "nooverlap", no_argument, NULL, 'L' }, - { "help", no_argument, NULL, 'h' }, - { "associated", required_argument, NULL, 'j' }, - { "json", no_argument, NULL, 'J' }, - { "list", no_argument, NULL, 'l' }, - { "sector-size", required_argument, NULL, 'b' }, - { "noheadings", no_argument, NULL, 'n' }, - { "offset", required_argument, NULL, 'o' }, - { "output", required_argument, NULL, 'O' }, - { "output-all", no_argument, NULL, OPT_OUTPUT_ALL }, - { "sizelimit", required_argument, NULL, OPT_SIZELIMIT }, - { "partscan", no_argument, NULL, 'P' }, - { "read-only", no_argument, NULL, 'r' }, - { "direct-io", optional_argument, NULL, OPT_DIO }, - { "raw", no_argument, NULL, OPT_RAW }, - { "show", no_argument, NULL, OPT_SHOW }, - { "type", required_argument, NULL, 't' }, - { "verbose", no_argument, NULL, 'v' }, - { "version", no_argument, NULL, 'V' }, - { NULL, 0, NULL, 0 } - }; - - static const ul_excl_t excl[] = { /* rows and cols in ASCII order */ - { 'D','a','c','d','f','j' }, - { 'D','c','d','f','l' }, - { 'D','c','d','f','O' }, - { 'J',OPT_RAW }, - { 0 } - }; - int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT; - - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - close_stdout_atexit(); - - if (loopcxt_init(&lc, 0)) - err(EXIT_FAILURE, _("failed to initialize loopcxt")); - - while ((c = getopt_long(argc, argv, "ab:c:d:Dfhj:JlLno:O:Prt:vV", - longopts, NULL)) != -1) { - - err_exclusive_options(c, longopts, excl, excl_st); - - switch (c) { - case 'a': - act = A_SHOW; - break; - case 'b': - set_blocksize = 1; - blocksize = strtosize_or_err(optarg, _("failed to parse logical block size")); - break; - case 'c': - act = A_SET_CAPACITY; - if (!is_loopdev(optarg) || - 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; - if (!is_loopdev(optarg) || - loopcxt_set_device(&lc, optarg)) - err(EXIT_FAILURE, _("%s: failed to use device"), - optarg); - break; - case 'D': - act = A_DELETE_ALL; - break; - case 'f': - act = A_FIND_FREE; - break; - case 'J': - json = 1; - break; - case 'j': - act = A_SHOW; - file = optarg; - break; - case 'l': - list = 1; - break; - case 'L': - no_overlap = 1; - break; - case 'n': - no_headings = 1; - break; - case OPT_RAW: - raw = 1; - break; - case 'o': - offset = strtosize_or_err(optarg, _("failed to parse offset")); - flags |= LOOPDEV_FL_OFFSET; - break; - case 'O': - outarg = optarg; - list = 1; - break; - case OPT_OUTPUT_ALL: - for (ncolumns = 0; ncolumns < ARRAY_SIZE(infos); ncolumns++) - columns[ncolumns] = ncolumns; - break; - case 'P': - lo_flags |= LO_FLAGS_PARTSCAN; - break; - case OPT_SHOW: - showdev = 1; - break; - case OPT_DIO: - use_dio = set_dio = 1; - if (optarg) - use_dio = parse_switch(optarg, _("argument error"), "on", "off", NULL); - break; - case 't': - if (optarg) { - if (parse_file_fmt_type(optarg, &file_fmt_type) == 0) - use_file_fmt_type = 1; - else - errx(EXIT_FAILURE, _("failed to parse file format type")); - } - break; - case 'v': - break; - case OPT_SIZELIMIT: /* --sizelimit */ - sizelimit = strtosize_or_err(optarg, _("failed to parse size")); - flags |= LOOPDEV_FL_SIZELIMIT; - break; - - case 'h': - usage(); - case 'V': - print_version(EXIT_SUCCESS); - default: - errtryhelp(EXIT_FAILURE); - } - } - - ul_path_init_debug(); - ul_sysfs_init_debug(); - - /* default is --list --all */ - if (argc == 1) { - act = A_SHOW; - list = 1; - } - - if (!act && argc == 2 && (raw || json)) { - act = A_SHOW; - list = 1; - } - - /* default --list output columns */ - if (list && !ncolumns) { - columns[ncolumns++] = COL_NAME; - columns[ncolumns++] = COL_SIZELIMIT; - columns[ncolumns++] = COL_OFFSET; - columns[ncolumns++] = COL_AUTOCLR; - columns[ncolumns++] = COL_RO; - columns[ncolumns++] = COL_BACK_FILE; - columns[ncolumns++] = COL_FILE_FMT_TYPE; - columns[ncolumns++] = COL_DIO; - columns[ncolumns++] = COL_LOGSEC; - } - - if (act == A_FIND_FREE && optind < argc) { - /* - * xlosetup -f <backing_file> - */ - act = A_CREATE; - file = argv[optind++]; - - if (optind < argc) - errx(EXIT_FAILURE, _("unexpected arguments")); - } - - if (list && !act && optind == argc) - /* - * xlosetup --list defaults to --all - */ - act = A_SHOW; - - if (!act && optind + 1 == argc) { - /* - * xlosetup [--list] <device> - * OR - * xlosetup {--direct-io[=off]|--logical-blocksize=size}... <device> - */ - if (!(set_dio || set_blocksize)) - act = A_SHOW_ONE; - if (set_dio) - act = A_SET_DIRECT_IO; - if (set_blocksize) - act = A_SET_BLOCKSIZE; - if (!is_loopdev(argv[optind]) || - loopcxt_set_device(&lc, argv[optind])) - err(EXIT_FAILURE, _("%s: failed to use device"), - argv[optind]); - optind++; - } - if (!act) { - /* - * xlosetup <xloopdev> <backing_file> - */ - act = A_CREATE; - - if (optind >= argc) - errx(EXIT_FAILURE, _("no xloop device specified")); - /* don't use is_loopdev() here, the device does not have exist yet */ - 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")); - file = argv[optind++]; - } - - if (act != A_CREATE && - (sizelimit || lo_flags || showdev || use_file_fmt_type)) - errx(EXIT_FAILURE, - _("the options %s are allowed during xloop device setup only"), - "--{sizelimit,partscan,read-only,show,type}"); - - if ((flags & LOOPDEV_FL_OFFSET) && - act != A_CREATE && (act != A_SHOW || !file)) - errx(EXIT_FAILURE, _("the option --offset is not allowed in this context")); - - if (outarg && string_add_to_idarray(outarg, columns, ARRAY_SIZE(columns), - &ncolumns, column_name_to_id) < 0) - return EXIT_FAILURE; - - switch (act) { - case A_CREATE: - res = create_loop(&lc, no_overlap, lo_flags, flags, file, - offset, sizelimit, blocksize, file_fmt_type); - if (res == 0) { - if (showdev) - printf("%s\n", loopcxt_get_device(&lc)); - if (set_dio) - goto lo_set_dio; - } - break; - case A_DELETE: - res = delete_loop(&lc); - while (optind < argc) { - if (!is_loopdev(argv[optind]) || - loopcxt_set_device(&lc, argv[optind])) - warn(_("%s: failed to use device"), - argv[optind]); - optind++; - res += delete_loop(&lc); - } - break; - case A_DELETE_ALL: - res = delete_all_loops(&lc); - break; - case A_FIND_FREE: - res = loopcxt_find_unused(&lc); - if (res) { - int errsv = errno; - - if (access(_PATH_DEV_LOOPCTL, F_OK) == 0 && - access(_PATH_DEV_LOOPCTL, W_OK) != 0) - ; - else - errno = errsv; - - warn(_("cannot find an unused xloop device")); - } else - printf("%s\n", loopcxt_get_device(&lc)); - break; - case A_SHOW: - if (list) - res = show_table(&lc, file, offset, flags); - else - res = show_all_loops(&lc, file, offset, flags); - break; - case A_SHOW_ONE: - if (list) - res = show_table(&lc, NULL, 0, 0); - else - res = printf_loopdev(&lc); - if (res) - warn("%s", loopcxt_get_device(&lc)); - break; - case A_SET_CAPACITY: - res = loopcxt_ioctl_capacity(&lc); - if (res) - warn(_("%s: set capacity failed"), - loopcxt_get_device(&lc)); - break; - case A_SET_DIRECT_IO: -lo_set_dio: - res = loopcxt_ioctl_dio(&lc, use_dio); - if (res) - warn(_("%s: set direct io failed"), - loopcxt_get_device(&lc)); - break; - case A_SET_BLOCKSIZE: - res = loopcxt_ioctl_blocksize(&lc, blocksize); - if (res) - warn(_("%s: set logical block size failed"), - loopcxt_get_device(&lc)); - break; - default: - warnx(_("bad usage")); - errtryhelp(EXIT_FAILURE); - break; - } - - loopcxt_deinit(&lc); - return res ? EXIT_FAILURE : EXIT_SUCCESS; -} - |
