My favorites
▼
|
Sign in
fscops
OHSM - Online Hierarchical Storage Manager
Project Home
Downloads
Wiki
Issues
Source
Export to GitHub
READ-ONLY: This project has been
archived
. For more information see
this post
.
Search
Search within:
All issues
Open issues
New issues
Issues to verify
for
Advanced search
Search tips
Subscriptions
Issue
73
attachment: libdevmapper.c
(12.4 KB)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
Sourcecode and documentation for cryptsetup version 1.0.6
show bar | Show file versions
Search packages:
| Sourcecode archive home
* Main Page
* Files
* Directories
cryptsetup-1.0.6 ยป lib
libdevmapper.c
00001 #include <stdio.h>
00002 #include <string.h>
00003 #include <stdlib.h>
00004 #include <stdint.h>
00005 #include <stdarg.h>
00006 #include <sys/types.h>
00007 #include <sys/stat.h>
00008 #include <sys/sysmacros.h>
00009 #include <unistd.h>
00010 #include <dirent.h>
00011 #include <errno.h>
00012 #include <libdevmapper.h>
00013
00014 #include "libcryptsetup.h"
00015 #include "internal.h"
00016
00017 #define DEVICE_DIR "/dev"
00018
00019 #define CRYPT_TARGET "crypt"
00020
00021 #define UDEVSETTLE "/sbin/udevsettle"
00022
00023 static void run_udevsettle(void)
00024 {
00025 system(UDEVSETTLE);
00026 }
00027
00028 static void set_dm_error(int level, const char *file, int line,
00029 const char *f, ...)
00030 {
00031 va_list va;
00032
00033 if (level > 3)
00034 return;
00035
00036 va_start(va, f);
00037 set_error_va(f, va);
00038 va_end(va);
00039 }
00040
00041 static int dm_init(void)
00042 {
00043 dm_log_init(set_dm_error);
00044 return 1; /* unsafe memory */
00045 }
00046
00047 static void dm_exit(void)
00048 {
00049 dm_log_init(NULL);
00050 dm_lib_release();
00051 }
00052
00053 static void flush_dm_workqueue(void)
00054 {
00055 /*
00056 * Unfortunately this is the only way to trigger libdevmapper's
00057 * update_nodes function
00058 */
00059 dm_exit();
00060 dm_init();
00061 }
00062
00063 static char *__lookup_dev(char *path, dev_t dev)
00064 {
00065 struct dirent *entry;
00066 struct stat st;
00067 char *ptr;
00068 char *result = NULL;
00069 DIR *dir;
00070 int space;
00071
00072 path[PATH_MAX - 1] = '\0';
00073 ptr = path + strlen(path);
00074 *ptr++ = '/';
00075 *ptr = '\0';
00076 space = PATH_MAX - (ptr - path);
00077
00078 dir = opendir(path);
00079 if (!dir)
00080 return NULL;
00081
00082 while((entry = readdir(dir))) {
00083 if (entry->d_name[0] == '.' &&
00084 (entry->d_name[1] == '\0' || (entry->d_name[1] == '.' &&
00085 entry->d_name[2] == '\0')))
00086 continue;
00087
00088 strncpy(ptr, entry->d_name, space);
00089 if (lstat(path, &st) < 0)
00090 continue;
00091
00092 if (S_ISDIR(st.st_mode)) {
00093 result = __lookup_dev(path, dev);
00094 if (result)
00095 break;
00096 } else if (S_ISBLK(st.st_mode)) {
00097 if (st.st_rdev == dev) {
00098 result = strdup(path);
00099 break;
00100 }
00101 }
00102 }
00103
00104 closedir(dir);
00105
00106 return result;
00107 }
00108
00109 static char *lookup_dev(const char *dev)
00110 {
00111 uint32_t major, minor;
00112 char buf[PATH_MAX + 1];
00113
00114 if (sscanf(dev, "%" PRIu32 ":%" PRIu32, &major, &minor) != 2)
00115 return NULL;
00116
00117 strncpy(buf, DEVICE_DIR, PATH_MAX);
00118 buf[PATH_MAX] = '\0';
00119
00120 return __lookup_dev(buf, makedev(major, minor));
00121 }
00122
00123 static char *get_params(struct crypt_options *options, const char *key)
00124 {
00125 char *params;
00126 char *hexkey;
00127 int i;
00128
00129 hexkey = safe_alloc(options->key_size * 2 + 1);
00130 if (!hexkey) {
00131 set_error("Memory allocation problem");
00132 return NULL;
00133 }
00134
00135 for(i = 0; i < options->key_size; i++)
00136 sprintf(&hexkey[i * 2], "%02x", (unsigned char)key[i]);
00137
00138 params = safe_alloc(strlen(hexkey) + strlen(options->cipher) +
00139 strlen(options->device) + 64);
00140 if (!params) {
00141 set_error("Memory allocation problem");
00142 goto out;
00143 }
00144
00145 sprintf(params, "%s %s %" PRIu64 " %s %" PRIu64,
00146 options->cipher, hexkey, options->skip,
00147 options->device, options->offset);
00148
00149 out:
00150 safe_free(hexkey);
00151
00152 return params;
00153 }
00154
00155 static int dm_create_device(int reload, struct crypt_options *options,
00156 const char *key)
00157 {
00158 struct dm_task *dmt = NULL;
00159 struct dm_task *dmt_query = NULL;
00160 struct dm_info dmi;
00161 char *params = NULL;
00162 int r = -EINVAL;
00163
00164 params = get_params(options, key);
00165 if (!params)
00166 goto out_no_removal;
00167 if (!(dmt = dm_task_create(reload ? DM_DEVICE_RELOAD
00168 : DM_DEVICE_CREATE)))
00169 goto out;
00170 if (!dm_task_set_name(dmt, options->name))
00171 goto out;
00172 if (options->flags & CRYPT_FLAG_READONLY && !dm_task_set_ro(dmt))
00173 goto out;
00174 if (!dm_task_add_target(dmt, 0, options->size, CRYPT_TARGET, params))
00175 goto out;
00176 if (!dm_task_run(dmt))
00177 goto out;
00178
00179 if (reload) {
00180 dm_task_destroy(dmt);
00181 if (!(dmt = dm_task_create(DM_DEVICE_RESUME)))
00182 goto out;
00183 if (!dm_task_set_name(dmt, options->name))
00184 goto out;
00185 if (!dm_task_run(dmt))
00186 goto out;
00187 }
00188
00189 if (!dm_task_get_info(dmt, &dmi))
00190 goto out;
00191 if (dmi.read_only)
00192 options->flags |= CRYPT_FLAG_READONLY;
00193
00194 /* run udevsettle to avoid a race in libdevmapper causing busy dm devices */
00195 run_udevsettle();
00196
00197 r = 0;
00198
00199 out:
00200 if (r < 0 && !reload) {
00201 char *error = (char *)get_error();
00202 if (error)
00203 error = strdup(error);
00204 if (dmt)
00205 dm_task_destroy(dmt);
00206
00207 if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
00208 goto out_restore_error;
00209 if (!dm_task_set_name(dmt, options->name))
00210 goto out_restore_error;
00211 if (!dm_task_run(dmt))
00212 goto out_restore_error;
00213
00214 out_restore_error:
00215 set_error("%s", error);
00216 if (error)
00217 free(error);
00218 }
00219
00220 out_no_removal:
00221 if (params)
00222 safe_free(params);
00223 if (dmt)
00224 dm_task_destroy(dmt);
00225 if(dmt_query)
00226 dm_task_destroy(dmt_query);
00227 flush_dm_workqueue();
00228 return r;
00229 }
00230
00231 static int dm_query_device(int details, struct crypt_options *options,
00232 char **key)
00233 {
00234 struct dm_task *dmt;
00235 struct dm_info dmi;
00236 uint64_t start, length;
00237 char *target_type, *params;
00238 void *next = NULL;
00239 int r = -EINVAL;
00240
00241 if (!(dmt = dm_task_create(details ? DM_DEVICE_TABLE
00242 : DM_DEVICE_STATUS)))
00243 goto out;
00244 if (!dm_task_set_name(dmt, options->name))
00245 goto out;
00246 r = -ENODEV;
00247 if (!dm_task_run(dmt))
00248 goto out;
00249
00250 r = -EINVAL;
00251 if (!dm_task_get_info(dmt, &dmi))
00252 goto out;
00253
00254 if (!dmi.exists) {
00255 r = -ENODEV;
00256 goto out;
00257 }
00258
00259 next = dm_get_next_target(dmt, next, &start, &length,
00260 &target_type, ¶ms);
00261 if (!target_type || strcmp(target_type, CRYPT_TARGET) != 0 ||
00262 start != 0 || next)
00263 goto out;
00264
00265 options->hash = NULL;
00266 options->cipher = NULL;
00267 options->offset = 0;
00268 options->skip = 0;
00269 options->size = length;
00270 if (details) {
00271 char *cipher, *key_, *device;
00272 uint64_t val64;
00273
00274 set_error("Invalid dm table");
00275
00276 cipher = strsep(¶ms, " ");
00277 key_ = strsep(¶ms, " ");
00278 if (!params)
00279 goto out;
00280
00281 val64 = strtoull(params, ¶ms, 10);
00282 if (*params != ' ')
00283 goto out;
00284 params++;
00285 options->skip = val64;
00286
00287 device = strsep(¶ms, " ");
00288 if (!params)
00289 goto out;
00290
00291 val64 = strtoull(params, ¶ms, 10);
00292 if (*params)
00293 goto out;
00294 options->offset = val64;
00295
00296 options->cipher = strdup(cipher);
00297 options->key_size = strlen(key_) / 2;
00298 if (key) {
00299 char buffer[3];
00300 char *endp;
00301 int i;
00302
00303 *key = safe_alloc(options->key_size);
00304 if (!*key) {
00305 set_error("Out of memory");
00306 r = -ENOMEM;
00307 goto out;
00308 }
00309
00310 buffer[2] = '\0';
00311 for(i = 0; i < options->key_size; i++) {
00312 memcpy(buffer, &key_[i * 2], 2);
00313 (*key)[i] = strtoul(buffer, &endp, 16);
00314 if (endp != &buffer[2]) {
00315 safe_free(key);
00316 *key = NULL;
00317 goto out;
00318 }
00319 }
00320 }
00321 memset(key_, 0, strlen(key_));
00322 options->device = lookup_dev(device);
00323
00324 set_error(NULL);
00325 }
00326
00327 r = (dmi.open_count > 0);
00328
00329 out:
00330 if (dmt)
00331 dm_task_destroy(dmt);
00332 if (r >= 0) {
00333 if (options->device)
00334 options->flags |= CRYPT_FLAG_FREE_DEVICE;
00335 if (options->cipher)
00336 options->flags |= CRYPT_FLAG_FREE_CIPHER;
00337 options->flags &= ~CRYPT_FLAG_READONLY;
00338 if (dmi.read_only)
00339 options->flags |= CRYPT_FLAG_READONLY;
00340 } else {
00341 if (options->device) {
00342 free((char *)options->device);
00343 options->device = NULL;
00344 options->flags &= ~CRYPT_FLAG_FREE_DEVICE;
00345 }
00346 if (options->cipher) {
00347 free((char *)options->cipher);
00348 options->cipher = NULL;
00349 options->flags &= ~CRYPT_FLAG_FREE_CIPHER;
00350 }
00351 }
00352 return r;
00353 }
00354
00355 static int dm_remove_device(struct crypt_options *options)
00356 {
00357 struct dm_task *dmt;
00358 int r = -EINVAL;
00359
00360 if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
00361 goto out;
00362 if (!dm_task_set_name(dmt, options->name))
00363 goto out;
00364 if (!dm_task_run(dmt))
00365 goto out;
00366
00367 r = 0;
00368
00369 out:
00370 if (dmt)
00371 dm_task_destroy(dmt);
00372 flush_dm_workqueue();
00373 return r;
00374 }
00375
00376
00377 static const char *dm_get_dir(void)
00378 {
00379 return dm_dir();
00380 }
00381
00382 struct setup_backend setup_libdevmapper_backend = {
00383 .name = "dm-crypt",
00384 .init = dm_init,
00385 .exit = dm_exit,
00386 .create = dm_create_device,
00387 .status = dm_query_device,
00388 .remove = dm_remove_device,
00389 .dir = dm_get_dir
00390 };
Generated by Doxygen 1.5.1
Powered by
Google Project Hosting