summaryrefslogtreecommitdiffstats
path: root/utils/sys-utils
diff options
context:
space:
mode:
authorManuel Bentele2020-10-23 15:18:01 +0200
committerManuel Bentele2020-10-23 15:18:01 +0200
commitdbb41ce2b7f309d394054a6bd1e33afd578798a5 (patch)
tree6a31092063d9f2fb5ac5720ec6759040e793c3d5 /utils/sys-utils
parentSet Linux kernel version to unknown if it is not detectable (diff)
downloadxloop-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.txt19
-rw-r--r--utils/sys-utils/xlosetup.8215
-rw-r--r--utils/sys-utils/xlosetup.c931
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;
-}
-