static int _losetup ( const char *loop, // Loop device const char *file, // Target file (or block device) int fatal ) { int r, loopfd = -1, filefd = -1, mode; r = filefd = open(file, mode = O_RDWR); if (r < 0) { r = filefd = open(file, mode = O_RDONLY); if (r < 0) { if (fatal) _fatal("cannot open %s", file); goto exit; } } r = loopfd = open(loop, mode); if (r < 0) { r = loopfd = open(loop, mode = O_RDONLY); if (r < 0) { if (fatal) _fatal("cannot open %s", loop); goto exit; } } r = losetup(loopfd, filefd, file); if (r < 0 && fatal) _fatal("cannot setup loop device %s", loop); exit: close(loopfd); close(filefd); return r; }
static int loop_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { int ret; switch (cmd) { /* Command: LOOPIOC_SETUP * Description: Setup the loop device * Argument: A pointer to a read-only instance of struct losetup_s. * Dependencies: The loop device must be enabled (CONFIG_DEV_LOOP=y) */ case LOOPIOC_SETUP: { FAR struct losetup_s *setup = (FAR struct losetup_s *)((uintptr_t)arg); if (setup == NULL) { ret = -EINVAL; } else { ret = losetup(setup->devname, setup->filename, setup->sectsize, setup->offset, setup->readonly); } } break; /* Command: LOOPIOC_TEARDOWN * Description: Teardown a loop device previously setup vis LOOPIOC_SETUP * Argument: A read-able pointer to the path of the device to be * torn down * Dependencies: The loop device must be enabled (CONFIG_DEV_LOOP=y) */ case LOOPIOC_TEARDOWN: { FAR const char *devname = (FAR const char *)((uintptr_t)arg); if (devname == NULL) { ret = -EINVAL; } else { ret = loteardown(devname); } } break; default: ret = -ENOTTY; break; } return ret; }
int cmd_losetup(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { char *loopdev = NULL; char *filepath = NULL; bool teardown = false; bool readonly = false; off_t offset = 0; bool badarg = false; int ret = ERROR; int option; /* Get the losetup options: Two forms are supported: * * losetup -d <loop-device> * losetup [-o <offset>] [-r] <loop-device> <filename> * * NOTE that the -o and -r options are accepted with the -d option, but * will be ignored. */ while ((option = getopt(argc, argv, "d:o:r")) != ERROR) { switch (option) { case 'd': loopdev = nsh_getfullpath(vtbl, optarg); teardown = true; break; case 'o': offset = atoi(optarg); break; case 'r': readonly = true; break; case '?': default: nsh_output(vtbl, g_fmtarginvalid, argv[0]); badarg = true; break; } } /* If a bad argument was encountered, then return without processing the command */ if (badarg) { goto errout_with_paths; } /* If this is not a tear down operation, then additional command line * parameters are required. */ if (!teardown) { /* There must be two arguments on the command line after the options */ if (optind + 1 < argc) { loopdev = nsh_getfullpath(vtbl, argv[optind]); optind++; filepath = nsh_getfullpath(vtbl, argv[optind]); optind++; } else { nsh_output(vtbl, g_fmtargrequired, argv[0]); goto errout_with_paths; } } /* There should be nothing else on the command line */ if (optind < argc) { nsh_output(vtbl, g_fmttoomanyargs, argv[0]); goto errout_with_paths; } /* Perform the teardown operation */ if (teardown) { /* Tear down the loop device. */ ret = loteardown(loopdev); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "loteardown", NSH_ERRNO_OF(-ret)); goto errout_with_paths; } } else { /* Set up the loop device */ ret = losetup(loopdev, filepath, 512, offset, readonly); if (ret < 0) { nsh_output(vtbl, g_fmtcmdfailed, argv[0], "losetup", NSH_ERRNO_OF(-ret)); goto errout_with_paths; } } /* Free memory */ errout_with_paths: if (loopdev) { free(loopdev); } if (filepath) { free(filepath); } return ret; }