7ebc5b6239210d4b6fcacb3f28ce9225d2999566
[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
16 extern int
17 dm_prereq (char * str, int x, int y, int z)
18 {
19         int r = 1;
20         struct dm_task *dmt;
21         struct dm_versions *target;
22         struct dm_versions *last_target;
23
24         if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
25                 return 1;
26
27         dm_task_no_open_count(dmt);
28
29         if (!dm_task_run(dmt))
30                 goto out;
31
32         target = dm_task_get_versions(dmt);
33
34         /* Fetch targets and print 'em */
35         do {
36                 last_target = target;
37
38                 if (!strncmp(str, target->name, strlen(str)) &&
39                     /* dummy prereq on multipath version */
40                     target->version[0] >= x &&
41                     target->version[1] >= y &&
42                     target->version[2] >= z
43                    )
44                         r = 0;
45
46                 target = (void *) target + target->next;
47         } while (last_target != target);
48
49         out:
50         dm_task_destroy(dmt);
51         return r;
52 }
53
54 extern int
55 dm_simplecmd (int task, const char *name, int no_flush, uint32_t *cookie) {
56         int r = 0;
57         int udev_wait_flag = (task == DM_DEVICE_RESUME ||
58                               task == DM_DEVICE_REMOVE);
59         struct dm_task *dmt;
60
61         if (!(dmt = dm_task_create(task)))
62                 return 0;
63
64         if (!dm_task_set_name(dmt, name))
65                 goto out;
66
67         dm_task_no_open_count(dmt);
68         dm_task_skip_lockfs(dmt);
69
70         if (no_flush)
71                 dm_task_no_flush(dmt);
72
73         if (udev_wait_flag && !dm_task_set_cookie(dmt, cookie, 0))
74                 goto out;
75         r = dm_task_run(dmt);
76
77         out:
78         dm_task_destroy(dmt);
79         return r;
80 }
81
82 extern int
83 dm_addmap (int task, const char *name, const char *target,
84            const char *params, uint64_t size, int ro, const char *uuid, int part,
85            mode_t mode, uid_t uid, gid_t gid, uint32_t *cookie) {
86         int r = 0;
87         struct dm_task *dmt;
88         char *prefixed_uuid = NULL;
89
90         if (!(dmt = dm_task_create (task)))
91                 return 0;
92
93         if (!dm_task_set_name (dmt, name))
94                 goto addout;
95
96         if (!dm_task_add_target (dmt, 0, size, target, params))
97                 goto addout;
98
99         if (ro && !dm_task_set_ro (dmt))
100                         goto addout;
101
102         if (task == DM_DEVICE_CREATE && uuid) {
103                 prefixed_uuid = malloc(MAX_PREFIX_LEN + strlen(uuid) + 1);
104                 if (!prefixed_uuid) {
105                         fprintf(stderr, "cannot create prefixed uuid : %s\n",
106                                 strerror(errno));
107                         goto addout;
108                 }
109                 sprintf(prefixed_uuid, UUID_PREFIX "%s", part, uuid);
110                 if (!dm_task_set_uuid(dmt, prefixed_uuid))
111                         goto addout;
112         }
113
114         if (!dm_task_set_mode(dmt, mode))
115                 goto addout;
116         if (!dm_task_set_uid(dmt, uid))
117                 goto addout;
118         if (!dm_task_set_gid(dmt, gid))
119                 goto addout;
120
121         dm_task_no_open_count(dmt);
122
123         if (task == DM_DEVICE_CREATE && !dm_task_set_cookie(dmt, cookie, 0))
124                 goto addout;
125         r = dm_task_run (dmt);
126
127         addout:
128         dm_task_destroy (dmt);
129
130         return r;
131 }
132
133 extern int
134 dm_map_present (char * str)
135 {
136         int r = 0;
137         struct dm_task *dmt;
138         struct dm_info info;
139
140         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
141                 return 0;
142
143         if (!dm_task_set_name(dmt, str))
144                 goto out;
145
146         dm_task_no_open_count(dmt);
147
148         if (!dm_task_run(dmt))
149                 goto out;
150
151         if (!dm_task_get_info(dmt, &info))
152                 goto out;
153
154         if (info.exists)
155                 r = 1;
156 out:
157         dm_task_destroy(dmt);
158         return r;
159 }
160
161
162 char *
163 dm_mapname(int major, int minor)
164 {
165         struct dm_task *dmt;
166         char *mapname = NULL;
167         const char *map;
168
169         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
170                 return NULL;
171
172         dm_task_no_open_count(dmt);
173         dm_task_set_major(dmt, major);
174         dm_task_set_minor(dmt, minor);
175
176         if (!dm_task_run(dmt))
177                 goto out;
178
179         map = dm_task_get_name(dmt);
180         if (map && strlen(map))
181                 mapname = strdup(map);
182
183 out:
184         dm_task_destroy(dmt);
185         return mapname;
186 }
187
188 /*
189  * dm_get_first_dep
190  *
191  * Return the device number of the first dependend device
192  * for a given target.
193  */
194 dev_t dm_get_first_dep(char *devname)
195 {
196         struct dm_task *dmt;
197         struct dm_deps *dm_deps;
198         dev_t ret = 0;
199
200         if ((dmt = dm_task_create(DM_DEVICE_DEPS)) == NULL) {
201                 return ret;
202         }
203         if (!dm_task_set_name(dmt, devname)) {
204                 goto out;
205         }
206         if (!dm_task_run(dmt)) {
207                 goto out;
208         }
209         if ((dm_deps = dm_task_get_deps(dmt)) == NULL) {
210                 goto out;
211         }
212         if (dm_deps->count > 0) {
213                 ret = dm_deps->device[0];
214         }
215 out:
216         dm_task_destroy(dmt);
217
218         return ret;
219 }
220
221 char *
222 dm_mapuuid(int major, int minor)
223 {
224         struct dm_task *dmt;
225         const char *tmp;
226         char *uuid = NULL;
227
228         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
229                 return NULL;
230
231         dm_task_no_open_count(dmt);
232         dm_task_set_major(dmt, major);
233         dm_task_set_minor(dmt, minor);
234
235         if (!dm_task_run(dmt))
236                 goto out;
237
238         tmp = dm_task_get_uuid(dmt);
239         if (tmp[0] != '\0')
240                 uuid = strdup(tmp);
241 out:
242         dm_task_destroy(dmt);
243         return uuid;
244 }
245
246 int
247 dm_devn (char * mapname, int *major, int *minor)
248 {
249         int r = 1;
250         struct dm_task *dmt;
251         struct dm_info info;
252
253         if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
254                 return 0;
255
256         if (!dm_task_set_name(dmt, mapname))
257                 goto out;
258
259         if (!dm_task_run(dmt))
260                 goto out;
261
262         if (!dm_task_get_info(dmt, &info))
263                 goto out;
264
265         *major = info.major;
266         *minor = info.minor;
267
268         r = 0;
269 out:
270         dm_task_destroy(dmt);
271         return r;
272 }
273