]> git.ipfire.org Git - thirdparty/util-linux.git/blame - mount/losetup.c
Imported from util-linux-2.9i tarball.
[thirdparty/util-linux.git] / mount / losetup.c
CommitLineData
fd6b7a7f
KZ
1/*
2 * losetup.c - setup and control loop devices
3 */
4
5#include <stdio.h>
6#include <string.h>
7#include <ctype.h>
8#include <fcntl.h>
9#include <unistd.h>
10#include <getopt.h>
11#include <errno.h>
12#include <sys/ioctl.h>
13
14#include "loop.h"
15#include "lomount.h"
16
17#ifdef LOOP_SET_FD
18
19static char *progname;
20
21struct crypt_type_struct {
22 int id;
23 char *name;
24} crypt_type_tbl[] = {
25 { LO_CRYPT_NONE,"no" },
26 { LO_CRYPT_NONE,"none" },
27 { LO_CRYPT_XOR, "xor" },
28 { LO_CRYPT_DES, "DES" },
29 { -1, NULL }
30};
31
32
33static char *crypt_name(int id)
34{
35 int i;
36
37 for (i = 0; crypt_type_tbl[i].id != -1; i++)
38 if (id == crypt_type_tbl[i].id)
39 return crypt_type_tbl[i].name;
40 return "undefined";
41}
42
43
44static int crypt_type(const char *name)
45{
46 int i;
47
48 for (i = 0; crypt_type_tbl[i].id != -1; i++)
49 if (!strcasecmp(name, crypt_type_tbl[i].name))
50 return crypt_type_tbl[i].id;
51 return -1;
52}
53
54
55static void show_loop(const char *device)
56{
57 struct loop_info loopinfo;
58 int fd;
2b6fc908 59
fd6b7a7f
KZ
60 if ((fd = open(device, O_RDWR)) < 0) {
61 perror(device);
62 return;
63 }
64 if (ioctl(fd, LOOP_GET_STATUS, &loopinfo) < 0) {
65 perror("Cannot get loop info");
66 close(fd);
67 return;
68 }
69 printf("%s: [%04x]:%ld (%s) offset %d, %s encryption\n",
70 device, loopinfo.lo_device, loopinfo.lo_inode,
71 loopinfo.lo_name, loopinfo.lo_offset,
72 crypt_name(loopinfo.lo_encrypt_type));
73 close(fd);
74}
75
76
77int set_loop(const char *device, const char *file, int offset,
78 const char *encryption, int *loopro)
79{
80 struct loop_info loopinfo;
81 int fd, ffd, mode, i;
82 char *pass;
2b6fc908 83
fd6b7a7f
KZ
84 mode = *loopro ? O_RDONLY : O_RDWR;
85 if ((ffd = open (file, mode)) < 0 && !*loopro
86 && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) {
87 perror (file);
88 return 1;
89 }
90 if ((fd = open (device, mode)) < 0) {
91 perror (device);
92 return 1;
93 }
94 *loopro = (mode == O_RDONLY);
95
96 memset(&loopinfo, 0, sizeof(loopinfo));
97 strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
98 loopinfo.lo_name[LO_NAME_SIZE-1] = 0;
99 if (encryption && (loopinfo.lo_encrypt_type = crypt_type(encryption))
100 < 0) {
2b6fc908 101 fprintf(stderr,"Unsupported encryption type %s\n",encryption);
fd6b7a7f
KZ
102 exit(1);
103 }
104 loopinfo.lo_offset = offset;
105 switch (loopinfo.lo_encrypt_type) {
106 case LO_CRYPT_NONE:
107 loopinfo.lo_encrypt_key_size = 0;
108 break;
109 case LO_CRYPT_XOR:
110 pass = getpass("Password: ");
111 strncpy(loopinfo.lo_encrypt_key, pass, LO_KEY_SIZE);
112 loopinfo.lo_encrypt_key[LO_KEY_SIZE-1] = 0;
113 loopinfo.lo_encrypt_key_size = strlen(loopinfo.lo_encrypt_key);
114 break;
115 case LO_CRYPT_DES:
116 pass = getpass("Password: ");
117 strncpy(loopinfo.lo_encrypt_key, pass, 8);
118 loopinfo.lo_encrypt_key[8] = 0;
119 loopinfo.lo_encrypt_key_size = 8;
120 pass = getpass("Init (up to 16 hex digits): ");
121 for (i = 0; i < 16 && pass[i]; i++)
122 if (isxdigit(pass[i]))
123 loopinfo.lo_init[i >> 3] |= (pass[i] > '9' ?
124 (islower(pass[i]) ? toupper(pass[i]) :
125 pass[i])-'A'+10 : pass[i]-'0') << (i & 7)*4;
126 else {
127 fprintf(stderr,"Non-hex digit '%c'.\n",pass[i]);
128 exit(1);
129 }
130 break;
131 default:
132 fprintf(stderr,
133 "Don't know how to get key for encryption system %d\n",
134 loopinfo.lo_encrypt_type);
135 exit(1);
136 }
137 if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
138 perror("ioctl: LOOP_SET_FD");
139 exit(1);
140 }
141 if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
142 (void) ioctl(fd, LOOP_CLR_FD, 0);
143 perror("ioctl: LOOP_SET_STATUS");
144 exit(1);
145 }
146 close(fd);
147 close(ffd);
148 return 0;
149}
150
151int del_loop(const char *device)
152{
153 int fd;
154
155 if ((fd = open(device, O_RDONLY)) < 0) {
156 perror(device);
157 exit(1);
158 }
159 if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
160 perror("ioctl: LOOP_CLR_FD");
161 exit(1);
162 }
163 return(0);
164}
165
166
167static int usage(void)
168{
169 fprintf(stderr, "usage:\n\
170 %s loop_device # give info\n\
171 %s -d loop_device # delete\n\
172 %s [ -e encryption ] [ -o offset ] loop_device file # setup\n",
173 progname, progname, progname);
174 exit(1);
175}
176
177int main(int argc, char **argv)
178{
179 char *offset,*encryption;
180 int delete,off,c;
181 int ro = 0;
182
183 delete = off = 0;
184 offset = encryption = NULL;
185 progname = argv[0];
186 while ((c = getopt(argc,argv,"de:o:")) != EOF) {
187 switch (c) {
188 case 'd':
189 delete = 1;
190 break;
191 case 'e':
192 encryption = optarg;
193 break;
194 case 'o':
195 offset = optarg;
196 break;
197 default:
198 usage();
199 }
200 }
201 if (argc == 1) usage();
202 if ((delete && (argc != optind+1 || encryption || offset)) ||
203 (!delete && (argc < optind+1 || argc > optind+2)))
204 usage();
5c36a0eb 205 if (argc == optind+1) {
fd6b7a7f
KZ
206 if (delete)
207 del_loop(argv[optind]);
208 else
209 show_loop(argv[optind]);
5c36a0eb 210 } else {
fd6b7a7f
KZ
211 if (offset && sscanf(offset,"%d",&off) != 1)
212 usage();
213 set_loop(argv[optind],argv[optind+1],off,encryption,&ro);
214 }
215 return 0;
216}
217
218#else /* LOOP_SET_FD not defined */
219
220int main(int argc, char **argv) {
221 fprintf(stderr,
222 "No loop support was available at compile time. Please recompile.\n");
223 return -1;
224}
225#endif