(root)/
util-linux-2.39/
sys-utils/
losetup.c
       1  /*
       2   * Copyright (C) 2011 Karel Zak <kzak@redhat.com>
       3   * Originally from Ted's losetup.c
       4   *
       5   * losetup.c - setup and control loop devices
       6   */
       7  #include <assert.h>
       8  #include <stdio.h>
       9  #include <string.h>
      10  #include <errno.h>
      11  #include <stdlib.h>
      12  #include <unistd.h>
      13  #include <sys/ioctl.h>
      14  #include <sys/stat.h>
      15  #include <inttypes.h>
      16  #include <getopt.h>
      17  
      18  #include <libsmartcols.h>
      19  
      20  #include "c.h"
      21  #include "nls.h"
      22  #include "strutils.h"
      23  #include "loopdev.h"
      24  #include "closestream.h"
      25  #include "optutils.h"
      26  #include "xalloc.h"
      27  #include "canonicalize.h"
      28  #include "pathnames.h"
      29  
      30  enum {
      31  	A_CREATE = 1,		/* setup a new device */
      32  	A_DELETE,		/* delete given device(s) */
      33  	A_DELETE_ALL,		/* delete all devices */
      34  	A_SHOW,			/* list devices */
      35  	A_SHOW_ONE,		/* print info about one device */
      36  	A_FIND_FREE,		/* find first unused */
      37  	A_SET_CAPACITY,		/* set device capacity */
      38  	A_SET_DIRECT_IO,	/* set accessing backing file by direct io */
      39  	A_SET_BLOCKSIZE,	/* set logical block size of the loop device */
      40  };
      41  
      42  enum {
      43  	COL_NAME = 0,
      44  	COL_AUTOCLR,
      45  	COL_BACK_FILE,
      46  	COL_BACK_INO,
      47  	COL_BACK_MAJMIN,
      48  	COL_MAJMIN,
      49  	COL_OFFSET,
      50  	COL_PARTSCAN,
      51  	COL_RO,
      52  	COL_SIZELIMIT,
      53  	COL_DIO,
      54  	COL_LOGSEC,
      55  };
      56  
      57  /* basic output flags */
      58  static int no_headings;
      59  static int raw;
      60  static int json;
      61  
      62  struct colinfo {
      63  	const char *name;
      64  	double whint;
      65  	int flags;
      66  	const char *help;
      67  
      68  	int json_type;	/* default is string */
      69  };
      70  
      71  static struct colinfo infos[] = {
      72  	[COL_AUTOCLR]     = { "AUTOCLEAR",    1, SCOLS_FL_RIGHT, N_("autoclear flag set"), SCOLS_JSON_BOOLEAN},
      73  	[COL_BACK_FILE]   = { "BACK-FILE",  0.3, SCOLS_FL_NOEXTREMES, N_("device backing file")},
      74  	[COL_BACK_INO]    = { "BACK-INO",     4, SCOLS_FL_RIGHT, N_("backing file inode number"), SCOLS_JSON_NUMBER},
      75  	[COL_BACK_MAJMIN] = { "BACK-MAJ:MIN", 6, 0, N_("backing file major:minor device number")},
      76  	[COL_NAME]        = { "NAME",      0.25, 0, N_("loop device name")},
      77  	[COL_OFFSET]      = { "OFFSET",       5, SCOLS_FL_RIGHT, N_("offset from the beginning"), SCOLS_JSON_NUMBER},
      78  	[COL_PARTSCAN]    = { "PARTSCAN",     1, SCOLS_FL_RIGHT, N_("partscan flag set"), SCOLS_JSON_BOOLEAN},
      79  	[COL_RO]          = { "RO",           1, SCOLS_FL_RIGHT, N_("read-only device"), SCOLS_JSON_BOOLEAN},
      80  	[COL_SIZELIMIT]   = { "SIZELIMIT",    5, SCOLS_FL_RIGHT, N_("size limit of the file in bytes"), SCOLS_JSON_NUMBER},
      81  	[COL_MAJMIN]      = { "MAJ:MIN",      3, 0, N_("loop device major:minor number")},
      82  	[COL_DIO]         = { "DIO",          1, SCOLS_FL_RIGHT, N_("access backing file with direct-io"), SCOLS_JSON_BOOLEAN},
      83  	[COL_LOGSEC]      = { "LOG-SEC",      4, SCOLS_FL_RIGHT, N_("logical sector size in bytes"), SCOLS_JSON_NUMBER},
      84  };
      85  
      86  static int columns[ARRAY_SIZE(infos) * 2] = {-1};
      87  static size_t ncolumns;
      88  
      89  static int get_column_id(int num)
      90  {
      91  	assert(num >= 0);
      92  	assert((size_t) num < ncolumns);
      93  	assert(columns[num] < (int) ARRAY_SIZE(infos));
      94  	return columns[num];
      95  }
      96  
      97  static struct colinfo *get_column_info(int num)
      98  {
      99  	return &infos[ get_column_id(num) ];
     100  }
     101  
     102  static int column_name_to_id(const char *name, size_t namesz)
     103  {
     104  	size_t i;
     105  
     106  	for (i = 0; i < ARRAY_SIZE(infos); i++) {
     107  		const char *cn = infos[i].name;
     108  
     109  		if (!strncasecmp(name, cn, namesz) && !*(cn + namesz))
     110  			return i;
     111  	}
     112  	warnx(_("unknown column: %s"), name);
     113  	return -1;
     114  }
     115  
     116  static int printf_loopdev(struct loopdev_cxt *lc)
     117  {
     118  	uint64_t x;
     119  	dev_t dev = 0;
     120  	ino_t ino = 0;
     121  	char *fname;
     122  	uint32_t type;
     123  
     124  	fname = loopcxt_get_backing_file(lc);
     125  	if (!fname)
     126  		return -EINVAL;
     127  
     128  	if (loopcxt_get_backing_devno(lc, &dev) == 0)
     129  		loopcxt_get_backing_inode(lc, &ino);
     130  
     131  	if (!dev && !ino) {
     132  		/*
     133  		 * Probably non-root user (no permissions to
     134  		 * call LOOP_GET_STATUS ioctls).
     135  		 */
     136  		printf("%s: []: (%s)",
     137  			loopcxt_get_device(lc), fname);
     138  
     139  		if (loopcxt_get_offset(lc, &x) == 0 && x)
     140  				printf(_(", offset %ju"), x);
     141  
     142  		if (loopcxt_get_sizelimit(lc, &x) == 0 && x)
     143  				printf(_(", sizelimit %ju"), x);
     144  		goto done;
     145  	}
     146  
     147  	printf("%s: [%04jd]:%ju (%s)",
     148  		loopcxt_get_device(lc), (intmax_t) dev, (uintmax_t) ino, fname);
     149  
     150  	if (loopcxt_get_offset(lc, &x) == 0 && x)
     151  			printf(_(", offset %ju"), x);
     152  
     153  	if (loopcxt_get_sizelimit(lc, &x) == 0 && x)
     154  			printf(_(", sizelimit %ju"), x);
     155  
     156  	if (loopcxt_get_encrypt_type(lc, &type) == 0) {
     157  		const char *e = loopcxt_get_crypt_name(lc);
     158  
     159  		if ((!e || !*e) && type == 1)
     160  			e = "XOR";
     161  		if (e && *e)
     162  			printf(_(", encryption %s (type %u)"), e, type);
     163  	}
     164  
     165  done:
     166  	free(fname);
     167  	printf("\n");
     168  	return 0;
     169  }
     170  
     171  static int show_all_loops(struct loopdev_cxt *lc, const char *file,
     172  			  uint64_t offset, int flags)
     173  {
     174  	struct stat sbuf, *st = &sbuf;
     175  	char *cn_file = NULL;
     176  
     177  	if (loopcxt_init_iterator(lc, LOOPITER_FL_USED))
     178  		return -1;
     179  
     180  	if (!file || stat(file, st))
     181  		st = NULL;
     182  
     183  	while (loopcxt_next(lc) == 0) {
     184  		if (file) {
     185  			int used;
     186  			const char *bf = cn_file ? cn_file : file;
     187  
     188  			used = loopcxt_is_used(lc, st, bf, offset, 0, flags);
     189  			if (!used && !cn_file) {
     190  				bf = cn_file = canonicalize_path(file);
     191  				used = loopcxt_is_used(lc, st, bf, offset, 0, flags);
     192  			}
     193  			if (!used)
     194  				continue;
     195  		}
     196  		printf_loopdev(lc);
     197  	}
     198  	loopcxt_deinit_iterator(lc);
     199  	free(cn_file);
     200  	return 0;
     201  }
     202  
     203  static int delete_loop(struct loopdev_cxt *lc)
     204  {
     205  	if (loopcxt_delete_device(lc))
     206  		warn(_("%s: detach failed"), loopcxt_get_device(lc));
     207  	else
     208  		return 0;
     209  
     210  	return -1;
     211  }
     212  
     213  static int delete_all_loops(struct loopdev_cxt *lc)
     214  {
     215  	int res = 0;
     216  
     217  	if (loopcxt_init_iterator(lc, LOOPITER_FL_USED))
     218  		return -1;
     219  
     220  	while (loopcxt_next(lc) == 0)
     221  		res += delete_loop(lc);
     222  
     223  	loopcxt_deinit_iterator(lc);
     224  	return res;
     225  }
     226  
     227  static int set_scols_data(struct loopdev_cxt *lc, struct libscols_line *ln)
     228  {
     229  	size_t i;
     230  
     231  	for (i = 0; i < ncolumns; i++) {
     232  		const char *p = NULL;			/* external data */
     233  		char *np = NULL;			/* allocated here */
     234  		uint64_t x = 0;
     235  		int rc = 0;
     236  
     237  		switch(get_column_id(i)) {
     238  		case COL_NAME:
     239  			p = loopcxt_get_device(lc);
     240  			break;
     241  		case COL_BACK_FILE:
     242  			np = loopcxt_get_backing_file(lc);
     243  			break;
     244  		case COL_OFFSET:
     245  			if (loopcxt_get_offset(lc, &x) == 0)
     246  				xasprintf(&np, "%jd", x);
     247  			break;
     248  		case COL_SIZELIMIT:
     249  			if (loopcxt_get_sizelimit(lc, &x) == 0)
     250  				xasprintf(&np, "%jd", x);
     251  			break;
     252  		case COL_BACK_MAJMIN:
     253  		{
     254  			dev_t dev = 0;
     255  			if (loopcxt_get_backing_devno(lc, &dev) == 0 && dev)
     256  				xasprintf(&np, "%8u:%-3u", major(dev), minor(dev));
     257  			break;
     258  		}
     259  		case COL_MAJMIN:
     260  		{
     261  			struct stat st;
     262  
     263  			if (loopcxt_get_device(lc)
     264  			    && stat(loopcxt_get_device(lc), &st) == 0
     265  			    && S_ISBLK(st.st_mode)
     266  			    && major(st.st_rdev) == LOOPDEV_MAJOR)
     267  				xasprintf(&np, "%3u:%-3u", major(st.st_rdev),
     268  						           minor(st.st_rdev));
     269  			break;
     270  		}
     271  		case COL_BACK_INO:
     272  		{
     273  			ino_t ino = 0;
     274  			if (loopcxt_get_backing_inode(lc, &ino) == 0 && ino)
     275  				xasprintf(&np, "%ju", ino);
     276  			break;
     277  		}
     278  		case COL_AUTOCLR:
     279  			p = loopcxt_is_autoclear(lc) ? "1" : "0";
     280  			break;
     281  		case COL_RO:
     282  			p = loopcxt_is_readonly(lc) ? "1" : "0";
     283  			break;
     284  		case COL_DIO:
     285  			p = loopcxt_is_dio(lc) ? "1" : "0";
     286  			break;
     287  		case COL_PARTSCAN:
     288  			p = loopcxt_is_partscan(lc) ? "1" : "0";
     289  			break;
     290  		case COL_LOGSEC:
     291  			if (loopcxt_get_blocksize(lc, &x) == 0)
     292  				xasprintf(&np, "%jd", x);
     293  			break;
     294  		default:
     295  			return -EINVAL;
     296  		}
     297  
     298  
     299  		if (p)
     300  			rc = scols_line_set_data(ln, i, p);	/* calls strdup() */
     301  		else if (np)
     302  			rc = scols_line_refer_data(ln, i, np);	/* only refers */
     303  
     304  		if (rc)
     305  			err(EXIT_FAILURE, _("failed to add output data"));
     306  	}
     307  
     308  	return 0;
     309  }
     310  
     311  static int show_table(struct loopdev_cxt *lc,
     312  		      const char *file,
     313  		      uint64_t offset,
     314  		      int flags)
     315  {
     316  	struct stat sbuf, *st = &sbuf;
     317  	struct libscols_table *tb;
     318  	struct libscols_line *ln;
     319  	int rc = 0;
     320  	size_t i;
     321  
     322  	scols_init_debug(0);
     323  
     324  	if (!(tb = scols_new_table()))
     325  		err(EXIT_FAILURE, _("failed to allocate output table"));
     326  	scols_table_enable_raw(tb, raw);
     327  	scols_table_enable_json(tb, json);
     328  	scols_table_enable_noheadings(tb, no_headings);
     329  
     330  	if (json)
     331  		scols_table_set_name(tb, "loopdevices");
     332  
     333  	for (i = 0; i < ncolumns; i++) {
     334  		struct colinfo *ci = get_column_info(i);
     335  		struct libscols_column *cl;
     336  
     337  		cl = scols_table_new_column(tb, ci->name, ci->whint, ci->flags);
     338  		if (!cl)
     339  			err(EXIT_FAILURE, _("failed to allocate output column"));
     340  		if (json)
     341  			scols_column_set_json_type(cl, ci->json_type);
     342  	}
     343  
     344  	/* only one loopdev requested (already assigned to loopdev_cxt) */
     345  	if (loopcxt_get_device(lc)) {
     346  		ln = scols_table_new_line(tb, NULL);
     347  		if (!ln)
     348  			err(EXIT_FAILURE, _("failed to allocate output line"));
     349  		rc = set_scols_data(lc, ln);
     350  
     351  	/* list all loopdevs */
     352  	} else {
     353  		char *cn_file = NULL;
     354  
     355  		rc = loopcxt_init_iterator(lc, LOOPITER_FL_USED);
     356  		if (rc)
     357  			goto done;
     358  		if (!file || stat(file, st))
     359  			st = NULL;
     360  
     361  		while (loopcxt_next(lc) == 0) {
     362  			if (file) {
     363  				int used;
     364  				const char *bf = cn_file ? cn_file : file;
     365  
     366  				used = loopcxt_is_used(lc, st, bf, offset, 0, flags);
     367  				if (!used && !cn_file) {
     368  					bf = cn_file = canonicalize_path(file);
     369  					used = loopcxt_is_used(lc, st, bf, offset, 0, flags);
     370  				}
     371  				if (!used)
     372  					continue;
     373  			}
     374  
     375  			ln = scols_table_new_line(tb, NULL);
     376  			if (!ln)
     377  				err(EXIT_FAILURE, _("failed to allocate output line"));
     378  			rc = set_scols_data(lc, ln);
     379  			if (rc)
     380  				break;
     381  		}
     382  
     383  		loopcxt_deinit_iterator(lc);
     384  		free(cn_file);
     385  	}
     386  done:
     387  	if (rc == 0)
     388  		rc = scols_print_table(tb);
     389  	scols_unref_table(tb);
     390  	return rc;
     391  }
     392  
     393  static void __attribute__((__noreturn__)) usage(void)
     394  {
     395  	FILE *out = stdout;
     396  	size_t i;
     397  
     398  	fputs(USAGE_HEADER, out);
     399  
     400  	fprintf(out,
     401  	      _(" %1$s [options] [<loopdev>]\n"
     402  		" %1$s [options] -f | <loopdev> <file>\n"),
     403  		program_invocation_short_name);
     404  
     405  	fputs(USAGE_SEPARATOR, out);
     406  	fputs(_("Set up and control loop devices.\n"), out);
     407  
     408  	/* commands */
     409  	fputs(USAGE_OPTIONS, out);
     410  	fputs(_(" -a, --all                     list all used devices\n"), out);
     411  	fputs(_(" -d, --detach <loopdev>...     detach one or more devices\n"), out);
     412  	fputs(_(" -D, --detach-all              detach all used devices\n"), out);
     413  	fputs(_(" -f, --find                    find first unused device\n"), out);
     414  	fputs(_(" -c, --set-capacity <loopdev>  resize the device\n"), out);
     415  	fputs(_(" -j, --associated <file>       list all devices associated with <file>\n"), out);
     416  	fputs(_(" -L, --nooverlap               avoid possible conflict between devices\n"), out);
     417  
     418  	/* commands options */
     419  	fputs(USAGE_SEPARATOR, out);
     420  	fputs(_(" -o, --offset <num>            start at offset <num> into file\n"), out);
     421  	fputs(_("     --sizelimit <num>         device is limited to <num> bytes of the file\n"), out);
     422  	fputs(_(" -b, --sector-size <num>       set the logical sector size to <num>\n"), out);
     423  	fputs(_(" -P, --partscan                create a partitioned loop device\n"), out);
     424  	fputs(_(" -r, --read-only               set up a read-only loop device\n"), out);
     425  	fputs(_("     --direct-io[=<on|off>]    open backing file with O_DIRECT\n"), out);
     426  	fputs(_("     --show                    print device name after setup (with -f)\n"), out);
     427  	fputs(_(" -v, --verbose                 verbose mode\n"), out);
     428  
     429  	/* output options */
     430  	fputs(USAGE_SEPARATOR, out);
     431  	fputs(_(" -J, --json                    use JSON --list output format\n"), out);
     432  	fputs(_(" -l, --list                    list info about all or specified (default)\n"), out);
     433  	fputs(_(" -n, --noheadings              don't print headings for --list output\n"), out);
     434  	fputs(_(" -O, --output <cols>           specify columns to output for --list\n"), out);
     435  	fputs(_("     --output-all              output all columns\n"), out);
     436  	fputs(_("     --raw                     use raw --list output format\n"), out);
     437  
     438  	fputs(USAGE_SEPARATOR, out);
     439  	printf(USAGE_HELP_OPTIONS(31));
     440  
     441  	fputs(USAGE_COLUMNS, out);
     442  	for (i = 0; i < ARRAY_SIZE(infos); i++)
     443  		fprintf(out, " %12s  %s\n", infos[i].name, _(infos[i].help));
     444  
     445  	printf(USAGE_MAN_TAIL("losetup(8)"));
     446  
     447  	exit(EXIT_SUCCESS);
     448  }
     449  
     450  static void warn_size(const char *filename, uint64_t size, uint64_t offset, int flags)
     451  {
     452  	struct stat st;
     453  
     454  	if (!size) {
     455  		if (stat(filename, &st) || S_ISBLK(st.st_mode))
     456  			return;
     457  		size = st.st_size;
     458  
     459  		if (flags & LOOPDEV_FL_OFFSET)
     460  			size -= offset;
     461  	}
     462  
     463  	if (size < 512)
     464  		warnx(_("%s: Warning: file is smaller than 512 bytes; the loop device "
     465  			"may be useless or invisible for system tools."),
     466  			filename);
     467  	else if (size % 512)
     468  		warnx(_("%s: Warning: file does not fit into a 512-byte sector; "
     469  		        "the end of the file will be ignored."),
     470  			filename);
     471  }
     472  
     473  static int create_loop(struct loopdev_cxt *lc,
     474  		       int nooverlap, int lo_flags, int flags,
     475  		       const char *file, uint64_t offset, uint64_t sizelimit,
     476  		       uint64_t blocksize)
     477  {
     478  	int hasdev = loopcxt_has_device(lc);
     479  	int rc = 0, ntries = 0;
     480  
     481  	/* losetup --find --noverlap file.img */
     482  	if (!hasdev && nooverlap) {
     483  		rc = loopcxt_find_overlap(lc, file, offset, sizelimit);
     484  		switch (rc) {
     485  		case 0: /* not found */
     486  			break;
     487  
     488  		case 1:	/* overlap */
     489  			loopcxt_deinit(lc);
     490  			errx(EXIT_FAILURE, _("%s: overlapping loop device exists"), file);
     491  
     492  		case 2: /* overlap -- full size and offset match (reuse) */
     493  		{
     494  			uint32_t lc_encrypt_type;
     495  
     496  			/* Once a loop is initialized RO, there is no
     497  			 * way to change its parameters. */
     498  			if (loopcxt_is_readonly(lc)
     499  			    && !(lo_flags & LO_FLAGS_READ_ONLY)) {
     500  				loopcxt_deinit(lc);
     501  				errx(EXIT_FAILURE, _("%s: overlapping read-only loop device exists"), file);
     502  			}
     503  
     504  			/* This is no more supported, but check to be safe. */
     505  			if (loopcxt_get_encrypt_type(lc, &lc_encrypt_type) == 0
     506  			    && lc_encrypt_type != LO_CRYPT_NONE) {
     507  				loopcxt_deinit(lc);
     508  				errx(EXIT_FAILURE, _("%s: overlapping encrypted loop device exists"), file);
     509  			}
     510  
     511  			lc->config.info.lo_flags &= ~LO_FLAGS_AUTOCLEAR;
     512  			if (loopcxt_ioctl_status(lc)) {
     513  				loopcxt_deinit(lc);
     514  				errx(EXIT_FAILURE, _("%s: failed to re-use loop device"), file);
     515  			}
     516  			return 0;	/* success, re-use */
     517  		}
     518  		default: /* error */
     519  			loopcxt_deinit(lc);
     520  			errx(EXIT_FAILURE, _("failed to inspect loop devices"));
     521  			return -errno;
     522  		}
     523  	}
     524  
     525  	if (hasdev)
     526  		loopcxt_add_device(lc);
     527  
     528  	/* losetup --noverlap /dev/loopN file.img */
     529  	if (hasdev && nooverlap) {
     530  		struct loopdev_cxt lc2;
     531  
     532  		if (loopcxt_init(&lc2, 0)) {
     533  			loopcxt_deinit(lc);
     534  			err(EXIT_FAILURE, _("failed to initialize loopcxt"));
     535  		}
     536  		rc = loopcxt_find_overlap(&lc2, file, offset, sizelimit);
     537  		loopcxt_deinit(&lc2);
     538  
     539  		if (rc) {
     540  			loopcxt_deinit(lc);
     541  			if (rc > 0)
     542  				errx(EXIT_FAILURE, _("%s: overlapping loop device exists"), file);
     543  			err(EXIT_FAILURE, _("%s: failed to check for conflicting loop devices"), file);
     544  		}
     545  	}
     546  
     547  	/* Create a new device */
     548  	do {
     549  		const char *errpre;
     550  
     551  		/* Note that loopcxt_{find_unused,set_device}() resets
     552  		 * loopcxt struct.
     553  		 */
     554  		if (!hasdev && (rc = loopcxt_find_unused(lc))) {
     555  			warnx(_("cannot find an unused loop device"));
     556  			break;
     557  		}
     558  		if (flags & LOOPDEV_FL_OFFSET)
     559  			loopcxt_set_offset(lc, offset);
     560  		if (flags & LOOPDEV_FL_SIZELIMIT)
     561  			loopcxt_set_sizelimit(lc, sizelimit);
     562  		if (lo_flags)
     563  			loopcxt_set_flags(lc, lo_flags);
     564  		if (blocksize > 0)
     565  			loopcxt_set_blocksize(lc, blocksize);
     566  
     567  		if ((rc = loopcxt_set_backing_file(lc, file))) {
     568  			warn(_("%s: failed to use backing file"), file);
     569  			break;
     570  		}
     571  		errno = 0;
     572  		rc = loopcxt_setup_device(lc);
     573  		if (rc == 0)
     574  			break;			/* success */
     575  
     576  		if ((errno == EBUSY || errno == EAGAIN) && !hasdev && ntries < 64) {
     577  			xusleep(200000);
     578  			ntries++;
     579  			continue;
     580  		}
     581  
     582  		/* errors */
     583  		errpre = hasdev && loopcxt_get_fd(lc) < 0 ?
     584  				 loopcxt_get_device(lc) : file;
     585  		warn(_("%s: failed to set up loop device"), errpre);
     586  		break;
     587  	} while (hasdev == 0);
     588  
     589  	return rc;
     590  }
     591  
     592  int main(int argc, char **argv)
     593  {
     594  	struct loopdev_cxt lc;
     595  	int act = 0, flags = 0, no_overlap = 0, c;
     596  	char *file = NULL;
     597  	uint64_t offset = 0, sizelimit = 0, blocksize = 0;
     598  	int res = 0, showdev = 0, lo_flags = 0;
     599  	char *outarg = NULL;
     600  	int list = 0;
     601  	unsigned long use_dio = 0, set_dio = 0, set_blocksize = 0;
     602  
     603  	enum {
     604  		OPT_SIZELIMIT = CHAR_MAX + 1,
     605  		OPT_SHOW,
     606  		OPT_RAW,
     607  		OPT_DIO,
     608  		OPT_OUTPUT_ALL
     609  	};
     610  	static const struct option longopts[] = {
     611  		{ "all",          no_argument,       NULL, 'a'           },
     612  		{ "set-capacity", required_argument, NULL, 'c'           },
     613  		{ "detach",       required_argument, NULL, 'd'           },
     614  		{ "detach-all",   no_argument,       NULL, 'D'           },
     615  		{ "find",         no_argument,       NULL, 'f'           },
     616  		{ "nooverlap",    no_argument,       NULL, 'L'           },
     617  		{ "help",         no_argument,       NULL, 'h'           },
     618  		{ "associated",   required_argument, NULL, 'j'           },
     619  		{ "json",         no_argument,       NULL, 'J'           },
     620  		{ "list",         no_argument,       NULL, 'l'           },
     621  		{ "sector-size",  required_argument, NULL, 'b'      },
     622  		{ "noheadings",   no_argument,       NULL, 'n'           },
     623  		{ "offset",       required_argument, NULL, 'o'           },
     624  		{ "output",       required_argument, NULL, 'O'           },
     625  		{ "output-all",   no_argument,       NULL, OPT_OUTPUT_ALL },
     626  		{ "sizelimit",    required_argument, NULL, OPT_SIZELIMIT },
     627  		{ "partscan",     no_argument,       NULL, 'P'           },
     628  		{ "read-only",    no_argument,       NULL, 'r'           },
     629  		{ "direct-io",    optional_argument, NULL, OPT_DIO       },
     630  		{ "raw",          no_argument,       NULL, OPT_RAW       },
     631  		{ "show",         no_argument,       NULL, OPT_SHOW      },
     632  		{ "verbose",      no_argument,       NULL, 'v'           },
     633  		{ "version",      no_argument,       NULL, 'V'           },
     634  		{ NULL, 0, NULL, 0 }
     635  	};
     636  
     637  	static const ul_excl_t excl[] = {	/* rows and cols in ASCII order */
     638  		{ 'D','a','c','d','f','j' },
     639  		{ 'D','c','d','f','l' },
     640  		{ 'D','c','d','f','O' },
     641  		{ 'J',OPT_RAW },
     642  		{ 0 }
     643  	};
     644  	int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
     645  
     646  	setlocale(LC_ALL, "");
     647  	bindtextdomain(PACKAGE, LOCALEDIR);
     648  	textdomain(PACKAGE);
     649  	close_stdout_atexit();
     650  
     651  	if (loopcxt_init(&lc, 0))
     652  		err(EXIT_FAILURE, _("failed to initialize loopcxt"));
     653  
     654  	while ((c = getopt_long(argc, argv, "ab:c:d:Dfhj:JlLno:O:PrvV",
     655  				longopts, NULL)) != -1) {
     656  
     657  		err_exclusive_options(c, longopts, excl, excl_st);
     658  
     659  		switch (c) {
     660  		case 'a':
     661  			act = A_SHOW;
     662  			break;
     663  		case 'b':
     664  			set_blocksize = 1;
     665  			blocksize = strtosize_or_err(optarg, _("failed to parse logical block size"));
     666  			break;
     667  		case 'c':
     668  			act = A_SET_CAPACITY;
     669  			if (!is_loopdev(optarg) ||
     670  			    loopcxt_set_device(&lc, optarg))
     671  				err(EXIT_FAILURE, _("%s: failed to use device"),
     672  						optarg);
     673  			break;
     674  		case 'r':
     675  			lo_flags |= LO_FLAGS_READ_ONLY;
     676  			break;
     677  		case 'd':
     678  			act = A_DELETE;
     679  			if (!is_loopdev(optarg) ||
     680  			    loopcxt_set_device(&lc, optarg))
     681  				err(EXIT_FAILURE, _("%s: failed to use device"),
     682  						optarg);
     683  			break;
     684  		case 'D':
     685  			act = A_DELETE_ALL;
     686  			break;
     687  		case 'f':
     688  			act = A_FIND_FREE;
     689  			break;
     690  		case 'J':
     691  			json = 1;
     692  			break;
     693  		case 'j':
     694  			act = A_SHOW;
     695  			file = optarg;
     696  			break;
     697  		case 'l':
     698  			list = 1;
     699  			break;
     700  		case 'L':
     701  			no_overlap = 1;
     702  			break;
     703  		case 'n':
     704  			no_headings = 1;
     705  			break;
     706  		case OPT_RAW:
     707  			raw = 1;
     708  			break;
     709  		case 'o':
     710  			offset = strtosize_or_err(optarg, _("failed to parse offset"));
     711  			flags |= LOOPDEV_FL_OFFSET;
     712  			break;
     713  		case 'O':
     714  			outarg = optarg;
     715  			list = 1;
     716  			break;
     717  		case OPT_OUTPUT_ALL:
     718  			for (ncolumns = 0; ncolumns < ARRAY_SIZE(infos); ncolumns++)
     719  				columns[ncolumns] = ncolumns;
     720  			break;
     721  		case 'P':
     722  			lo_flags |= LO_FLAGS_PARTSCAN;
     723  			break;
     724  		case OPT_SHOW:
     725  			showdev = 1;
     726  			break;
     727  		case OPT_DIO:
     728  			use_dio = set_dio = 1;
     729  			if (optarg)
     730  				use_dio = parse_switch(optarg, _("argument error"), "on", "off", NULL);
     731  			if (use_dio)
     732  				lo_flags |= LO_FLAGS_DIRECT_IO;
     733  			break;
     734  		case 'v':
     735  			break;
     736  		case OPT_SIZELIMIT:			/* --sizelimit */
     737  			sizelimit = strtosize_or_err(optarg, _("failed to parse size"));
     738  			flags |= LOOPDEV_FL_SIZELIMIT;
     739                          break;
     740  
     741  		case 'h':
     742  			usage();
     743  		case 'V':
     744  			print_version(EXIT_SUCCESS);
     745  		default:
     746  			errtryhelp(EXIT_FAILURE);
     747  		}
     748  	}
     749  
     750  	ul_path_init_debug();
     751  	ul_sysfs_init_debug();
     752  
     753  	/* default is --list --all */
     754  	if (argc == 1) {
     755  		act = A_SHOW;
     756  		list = 1;
     757  	}
     758  
     759  	if (!act && argc == 2 && (raw || json)) {
     760  		act = A_SHOW;
     761  		list = 1;
     762  	}
     763  
     764  	/* default --list output columns */
     765  	if (list && !ncolumns) {
     766  		columns[ncolumns++] = COL_NAME;
     767  		columns[ncolumns++] = COL_SIZELIMIT;
     768  		columns[ncolumns++] = COL_OFFSET;
     769  		columns[ncolumns++] = COL_AUTOCLR;
     770  		columns[ncolumns++] = COL_RO;
     771  		columns[ncolumns++] = COL_BACK_FILE;
     772  		columns[ncolumns++] = COL_DIO;
     773  		columns[ncolumns++] = COL_LOGSEC;
     774  	}
     775  
     776  	if (act == A_FIND_FREE && optind < argc) {
     777  		/*
     778  		 * losetup -f <backing_file>
     779  		 */
     780  		act = A_CREATE;
     781  		file = argv[optind++];
     782  
     783  		if (optind < argc)
     784  			errx(EXIT_FAILURE, _("unexpected arguments"));
     785  	}
     786  
     787  	if (list && !act && optind == argc)
     788  		/*
     789  		 * losetup --list	defaults to --all
     790  		 */
     791  		act = A_SHOW;
     792  
     793  	if (!act && optind + 1 == argc) {
     794  		/*
     795  		 * losetup [--list] <device>
     796  		 * OR
     797  		 * losetup {--direct-io[=off]|--logical-blocksize=size}... <device>
     798  		 */
     799  		if (set_dio) {
     800  			act = A_SET_DIRECT_IO;
     801  			lo_flags &= ~LO_FLAGS_DIRECT_IO;
     802  		} else if (set_blocksize)
     803  			act = A_SET_BLOCKSIZE;
     804  		else
     805  			act = A_SHOW_ONE;
     806  
     807  		if (!is_loopdev(argv[optind]) ||
     808  		    loopcxt_set_device(&lc, argv[optind]))
     809  			err(EXIT_FAILURE, _("%s: failed to use device"),
     810  					argv[optind]);
     811  		optind++;
     812  	}
     813  	if (!act) {
     814  		/*
     815  		 * losetup <loopdev> <backing_file>
     816  		 */
     817  		act = A_CREATE;
     818  
     819  		if (optind >= argc)
     820  			errx(EXIT_FAILURE, _("no loop device specified"));
     821  		/* don't use is_loopdev() here, the device does not have exist yet */
     822  		if (loopcxt_set_device(&lc, argv[optind]))
     823  			err(EXIT_FAILURE, _("%s: failed to use device"),
     824  					argv[optind]);
     825  		optind++;
     826  
     827  		if (optind >= argc)
     828  			errx(EXIT_FAILURE, _("no file specified"));
     829  		file = argv[optind++];
     830  	}
     831  
     832  	if (act != A_CREATE &&
     833  	    (sizelimit || lo_flags || showdev))
     834  		errx(EXIT_FAILURE,
     835  			_("the options %s are allowed during loop device setup only"),
     836  			"--{sizelimit,partscan,read-only,show}");
     837  
     838  	if ((flags & LOOPDEV_FL_OFFSET) &&
     839  	    act != A_CREATE && (act != A_SHOW || !file))
     840  		errx(EXIT_FAILURE, _("the option --offset is not allowed in this context"));
     841  
     842  	if (outarg && string_add_to_idarray(outarg, columns, ARRAY_SIZE(columns),
     843  					 &ncolumns, column_name_to_id) < 0)
     844  		return EXIT_FAILURE;
     845  
     846  	switch (act) {
     847  	case A_CREATE:
     848  		res = create_loop(&lc, no_overlap, lo_flags, flags, file,
     849  				  offset, sizelimit, blocksize);
     850  		if (res == 0) {
     851  			if (showdev)
     852  				printf("%s\n", loopcxt_get_device(&lc));
     853  			warn_size(file, sizelimit, offset, flags);
     854  		}
     855  		break;
     856  	case A_DELETE:
     857  		res = delete_loop(&lc);
     858  		while (optind < argc) {
     859  			if (!is_loopdev(argv[optind]) ||
     860  			    loopcxt_set_device(&lc, argv[optind]))
     861  				warn(_("%s: failed to use device"),
     862  						argv[optind]);
     863  			optind++;
     864  			res += delete_loop(&lc);
     865  		}
     866  		break;
     867  	case A_DELETE_ALL:
     868  		res = delete_all_loops(&lc);
     869  		break;
     870  	case A_FIND_FREE:
     871  		res = loopcxt_find_unused(&lc);
     872  		if (res) {
     873  			int errsv = errno;
     874  
     875  			if (access(_PATH_DEV_LOOPCTL, F_OK) == 0 &&
     876  			    access(_PATH_DEV_LOOPCTL, W_OK) != 0)
     877  				;
     878  			else
     879  				errno = errsv;
     880  
     881  			warn(_("cannot find an unused loop device"));
     882  		} else
     883  			printf("%s\n", loopcxt_get_device(&lc));
     884  		break;
     885  	case A_SHOW:
     886  		if (list)
     887  			res = show_table(&lc, file, offset, flags);
     888  		else
     889  			res = show_all_loops(&lc, file, offset, flags);
     890  		break;
     891  	case A_SHOW_ONE:
     892  		if (list)
     893  			res = show_table(&lc, NULL, 0, 0);
     894  		else
     895  			res = printf_loopdev(&lc);
     896  		if (res)
     897  			warn("%s", loopcxt_get_device(&lc));
     898  		break;
     899  	case A_SET_CAPACITY:
     900  		res = loopcxt_ioctl_capacity(&lc);
     901  		if (res)
     902  			warn(_("%s: set capacity failed"),
     903  			        loopcxt_get_device(&lc));
     904  		break;
     905  	case A_SET_DIRECT_IO:
     906  		res = loopcxt_ioctl_dio(&lc, use_dio);
     907  		if (res)
     908  			warn(_("%s: set direct io failed"),
     909  			        loopcxt_get_device(&lc));
     910  		break;
     911  	case A_SET_BLOCKSIZE:
     912  		res = loopcxt_ioctl_blocksize(&lc, blocksize);
     913  		if (res)
     914  			warn(_("%s: set logical block size failed"),
     915  			        loopcxt_get_device(&lc));
     916  		break;
     917  	default:
     918  		warnx(_("bad usage"));
     919  		errtryhelp(EXIT_FAILURE);
     920  		break;
     921  	}
     922  
     923  	loopcxt_deinit(&lc);
     924  	return res ? EXIT_FAILURE : EXIT_SUCCESS;
     925  }
     926