Imported Upstream version 0.6.3
[platform/upstream/multipath-tools.git] / kpartx / devmapper.c
1 /*
2  * Copyright (c) 2004, 2005 Christophe Varoqui
3  */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <stdint.h>
8 #include <libdevmapper.h>
9 #include <ctype.h>
10 #include <errno.h>
11 #include "devmapper.h"
12
13 #define UUID_PREFIX "part%d-"
14 #define MAX_PREFIX_LEN 8
15 #define PARAMS_SIZE 1024
16
17 extern int
18 dm_prereq (char * str, int x, int y, int z)
19 {
20         int r = 1;
21         struct dm_task *dmt;
22         struct dm_versions *target;
23         struct dm_versions *last_target;
24
25         if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
26                 return 1;
27
28         dm_task_no_open_count(dmt);
29
30         if (!dm_task_run(dmt))
31                 goto out;
32
33         target = dm_task_get_versions(dmt);
34
35         /* Fetch targets and print 'em */
36         do {
37                 last_target = target;
38
39                 if (!strncmp(str, target->name, strlen(str)) &&
40                     /* dummy prereq on multipath version */
41                     target->version[0] >= x &&
42                     target->version[1] >= y &&
43                     target->version[2] >= z
44                    )
45                         r = 0;
46
47                 target = (void *) target + target->next;
48         } while (last_target != target);
49
50 out:
51         dm_task_destroy(dmt);
52         return r;
53 }
54
55 extern int
56 dm_simplecmd (int task, const char *name, int no_flush, uint16_t udev_flags) {
57         int r = 0;
58         int udev_wait_flag = (task == DM_DEVICE_RESUME ||
59                               task == DM_DEVICE_REMOVE);
60 #ifdef LIBDM_API_COOKIE
61         uint32_t cookie = 0;
62 #endif
63         struct dm_task *dmt;
64
65         if (!(dmt = dm_task_create(task)))
66                 return 0;
67
68         if (!dm_task_set_name(dmt, name))
69                 goto out;
70
71         dm_task_no_open_count(dmt);
72         dm_task_skip_lockfs(dmt);
73
74         if (no_flush)
75                 dm_task_no_flush(dmt);
76
77 #ifdef LIBDM_API_COOKIE
78         if (!udev_sync)
79                 udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
80         if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, udev_flags))
81                 goto out;
82 #endif
83         r = dm_task_run(dmt);
84 #ifdef LIBDM_API_COOKIE
85         if (udev_wait_flag)
86                         dm_udev_wait(cookie);
87 #endif
88 out:
89         dm_task_destroy(dmt);
90         return r;
91 }
92
93 extern int
94 dm_addmap (int task, const char *name, const char *target,
95            const char *params, uint64_t size, int ro, const char *uuid, int part,
96            mode_t mode, uid_t uid, gid_t gid) {
97         int r = 0;
98         struct dm_task *dmt;
99         char *prefixed_uuid = NULL;
100 #ifdef LIBDM_API_COOKIE
101         uint32_t cookie = 0;
102         uint16_t udev_flags = 0;
103 #endif
104
105         if (!(dmt = dm_task_create (task)))
106                 return 0;
107
108         if (!dm_task_set_name (dmt, name))
109                 goto addout;
110
111         if (!dm_task_add_target (dmt, 0, size, target, params))
112                 goto addout;
113
114         if (ro && !dm_task_set_ro (dmt))
115                         goto addout;
116
117         if (task == DM_DEVICE_CREATE && uuid) {
118                 prefixed_uuid = malloc(MAX_PREFIX_LEN + strlen(uuid) + 1);
119                 if (!prefixed_uuid) {
120                         fprintf(stderr, "cannot create prefixed uuid : %s\n",
121                                 strerror(errno));
122                         goto addout;
123                 }
124                 sprintf(prefixed_uuid, UUID_PREFIX "%s", part, uuid);
125                 if (!dm_task_set_uuid(dmt, prefixed_uuid))
126                         goto addout;
127         }
128
129         if (!dm_task_set_mode(dmt, mode))
130                 goto addout;
131         if (!dm_task_set_uid(dmt, uid))
132                 goto addout;
133         if (!dm_task_set_gid(dmt, gid))
134                 goto addout;
135
136         dm_task_no_open_count(dmt);
137
138 #ifdef LIBDM_API_COOKIE
139         if (!udev_sync)
140                 udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK;
141         if (task == DM_DEVICE_CREATE &&
142             !dm_task_set_cookie(dmt, &cookie, udev_flags))
143                 goto addout;
144 #endif
145         r = dm_task_run (dmt);
146 #ifdef LIBDM_API_COOKIE
147         if (task == DM_DEVICE_CREATE)
148                         dm_udev_wait(cookie);
149 #endif
150 addout:
151         dm_task_destroy (dmt);
152         free(prefixed_uuid);
153
154         return r;
155 }
156
157 extern int
158 dm_map_present (char * str, char **uuid)
159 {
160         int r = 0;
161         struct dm_task *dmt;
162         const char *uuidtmp;
163         struct dm_info info;
164
165         if (uuid)
166                 *uuid = NULL;
167
168         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
169                 return 0;
170
171         if (!dm_task_set_name(dmt, str))
172                 goto out;
173
174         dm_task_no_open_count(dmt);
175
176         if (!dm_task_run(dmt))
177                 goto out;
178
179         if (!dm_task_get_info(dmt, &info))
180                 goto out;
181
182         if (!info.exists)
183                 goto out;
184
185         r = 1;
186         if (uuid) {
187                 uuidtmp = dm_task_get_uuid(dmt);
188                 if (uuidtmp && strlen(uuidtmp))
189                         *uuid = strdup(uuidtmp);
190         }
191 out:
192         dm_task_destroy(dmt);
193         return r;
194 }
195
196
197 char *
198 dm_mapname(int major, int minor)
199 {
200         struct dm_task *dmt;
201         char *mapname = NULL;
202         const char *map;
203
204         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
205                 return NULL;
206
207         dm_task_no_open_count(dmt);
208         dm_task_set_major(dmt, major);
209         dm_task_set_minor(dmt, minor);
210
211         if (!dm_task_run(dmt))
212                 goto out;
213
214         map = dm_task_get_name(dmt);
215         if (map && strlen(map))
216                 mapname = strdup(map);
217
218 out:
219         dm_task_destroy(dmt);
220         return mapname;
221 }
222
223 /*
224  * dm_get_first_dep
225  *
226  * Return the device number of the first dependend device
227  * for a given target.
228  */
229 dev_t dm_get_first_dep(char *devname)
230 {
231         struct dm_task *dmt;
232         struct dm_deps *dm_deps;
233         dev_t ret = 0;
234
235         if ((dmt = dm_task_create(DM_DEVICE_DEPS)) == NULL) {
236                 return ret;
237         }
238         if (!dm_task_set_name(dmt, devname)) {
239                 goto out;
240         }
241         if (!dm_task_run(dmt)) {
242                 goto out;
243         }
244         if ((dm_deps = dm_task_get_deps(dmt)) == NULL) {
245                 goto out;
246         }
247         if (dm_deps->count > 0) {
248                 ret = dm_deps->device[0];
249         }
250 out:
251         dm_task_destroy(dmt);
252
253         return ret;
254 }
255
256 char *
257 dm_mapuuid(int major, int minor)
258 {
259         struct dm_task *dmt;
260         const char *tmp;
261         char *uuid = NULL;
262
263         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
264                 return NULL;
265
266         dm_task_no_open_count(dmt);
267         dm_task_set_major(dmt, major);
268         dm_task_set_minor(dmt, minor);
269
270         if (!dm_task_run(dmt))
271                 goto out;
272
273         tmp = dm_task_get_uuid(dmt);
274         if (tmp[0] != '\0')
275                 uuid = strdup(tmp);
276 out:
277         dm_task_destroy(dmt);
278         return uuid;
279 }
280
281 int
282 dm_devn (char * mapname, int *major, int *minor)
283 {
284         int r = 1;
285         struct dm_task *dmt;
286         struct dm_info info;
287
288         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
289                 return 0;
290
291         if (!dm_task_set_name(dmt, mapname))
292                 goto out;
293
294         if (!dm_task_run(dmt))
295                 goto out;
296
297         if (!dm_task_get_info(dmt, &info))
298                 goto out;
299
300         *major = info.major;
301         *minor = info.minor;
302
303         r = 0;
304 out:
305         dm_task_destroy(dmt);
306         return r;
307 }
308
309 int
310 dm_get_map(int major, int minor, char * outparams)
311 {
312         int r = 1;
313         struct dm_task *dmt;
314         uint64_t start, length;
315         char *target_type = NULL;
316         char *params = NULL;
317
318         if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
319                 return 1;
320
321         dm_task_set_major(dmt, major);
322         dm_task_set_minor(dmt, minor);
323         dm_task_no_open_count(dmt);
324
325         if (!dm_task_run(dmt))
326                 goto out;
327
328         /* Fetch 1st target */
329         dm_get_next_target(dmt, NULL, &start, &length,
330                            &target_type, &params);
331
332         if (snprintf(outparams, PARAMS_SIZE, "%s", params) <= PARAMS_SIZE)
333                 r = 0;
334 out:
335         dm_task_destroy(dmt);
336         return r;
337 }
338
339 #define FEATURE_NO_PART "no_partitions"
340
341 int
342 dm_no_partitions(int major, int minor)
343 {
344         char params[PARAMS_SIZE], *ptr;
345         int i, num_features;
346
347         if (dm_get_map(major, minor, params))
348                 return 0;
349
350         ptr = params;
351         num_features = strtoul(params, &ptr, 10);
352         if ((ptr == params) || num_features == 0) {
353                 /* No features found, return success */
354                 return 0;
355         }
356         for (i = 0; (i < num_features); i++) {
357                 if (!ptr || ptr > params + strlen(params))
358                         break;
359                 /* Skip whitespaces */
360                 while(ptr && *ptr == ' ') ptr++;
361                 if (!strncmp(ptr, FEATURE_NO_PART, strlen(FEATURE_NO_PART)))
362                         return 1;
363                 ptr = strchr(ptr, ' ');
364         }
365         return 0;
366 }