]>
Commit | Line | Data |
---|---|---|
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 | ||
19 | static char *progname; | |
20 | ||
21 | struct 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 | ||
33 | static 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 | ||
44 | static 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 | ||
55 | static 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 | ||
77 | int 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 | ||
151 | int 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 | ||
167 | static 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 | ||
177 | int 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 | ||
220 | int 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 |