/* losetup.c - Loopback setup
 *
 * Copyright 2012 Rob Landley <rob@landley.net>
 *
 * No standard. (Sigh.)

USE_LOSETUP(NEWTOY(losetup, ">2S(sizelimit)#s(show)ro#j:fdcaD[!afj]", TOYFLAG_SBIN))

config LOSETUP
  bool "losetup"
  default y
  help
    usage: losetup [-cdrs] [-o OFFSET] [-S SIZE] {-d DEVICE...|-j FILE|-af|{DEVICE FILE}}

    Associate a loopback device with a file, or show current file (if any)
    associated with a loop device.

    Instead of a device:
    -a	Iterate through all loopback devices
    -f	Find first unused loop device (may create one)
    -j FILE	Iterate through all loopback devices associated with FILE

    existing:
    -c	Check capacity (file size changed)
    -d DEV	Detach loopback device
    -D	Detach all loopback devices

    new:
    -s	Show device name (alias --show)
    -o OFF	Start association at offset OFF into FILE
    -r	Read only
    -S SIZE	Limit SIZE of loopback association (alias --sizelimit)
*/

#define FOR_losetup
#include "toys.h"
#include <linux/loop.h>

GLOBALS(
  char *j;
  long o, S;

  int openflags;
  dev_t jdev;
  ino_t jino;
  char *dir;
)

// -f: *device is NULL

// Perform requested operation on one device. Returns 1 if handled, 0 if error
static int loopback_setup(char *device, char *file)
{
  struct loop_info64 *loop = (void *)(toybuf+32);
  int lfd = -1, ffd = ffd;
  int racy = !device;

  // Open file (ffd) and loop device (lfd)

  if (file) ffd = xopen(file, TT.openflags);
  if (!device) {
    int i, cfd = open("/dev/loop-control", O_RDWR);

    // We assume /dev is devtmpfs so device creation has no lag. Otherwise
    // just preallocate loop devices and stay within them.

    // mount -o loop depends on found device being at the start of toybuf.
    if (cfd != -1) {
      if (0 <= (i = ioctl(cfd, LOOP_CTL_GET_FREE))) {
        sprintf(device = toybuf, "%s/loop%d", TT.dir, i);
      }
      close(cfd);
    }
  }

  if (device) lfd = open(device, TT.openflags);

  // Stat the loop device to see if there's a current association.
  memset(loop, 0, sizeof(struct loop_info64));
  if (-1 == lfd || ioctl(lfd, LOOP_GET_STATUS64, loop)) {
    if (errno == ENXIO && (FLAG(a) || FLAG(j))) goto done;
    // ENXIO expected if we're just trying to print the first unused device.
    if (errno == ENXIO && FLAG(f) && !file) {
      puts(device);
      goto done;
    }
    if (errno != ENXIO || !file) {
      perror_msg_raw(device ? device : "-f");
      goto done;
    }
  }

  // Skip -j filtered devices
  if (TT.j && (loop->lo_device != TT.jdev || loop->lo_inode != TT.jino))
    goto done;

  // Check size of file or delete existing association
  if (FLAG(c) || FLAG(d)) {
    // The constant is LOOP_SET_CAPACITY
    if (ioctl(lfd, FLAG(c) ? 0x4C07 : LOOP_CLR_FD, 0)) {
      perror_msg_raw(device);
      goto done;
    }
  // Associate file with this device?
  } else if (file) {
    char *f_path = xabspath(file, 1);

    if (!f_path) perror_exit("file"); // already opened, but if deleted since...
    if (ioctl(lfd, LOOP_SET_FD, ffd)) {
      free(f_path);
      if (racy && errno == EBUSY) return 1;
      perror_exit("%s=%s", device, file);
    }
    xstrncpy((char *)loop->lo_file_name, f_path, LO_NAME_SIZE);
    free(f_path);
    loop->lo_offset = TT.o;
    loop->lo_sizelimit = TT.S;
    if (ioctl(lfd, LOOP_SET_STATUS64, loop)) perror_exit("%s=%s", device, file);
    if (FLAG(s)) puts(device);
  }
  else {
    xprintf("%s: [%lld]:%llu (%s)", device, (long long)loop->lo_device,
      (long long)loop->lo_inode, loop->lo_file_name);
    if (loop->lo_offset) xprintf(", offset %llu",
      (unsigned long long)loop->lo_offset);
    if (loop->lo_sizelimit) xprintf(", sizelimit %llu",
      (unsigned long long)loop->lo_sizelimit);
    xputc('\n');
  }

done:
  if (file) close(ffd);
  if (lfd != -1) close(lfd);
  return 0;
}

// Perform an action on all currently existing loop devices
static int dash_a(struct dirtree *node)
{
  char *s = node->name;

  // Initial /dev node needs to recurse down one level, then only loop[0-9]*
  if (!node->parent) return DIRTREE_RECURSE;
  if (strncmp(s, "loop", 4) || !isdigit(s[4])) return 0;

  s = dirtree_path(node, 0);
  loopback_setup(s, 0);
  free(s);

  return 0;
}

void losetup_main(void)
{
  char **s;

  TT.dir = CFG_TOYBOX_ON_ANDROID ? "/dev/block" : "/dev";
  TT.openflags = FLAG(r) ? O_RDONLY : O_RDWR;

  if (TT.j) {
    struct stat st;

    xstat(TT.j, &st);
    TT.jdev = st.st_dev;
    TT.jino = st.st_ino;
  }

  // With just device, display current association
  // -a, -f substitute for device
  // -j substitute for device

  // new association: S size o offset rs - need a file
  // existing association: cd

  // -f(dc FILE)

  if (FLAG(D)) toys.optflags |= FLAG_a | FLAG_d;

  if (FLAG(f)) {
    if (toys.optc > 1) perror_exit("max 1 arg");
    while (loopback_setup(NULL, *toys.optargs));
  } else if (FLAG(a) || FLAG(j)) {
    if (toys.optc) error_exit("bad args");
    dirtree_read(TT.dir, dash_a);
  // Do we need one DEVICE argument?
  } else {
    char *file = (FLAG(c) || FLAG(d)) ? NULL : toys.optargs[1];

    if (!toys.optc || (file && toys.optc != 2))
      help_exit("needs %d arg%s", 1+!!file, file ? "s" : "");
    for (s = toys.optargs; *s; s++) {
      loopback_setup(*s, file);
      if (file) break;
    }
  }
}
