Eric Andersen | cc8ed39 | 1999-10-05 16:24:54 +0000 | [diff] [blame] | 1 | /* |
| 2 | * losetup.c - setup and control loop devices |
| 3 | */ |
| 4 | |
| 5 | |
| 6 | #include "internal.h" |
| 7 | |
| 8 | const char losetup_usage[] = "losetup\n" |
| 9 | "\n" |
| 10 | "\tlosetup loop_device give info\n" |
| 11 | "\tlosetup -d loop_device delete\n" |
| 12 | "\tlosetup [ -o offset ] loop_device file setup\n"; |
| 13 | |
| 14 | /* from mount-2.6d */ |
| 15 | |
| 16 | /* |
| 17 | * losetup.c - setup and control loop devices |
| 18 | */ |
| 19 | |
| 20 | #include <stdio.h> |
| 21 | #include <string.h> |
| 22 | #include <ctype.h> |
| 23 | #include <fcntl.h> |
| 24 | #include <unistd.h> |
| 25 | #include <getopt.h> |
| 26 | #include <errno.h> |
| 27 | #include <sys/ioctl.h> |
| 28 | #include <linux/fs.h> |
| 29 | /* #include "loop.h" */ |
| 30 | |
| 31 | /* |
| 32 | * include/linux/loop.h |
| 33 | * |
| 34 | * Written by Theodore Ts'o, 3/29/93. |
| 35 | * |
| 36 | * Copyright 1993 by Theodore Ts'o. Redistribution of this file is |
| 37 | * permitted under the GNU Public License. |
| 38 | */ |
| 39 | |
| 40 | #define LO_NAME_SIZE 64 |
| 41 | #define LO_KEY_SIZE 32 |
| 42 | |
| 43 | struct loop_info { |
| 44 | int lo_number; /* ioctl r/o */ |
| 45 | dev_t lo_device; /* ioctl r/o */ |
| 46 | unsigned long lo_inode; /* ioctl r/o */ |
| 47 | dev_t lo_rdevice; /* ioctl r/o */ |
| 48 | int lo_offset; |
| 49 | int lo_encrypt_type; |
| 50 | int lo_encrypt_key_size; /* ioctl w/o */ |
| 51 | int lo_flags; /* ioctl r/o */ |
| 52 | char lo_name[LO_NAME_SIZE]; |
| 53 | unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ |
| 54 | unsigned long lo_init[2]; |
| 55 | char reserved[4]; |
| 56 | }; |
| 57 | |
| 58 | /* |
| 59 | * IOCTL commands --- we will commandeer 0x4C ('L') |
| 60 | */ |
| 61 | |
| 62 | #define LOOP_SET_FD 0x4C00 |
| 63 | #define LOOP_CLR_FD 0x4C01 |
| 64 | #define LOOP_SET_STATUS 0x4C02 |
| 65 | #define LOOP_GET_STATUS 0x4C03 |
| 66 | |
| 67 | /* #include "lomount.h" */ |
| 68 | |
| 69 | extern int set_loop (const char *, const char *, int, int *); |
| 70 | extern int del_loop (const char *); |
| 71 | |
| 72 | static void show_loop(const char *device) |
| 73 | { |
| 74 | struct loop_info loopinfo; |
| 75 | int fd; |
| 76 | |
| 77 | if ((fd = open(device, O_RDWR)) < 0) { |
| 78 | perror(device); |
| 79 | return; |
| 80 | } |
| 81 | if (ioctl(fd, LOOP_GET_STATUS, &loopinfo) < 0) { |
| 82 | perror("Cannot get loop info"); |
| 83 | close(fd); |
| 84 | return; |
| 85 | } |
| 86 | printf("%s: [%04x]:%ld (%s) offset %d\n", |
| 87 | device, (unsigned int)loopinfo.lo_device, loopinfo.lo_inode, |
| 88 | loopinfo.lo_name, loopinfo.lo_offset); |
| 89 | close(fd); |
| 90 | } |
| 91 | |
| 92 | |
| 93 | int set_loop(const char *device, const char *file, int offset, int *loopro) |
| 94 | { |
| 95 | struct loop_info loopinfo; |
| 96 | int fd, ffd, mode; |
| 97 | |
| 98 | mode = *loopro ? O_RDONLY : O_RDWR; |
| 99 | if ((ffd = open (file, mode)) < 0 && !*loopro |
| 100 | && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) { |
| 101 | perror (file); |
| 102 | return 1; |
| 103 | } |
| 104 | if ((fd = open (device, mode)) < 0) { |
| 105 | close(ffd); |
| 106 | perror (device); |
| 107 | return 1; |
| 108 | } |
| 109 | *loopro = (mode == O_RDONLY); |
| 110 | |
| 111 | memset(&loopinfo, 0, sizeof(loopinfo)); |
| 112 | strncpy(loopinfo.lo_name, file, LO_NAME_SIZE); |
| 113 | loopinfo.lo_name[LO_NAME_SIZE-1] = 0; |
| 114 | |
| 115 | loopinfo.lo_offset = offset; |
| 116 | |
| 117 | loopinfo.lo_encrypt_key_size = 0; |
| 118 | if (ioctl(fd, LOOP_SET_FD, ffd) < 0) { |
| 119 | perror("ioctl: LOOP_SET_FD"); |
| 120 | exit(1); |
| 121 | } |
| 122 | if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) { |
| 123 | (void) ioctl(fd, LOOP_CLR_FD, 0); |
| 124 | perror("ioctl: LOOP_SET_STATUS"); |
| 125 | exit(1); |
| 126 | } |
| 127 | close(fd); |
| 128 | close(ffd); |
| 129 | return 0; |
| 130 | } |
| 131 | |
| 132 | int del_loop(const char *device) |
| 133 | { |
| 134 | int fd; |
| 135 | |
| 136 | if ((fd = open(device, O_RDONLY)) < 0) { |
| 137 | perror(device); |
| 138 | exit(1); |
| 139 | } |
| 140 | if (ioctl(fd, LOOP_CLR_FD, 0) < 0) { |
| 141 | perror("ioctl: LOOP_CLR_FD"); |
| 142 | exit(1); |
| 143 | } |
| 144 | close(fd); |
| 145 | return(0); |
| 146 | } |
| 147 | |
| 148 | |
| 149 | static int losetup_usage_fn(void) |
| 150 | { |
| 151 | fprintf(stderr, losetup_usage); |
| 152 | exit(1); |
| 153 | } |
| 154 | |
| 155 | int losetup_main(struct FileInfo * i, int argc, char * * argv) |
| 156 | { |
| 157 | char *offset; |
| 158 | int delete,off,c; |
| 159 | int ro = 0; |
| 160 | |
| 161 | delete = off = 0; |
| 162 | offset = NULL; |
| 163 | while ((c = getopt(argc,argv,"do:")) != EOF) { |
| 164 | switch (c) { |
| 165 | case 'd': |
| 166 | delete = 1; |
| 167 | break; |
| 168 | case 'o': |
| 169 | offset = optarg; |
| 170 | break; |
| 171 | default: |
| 172 | losetup_usage_fn(); |
| 173 | } |
| 174 | } |
| 175 | if (argc == 1) losetup_usage_fn(); |
| 176 | if ((delete && (argc != optind+1 || offset)) || |
| 177 | (!delete && (argc < optind+1 || argc > optind+2))) |
| 178 | losetup_usage_fn(); |
| 179 | if (argc == optind+1) |
| 180 | if (delete) |
| 181 | del_loop(argv[optind]); |
| 182 | else |
| 183 | show_loop(argv[optind]); |
| 184 | else { |
| 185 | if (offset && sscanf(offset,"%d",&off) != 1) |
| 186 | losetup_usage_fn(); |
| 187 | set_loop(argv[optind],argv[optind+1],off,&ro); |
| 188 | } |
| 189 | return 0; |
| 190 | } |