Statistics
| Branch: | Revision:

root / vhd / lib / vhd-util-scan.c @ abdb293f

History | View | Annotate | Download (27.6 kB)

1 abdb293f Chrysostomos Nanakos
/*
2 abdb293f Chrysostomos Nanakos
 * Copyright (c) 2007, XenSource Inc.
3 abdb293f Chrysostomos Nanakos
 * Copyright (c) 2010, Citrix Systems, Inc.
4 abdb293f Chrysostomos Nanakos
 *
5 abdb293f Chrysostomos Nanakos
 * All rights reserved.
6 abdb293f Chrysostomos Nanakos
 *
7 abdb293f Chrysostomos Nanakos
 * Redistribution and use in source and binary forms, with or without
8 abdb293f Chrysostomos Nanakos
 * modification, are permitted provided that the following conditions are met:
9 abdb293f Chrysostomos Nanakos
 *     * Redistributions of source code must retain the above copyright
10 abdb293f Chrysostomos Nanakos
 *       notice, this list of conditions and the following disclaimer.
11 abdb293f Chrysostomos Nanakos
 *     * Redistributions in binary form must reproduce the above copyright
12 abdb293f Chrysostomos Nanakos
 *       notice, this list of conditions and the following disclaimer in the
13 abdb293f Chrysostomos Nanakos
 *       documentation and/or other materials provided with the distribution.
14 abdb293f Chrysostomos Nanakos
 *     * Neither the name of XenSource Inc. nor the names of its contributors
15 abdb293f Chrysostomos Nanakos
 *       may be used to endorse or promote products derived from this software
16 abdb293f Chrysostomos Nanakos
 *       without specific prior written permission.
17 abdb293f Chrysostomos Nanakos
 *
18 abdb293f Chrysostomos Nanakos
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 abdb293f Chrysostomos Nanakos
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 abdb293f Chrysostomos Nanakos
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 abdb293f Chrysostomos Nanakos
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
22 abdb293f Chrysostomos Nanakos
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 abdb293f Chrysostomos Nanakos
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 abdb293f Chrysostomos Nanakos
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 abdb293f Chrysostomos Nanakos
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 abdb293f Chrysostomos Nanakos
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 abdb293f Chrysostomos Nanakos
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 abdb293f Chrysostomos Nanakos
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 abdb293f Chrysostomos Nanakos
 */
30 abdb293f Chrysostomos Nanakos
31 abdb293f Chrysostomos Nanakos
#ifdef HAVE_CONFIG_H
32 abdb293f Chrysostomos Nanakos
#include "config.h"
33 abdb293f Chrysostomos Nanakos
#endif
34 abdb293f Chrysostomos Nanakos
35 abdb293f Chrysostomos Nanakos
#include <glob.h>
36 abdb293f Chrysostomos Nanakos
#include <errno.h>
37 abdb293f Chrysostomos Nanakos
#include <fcntl.h>
38 abdb293f Chrysostomos Nanakos
#include <stdio.h>
39 abdb293f Chrysostomos Nanakos
#include <string.h>
40 abdb293f Chrysostomos Nanakos
#include <stdlib.h>
41 abdb293f Chrysostomos Nanakos
#include <unistd.h>
42 abdb293f Chrysostomos Nanakos
#include <fnmatch.h>
43 abdb293f Chrysostomos Nanakos
#include <limits.h>
44 abdb293f Chrysostomos Nanakos
#include <libgen.h>
45 abdb293f Chrysostomos Nanakos
#include <syslog.h>
46 abdb293f Chrysostomos Nanakos
#include <sys/stat.h>
47 abdb293f Chrysostomos Nanakos
#include <sys/types.h>
48 abdb293f Chrysostomos Nanakos
49 abdb293f Chrysostomos Nanakos
#include "list.h"
50 abdb293f Chrysostomos Nanakos
#include "libvhd.h"
51 abdb293f Chrysostomos Nanakos
#include "lvm-util.h"
52 abdb293f Chrysostomos Nanakos
53 abdb293f Chrysostomos Nanakos
#define VHD_SCAN_FAST        0x01
54 abdb293f Chrysostomos Nanakos
#define VHD_SCAN_PRETTY      0x02
55 abdb293f Chrysostomos Nanakos
#define VHD_SCAN_VOLUME      0x04
56 abdb293f Chrysostomos Nanakos
#define VHD_SCAN_NOFAIL      0x08
57 abdb293f Chrysostomos Nanakos
#define VHD_SCAN_VERBOSE     0x10
58 abdb293f Chrysostomos Nanakos
#define VHD_SCAN_PARENTS     0x20
59 abdb293f Chrysostomos Nanakos
#define VHD_SCAN_MARKERS     0x40
60 abdb293f Chrysostomos Nanakos
61 abdb293f Chrysostomos Nanakos
#define VHD_TYPE_RAW_FILE    0x01
62 abdb293f Chrysostomos Nanakos
#define VHD_TYPE_VHD_FILE    0x02
63 abdb293f Chrysostomos Nanakos
#define VHD_TYPE_RAW_VOLUME  0x04
64 abdb293f Chrysostomos Nanakos
#define VHD_TYPE_VHD_VOLUME  0x08
65 abdb293f Chrysostomos Nanakos
66 abdb293f Chrysostomos Nanakos
#define EPRINTF(_f, _a...)                                        \
67 abdb293f Chrysostomos Nanakos
        do {                                                        \
68 abdb293f Chrysostomos Nanakos
                syslog(LOG_INFO, "%s: " _f, __func__, ##_a);        \
69 abdb293f Chrysostomos Nanakos
        } while (0)
70 abdb293f Chrysostomos Nanakos
71 abdb293f Chrysostomos Nanakos
static inline int
72 abdb293f Chrysostomos Nanakos
target_volume(uint8_t type)
73 abdb293f Chrysostomos Nanakos
{
74 abdb293f Chrysostomos Nanakos
        return (type == VHD_TYPE_RAW_VOLUME || type == VHD_TYPE_VHD_VOLUME);
75 abdb293f Chrysostomos Nanakos
}
76 abdb293f Chrysostomos Nanakos
77 abdb293f Chrysostomos Nanakos
static inline int
78 abdb293f Chrysostomos Nanakos
target_vhd(uint8_t type)
79 abdb293f Chrysostomos Nanakos
{
80 abdb293f Chrysostomos Nanakos
        return (type == VHD_TYPE_VHD_FILE || type == VHD_TYPE_VHD_VOLUME);
81 abdb293f Chrysostomos Nanakos
}
82 abdb293f Chrysostomos Nanakos
83 abdb293f Chrysostomos Nanakos
struct target {
84 abdb293f Chrysostomos Nanakos
        char                 name[VHD_MAX_NAME_LEN];
85 abdb293f Chrysostomos Nanakos
        char                 device[VHD_MAX_NAME_LEN];
86 abdb293f Chrysostomos Nanakos
        uint64_t             size;
87 abdb293f Chrysostomos Nanakos
        uint64_t             start;
88 abdb293f Chrysostomos Nanakos
        uint64_t             end;
89 abdb293f Chrysostomos Nanakos
        uint8_t              type;
90 abdb293f Chrysostomos Nanakos
};
91 abdb293f Chrysostomos Nanakos
92 abdb293f Chrysostomos Nanakos
struct iterator {
93 abdb293f Chrysostomos Nanakos
        int                  cur;
94 abdb293f Chrysostomos Nanakos
        int                  cur_size;
95 abdb293f Chrysostomos Nanakos
        int                  max_size;
96 abdb293f Chrysostomos Nanakos
        struct target       *targets;
97 abdb293f Chrysostomos Nanakos
};
98 abdb293f Chrysostomos Nanakos
99 abdb293f Chrysostomos Nanakos
struct vhd_image {
100 abdb293f Chrysostomos Nanakos
        char                *name;
101 abdb293f Chrysostomos Nanakos
        char                *parent;
102 abdb293f Chrysostomos Nanakos
        uint64_t             capacity;
103 abdb293f Chrysostomos Nanakos
        off64_t              size;
104 abdb293f Chrysostomos Nanakos
        uint8_t              hidden;
105 abdb293f Chrysostomos Nanakos
        char                 marker;
106 abdb293f Chrysostomos Nanakos
        int                  error;
107 abdb293f Chrysostomos Nanakos
        char                *message;
108 abdb293f Chrysostomos Nanakos
109 abdb293f Chrysostomos Nanakos
        struct target       *target;
110 abdb293f Chrysostomos Nanakos
111 abdb293f Chrysostomos Nanakos
        struct list_head     sibling;
112 abdb293f Chrysostomos Nanakos
        struct list_head     children;
113 abdb293f Chrysostomos Nanakos
        struct vhd_image    *parent_image;
114 abdb293f Chrysostomos Nanakos
};
115 abdb293f Chrysostomos Nanakos
116 abdb293f Chrysostomos Nanakos
struct vhd_scan {
117 abdb293f Chrysostomos Nanakos
        int                  cur;
118 abdb293f Chrysostomos Nanakos
        int                  size;
119 abdb293f Chrysostomos Nanakos
120 abdb293f Chrysostomos Nanakos
        int                  lists_cur;
121 abdb293f Chrysostomos Nanakos
        int                  lists_size;
122 abdb293f Chrysostomos Nanakos
123 abdb293f Chrysostomos Nanakos
        struct vhd_image   **images;
124 abdb293f Chrysostomos Nanakos
        struct vhd_image   **lists;
125 abdb293f Chrysostomos Nanakos
};
126 abdb293f Chrysostomos Nanakos
127 abdb293f Chrysostomos Nanakos
static int flags;
128 abdb293f Chrysostomos Nanakos
static struct vg vg;
129 abdb293f Chrysostomos Nanakos
static struct vhd_scan scan;
130 abdb293f Chrysostomos Nanakos
131 abdb293f Chrysostomos Nanakos
static int
132 abdb293f Chrysostomos Nanakos
vhd_util_scan_pretty_allocate_list(int cnt)
133 abdb293f Chrysostomos Nanakos
{
134 abdb293f Chrysostomos Nanakos
        int i;
135 abdb293f Chrysostomos Nanakos
136 abdb293f Chrysostomos Nanakos
        memset(&scan, 0, sizeof(scan));
137 abdb293f Chrysostomos Nanakos
138 abdb293f Chrysostomos Nanakos
        scan.lists_cur  = 1;
139 abdb293f Chrysostomos Nanakos
        scan.lists_size = 10;
140 abdb293f Chrysostomos Nanakos
141 abdb293f Chrysostomos Nanakos
        scan.lists = calloc(scan.lists_size, sizeof(struct vhd_image *));
142 abdb293f Chrysostomos Nanakos
        if (!scan.lists)
143 abdb293f Chrysostomos Nanakos
                goto fail;
144 abdb293f Chrysostomos Nanakos
145 abdb293f Chrysostomos Nanakos
        scan.lists[0] = calloc(cnt, sizeof(struct vhd_image));
146 abdb293f Chrysostomos Nanakos
        if (!scan.lists[0])
147 abdb293f Chrysostomos Nanakos
                goto fail;
148 abdb293f Chrysostomos Nanakos
149 abdb293f Chrysostomos Nanakos
        scan.images = calloc(cnt, sizeof(struct vhd_image *));
150 abdb293f Chrysostomos Nanakos
        if (!scan.images)
151 abdb293f Chrysostomos Nanakos
                goto fail;
152 abdb293f Chrysostomos Nanakos
153 abdb293f Chrysostomos Nanakos
        for (i = 0; i < cnt; i++)
154 abdb293f Chrysostomos Nanakos
                scan.images[i] = scan.lists[0] + i;
155 abdb293f Chrysostomos Nanakos
156 abdb293f Chrysostomos Nanakos
        scan.cur  = 0;
157 abdb293f Chrysostomos Nanakos
        scan.size = cnt;
158 abdb293f Chrysostomos Nanakos
159 abdb293f Chrysostomos Nanakos
        return 0;
160 abdb293f Chrysostomos Nanakos
161 abdb293f Chrysostomos Nanakos
fail:
162 abdb293f Chrysostomos Nanakos
        if (scan.lists) {
163 abdb293f Chrysostomos Nanakos
                free(scan.lists[0]);
164 abdb293f Chrysostomos Nanakos
                free(scan.lists);
165 abdb293f Chrysostomos Nanakos
        }
166 abdb293f Chrysostomos Nanakos
167 abdb293f Chrysostomos Nanakos
        free(scan.images);
168 abdb293f Chrysostomos Nanakos
        memset(&scan, 0, sizeof(scan));
169 abdb293f Chrysostomos Nanakos
        return -ENOMEM;
170 abdb293f Chrysostomos Nanakos
}
171 abdb293f Chrysostomos Nanakos
172 abdb293f Chrysostomos Nanakos
static void
173 abdb293f Chrysostomos Nanakos
vhd_util_scan_pretty_free_list(void)
174 abdb293f Chrysostomos Nanakos
{
175 abdb293f Chrysostomos Nanakos
        int i;
176 abdb293f Chrysostomos Nanakos
177 abdb293f Chrysostomos Nanakos
        if (scan.lists) {
178 abdb293f Chrysostomos Nanakos
                for (i = 0; i < scan.lists_cur; i++)
179 abdb293f Chrysostomos Nanakos
                        free(scan.lists[i]);
180 abdb293f Chrysostomos Nanakos
                free(scan.lists);
181 abdb293f Chrysostomos Nanakos
        }
182 abdb293f Chrysostomos Nanakos
183 abdb293f Chrysostomos Nanakos
        free(scan.images);
184 abdb293f Chrysostomos Nanakos
        memset(&scan, 0, sizeof(scan));
185 abdb293f Chrysostomos Nanakos
}
186 abdb293f Chrysostomos Nanakos
187 abdb293f Chrysostomos Nanakos
static int
188 abdb293f Chrysostomos Nanakos
vhd_util_scan_pretty_add_image(struct vhd_image *image)
189 abdb293f Chrysostomos Nanakos
{
190 abdb293f Chrysostomos Nanakos
        int i;
191 abdb293f Chrysostomos Nanakos
        struct vhd_image *img;
192 abdb293f Chrysostomos Nanakos
193 abdb293f Chrysostomos Nanakos
        for (i = 0; i < scan.cur; i++) {
194 abdb293f Chrysostomos Nanakos
                img = scan.images[i];
195 abdb293f Chrysostomos Nanakos
                if (!strcmp(img->name, image->name))
196 abdb293f Chrysostomos Nanakos
                        return 0;
197 abdb293f Chrysostomos Nanakos
        }
198 abdb293f Chrysostomos Nanakos
199 abdb293f Chrysostomos Nanakos
        if (scan.cur >= scan.size) {
200 abdb293f Chrysostomos Nanakos
                struct vhd_image *new, **list;
201 abdb293f Chrysostomos Nanakos
202 abdb293f Chrysostomos Nanakos
                if (scan.lists_cur >= scan.lists_size) {
203 abdb293f Chrysostomos Nanakos
                        list = realloc(scan.lists, scan.lists_size * 2 *
204 abdb293f Chrysostomos Nanakos
                                       sizeof(struct vhd_image *));
205 abdb293f Chrysostomos Nanakos
                        if (!list)
206 abdb293f Chrysostomos Nanakos
                                return -ENOMEM;
207 abdb293f Chrysostomos Nanakos
208 abdb293f Chrysostomos Nanakos
                        scan.lists_size *= 2;
209 abdb293f Chrysostomos Nanakos
                        scan.lists       = list;
210 abdb293f Chrysostomos Nanakos
                }
211 abdb293f Chrysostomos Nanakos
212 abdb293f Chrysostomos Nanakos
                new = calloc(scan.size, sizeof(struct vhd_image));
213 abdb293f Chrysostomos Nanakos
                if (!new)
214 abdb293f Chrysostomos Nanakos
                        return -ENOMEM;
215 abdb293f Chrysostomos Nanakos
216 abdb293f Chrysostomos Nanakos
                scan.lists[scan.lists_cur++] = new;
217 abdb293f Chrysostomos Nanakos
                scan.size *= 2;
218 abdb293f Chrysostomos Nanakos
219 abdb293f Chrysostomos Nanakos
                list = realloc(scan.images, scan.size *
220 abdb293f Chrysostomos Nanakos
                               sizeof(struct vhd_image *));
221 abdb293f Chrysostomos Nanakos
                if (!list)
222 abdb293f Chrysostomos Nanakos
                        return -ENOMEM;
223 abdb293f Chrysostomos Nanakos
224 abdb293f Chrysostomos Nanakos
                scan.images = list;
225 abdb293f Chrysostomos Nanakos
                for (i = 0; i + scan.cur < scan.size; i++)
226 abdb293f Chrysostomos Nanakos
                        scan.images[i + scan.cur] = new + i;
227 abdb293f Chrysostomos Nanakos
        }
228 abdb293f Chrysostomos Nanakos
229 abdb293f Chrysostomos Nanakos
        img = scan.images[scan.cur];
230 abdb293f Chrysostomos Nanakos
        INIT_LIST_HEAD(&img->sibling);
231 abdb293f Chrysostomos Nanakos
        INIT_LIST_HEAD(&img->children);
232 abdb293f Chrysostomos Nanakos
233 abdb293f Chrysostomos Nanakos
        img->capacity = image->capacity;
234 abdb293f Chrysostomos Nanakos
        img->size     = image->size;
235 abdb293f Chrysostomos Nanakos
        img->hidden   = image->hidden;
236 abdb293f Chrysostomos Nanakos
        img->marker   = image->marker;
237 abdb293f Chrysostomos Nanakos
        img->error    = image->error;
238 abdb293f Chrysostomos Nanakos
        img->message  = image->message;
239 abdb293f Chrysostomos Nanakos
240 abdb293f Chrysostomos Nanakos
        img->name = strdup(image->name);
241 abdb293f Chrysostomos Nanakos
        if (!img->name)
242 abdb293f Chrysostomos Nanakos
                goto fail;
243 abdb293f Chrysostomos Nanakos
244 abdb293f Chrysostomos Nanakos
        if (image->parent) {
245 abdb293f Chrysostomos Nanakos
                img->parent = strdup(image->parent);
246 abdb293f Chrysostomos Nanakos
                if (!img->parent)
247 abdb293f Chrysostomos Nanakos
                        goto fail;
248 abdb293f Chrysostomos Nanakos
        }
249 abdb293f Chrysostomos Nanakos
250 abdb293f Chrysostomos Nanakos
        scan.cur++;
251 abdb293f Chrysostomos Nanakos
        return 0;
252 abdb293f Chrysostomos Nanakos
253 abdb293f Chrysostomos Nanakos
fail:
254 abdb293f Chrysostomos Nanakos
        free(img->name);
255 abdb293f Chrysostomos Nanakos
        free(img->parent);
256 abdb293f Chrysostomos Nanakos
        memset(img, 0, sizeof(*img));
257 abdb293f Chrysostomos Nanakos
        return -ENOMEM;
258 abdb293f Chrysostomos Nanakos
}
259 abdb293f Chrysostomos Nanakos
260 abdb293f Chrysostomos Nanakos
static int
261 abdb293f Chrysostomos Nanakos
vhd_util_scan_pretty_image_compare(const void *lhs, const void *rhs)
262 abdb293f Chrysostomos Nanakos
{
263 abdb293f Chrysostomos Nanakos
        struct vhd_image *l, *r;
264 abdb293f Chrysostomos Nanakos
265 abdb293f Chrysostomos Nanakos
        l = *(struct vhd_image **)lhs;
266 abdb293f Chrysostomos Nanakos
        r = *(struct vhd_image **)rhs;
267 abdb293f Chrysostomos Nanakos
268 abdb293f Chrysostomos Nanakos
        return strcmp(l->name, r->name);
269 abdb293f Chrysostomos Nanakos
}
270 abdb293f Chrysostomos Nanakos
271 abdb293f Chrysostomos Nanakos
static void
272 abdb293f Chrysostomos Nanakos
vhd_util_scan_print_image_indent(struct vhd_image *image, int tab)
273 abdb293f Chrysostomos Nanakos
{
274 abdb293f Chrysostomos Nanakos
        char *pad, *name, *pmsg, *parent;
275 abdb293f Chrysostomos Nanakos
276 abdb293f Chrysostomos Nanakos
        pad    = (tab ? " " : "");
277 abdb293f Chrysostomos Nanakos
        name   = image->name;
278 abdb293f Chrysostomos Nanakos
        parent = (image->parent ? : "none");
279 abdb293f Chrysostomos Nanakos
280 abdb293f Chrysostomos Nanakos
        if ((flags & VHD_SCAN_PRETTY) && image->parent && !image->parent_image)
281 abdb293f Chrysostomos Nanakos
                pmsg = " (not found in scan)";
282 abdb293f Chrysostomos Nanakos
        else
283 abdb293f Chrysostomos Nanakos
                pmsg = "";
284 abdb293f Chrysostomos Nanakos
285 abdb293f Chrysostomos Nanakos
        if (!(flags & VHD_SCAN_VERBOSE)) {
286 abdb293f Chrysostomos Nanakos
                name = basename(image->name);
287 abdb293f Chrysostomos Nanakos
                if (image->parent)
288 abdb293f Chrysostomos Nanakos
                        parent = basename(image->parent);
289 abdb293f Chrysostomos Nanakos
        }
290 abdb293f Chrysostomos Nanakos
291 abdb293f Chrysostomos Nanakos
        if (image->error)
292 abdb293f Chrysostomos Nanakos
                printf("%*svhd=%s scan-error=%d error-message='%s'\n",
293 abdb293f Chrysostomos Nanakos
                       tab, pad, image->name, image->error, image->message);
294 abdb293f Chrysostomos Nanakos
        else if (!(flags & VHD_SCAN_MARKERS))
295 abdb293f Chrysostomos Nanakos
                printf("%*svhd=%s capacity=%"PRIu64" size=%"PRIu64" hidden=%u "
296 abdb293f Chrysostomos Nanakos
                       "parent=%s%s\n", tab, pad, name, image->capacity,
297 abdb293f Chrysostomos Nanakos
                       image->size, image->hidden, parent, pmsg);
298 abdb293f Chrysostomos Nanakos
        else
299 abdb293f Chrysostomos Nanakos
                printf("%*svhd=%s capacity=%"PRIu64" size=%"PRIu64" hidden=%u "
300 abdb293f Chrysostomos Nanakos
                       "marker=%u parent=%s%s\n", tab, pad, name,
301 abdb293f Chrysostomos Nanakos
                       image->capacity, image->size, image->hidden,
302 abdb293f Chrysostomos Nanakos
                       (uint8_t)image->marker, parent, pmsg);
303 abdb293f Chrysostomos Nanakos
}
304 abdb293f Chrysostomos Nanakos
305 abdb293f Chrysostomos Nanakos
static void
306 abdb293f Chrysostomos Nanakos
vhd_util_scan_pretty_print_tree(struct vhd_image *image, int depth)
307 abdb293f Chrysostomos Nanakos
{
308 abdb293f Chrysostomos Nanakos
        struct vhd_image *img, *tmp;
309 abdb293f Chrysostomos Nanakos
310 abdb293f Chrysostomos Nanakos
        vhd_util_scan_print_image_indent(image, depth * 3);
311 abdb293f Chrysostomos Nanakos
312 abdb293f Chrysostomos Nanakos
        list_for_each_entry_safe(img, tmp, &image->children, sibling)
313 abdb293f Chrysostomos Nanakos
                if (!img->hidden)
314 abdb293f Chrysostomos Nanakos
                        vhd_util_scan_pretty_print_tree(img, depth + 1);
315 abdb293f Chrysostomos Nanakos
316 abdb293f Chrysostomos Nanakos
        list_for_each_entry_safe(img, tmp, &image->children, sibling)
317 abdb293f Chrysostomos Nanakos
                if (img->hidden)
318 abdb293f Chrysostomos Nanakos
                        vhd_util_scan_pretty_print_tree(img, depth + 1);
319 abdb293f Chrysostomos Nanakos
320 abdb293f Chrysostomos Nanakos
        free(image->name);
321 abdb293f Chrysostomos Nanakos
        free(image->parent);
322 abdb293f Chrysostomos Nanakos
323 abdb293f Chrysostomos Nanakos
        image->name   = NULL;
324 abdb293f Chrysostomos Nanakos
        image->parent = NULL;
325 abdb293f Chrysostomos Nanakos
}
326 abdb293f Chrysostomos Nanakos
327 abdb293f Chrysostomos Nanakos
static void
328 abdb293f Chrysostomos Nanakos
vhd_util_scan_pretty_print_images(void)
329 abdb293f Chrysostomos Nanakos
{
330 abdb293f Chrysostomos Nanakos
        int i;
331 abdb293f Chrysostomos Nanakos
        struct vhd_image *image, **parentp, *parent, *keyp, key;
332 abdb293f Chrysostomos Nanakos
333 abdb293f Chrysostomos Nanakos
        qsort(scan.images, scan.cur, sizeof(scan.images[0]),
334 abdb293f Chrysostomos Nanakos
              vhd_util_scan_pretty_image_compare);
335 abdb293f Chrysostomos Nanakos
336 abdb293f Chrysostomos Nanakos
        for (i = 0; i < scan.cur; i++) {
337 abdb293f Chrysostomos Nanakos
                image = scan.images[i];
338 abdb293f Chrysostomos Nanakos
339 abdb293f Chrysostomos Nanakos
                if (!image->parent) {
340 abdb293f Chrysostomos Nanakos
                        image->parent_image = NULL;
341 abdb293f Chrysostomos Nanakos
                        continue;
342 abdb293f Chrysostomos Nanakos
                }
343 abdb293f Chrysostomos Nanakos
344 abdb293f Chrysostomos Nanakos
                memset(&key, 0, sizeof(key));
345 abdb293f Chrysostomos Nanakos
                key.name = image->parent;
346 abdb293f Chrysostomos Nanakos
                keyp     = &key;
347 abdb293f Chrysostomos Nanakos
348 abdb293f Chrysostomos Nanakos
                parentp  = bsearch(&keyp, scan.images, scan.cur,
349 abdb293f Chrysostomos Nanakos
                                   sizeof(scan.images[0]),
350 abdb293f Chrysostomos Nanakos
                                   vhd_util_scan_pretty_image_compare);
351 abdb293f Chrysostomos Nanakos
                if (!parentp) {
352 abdb293f Chrysostomos Nanakos
                        image->parent_image = NULL;
353 abdb293f Chrysostomos Nanakos
                        continue;
354 abdb293f Chrysostomos Nanakos
                }
355 abdb293f Chrysostomos Nanakos
356 abdb293f Chrysostomos Nanakos
                parent = *parentp;
357 abdb293f Chrysostomos Nanakos
                image->parent_image = parent;
358 abdb293f Chrysostomos Nanakos
                list_add_tail(&image->sibling, &parent->children);
359 abdb293f Chrysostomos Nanakos
        }
360 abdb293f Chrysostomos Nanakos
361 abdb293f Chrysostomos Nanakos
        for (i = 0; i < scan.cur; i++) {
362 abdb293f Chrysostomos Nanakos
                image = scan.images[i];
363 abdb293f Chrysostomos Nanakos
364 abdb293f Chrysostomos Nanakos
                if (image->parent_image || !image->hidden)
365 abdb293f Chrysostomos Nanakos
                        continue;
366 abdb293f Chrysostomos Nanakos
367 abdb293f Chrysostomos Nanakos
                vhd_util_scan_pretty_print_tree(image, 0);
368 abdb293f Chrysostomos Nanakos
        }
369 abdb293f Chrysostomos Nanakos
370 abdb293f Chrysostomos Nanakos
        for (i = 0; i < scan.cur; i++) {
371 abdb293f Chrysostomos Nanakos
                image = scan.images[i];
372 abdb293f Chrysostomos Nanakos
373 abdb293f Chrysostomos Nanakos
                if (!image->name || image->parent_image)
374 abdb293f Chrysostomos Nanakos
                        continue;
375 abdb293f Chrysostomos Nanakos
376 abdb293f Chrysostomos Nanakos
                vhd_util_scan_pretty_print_tree(image, 0);
377 abdb293f Chrysostomos Nanakos
        }
378 abdb293f Chrysostomos Nanakos
379 abdb293f Chrysostomos Nanakos
        for (i = 0; i < scan.cur; i++) {
380 abdb293f Chrysostomos Nanakos
                image = scan.images[i];
381 abdb293f Chrysostomos Nanakos
382 abdb293f Chrysostomos Nanakos
                if (!image->name)
383 abdb293f Chrysostomos Nanakos
                        continue;
384 abdb293f Chrysostomos Nanakos
385 abdb293f Chrysostomos Nanakos
                vhd_util_scan_pretty_print_tree(image, 0);
386 abdb293f Chrysostomos Nanakos
        }
387 abdb293f Chrysostomos Nanakos
}
388 abdb293f Chrysostomos Nanakos
389 abdb293f Chrysostomos Nanakos
static void
390 abdb293f Chrysostomos Nanakos
vhd_util_scan_print_image(struct vhd_image *image)
391 abdb293f Chrysostomos Nanakos
{
392 abdb293f Chrysostomos Nanakos
        int err;
393 abdb293f Chrysostomos Nanakos
394 abdb293f Chrysostomos Nanakos
        if (!image->error && (flags & VHD_SCAN_PRETTY)) {
395 abdb293f Chrysostomos Nanakos
                err = vhd_util_scan_pretty_add_image(image);
396 abdb293f Chrysostomos Nanakos
                if (!err)
397 abdb293f Chrysostomos Nanakos
                        return;
398 abdb293f Chrysostomos Nanakos
399 abdb293f Chrysostomos Nanakos
                if (!image->error) {
400 abdb293f Chrysostomos Nanakos
                        image->error   = err;
401 abdb293f Chrysostomos Nanakos
                        image->message = "allocating memory";
402 abdb293f Chrysostomos Nanakos
                }
403 abdb293f Chrysostomos Nanakos
        }
404 abdb293f Chrysostomos Nanakos
405 abdb293f Chrysostomos Nanakos
        vhd_util_scan_print_image_indent(image, 0);
406 abdb293f Chrysostomos Nanakos
}
407 abdb293f Chrysostomos Nanakos
408 abdb293f Chrysostomos Nanakos
static int
409 abdb293f Chrysostomos Nanakos
vhd_util_scan_error(const char *file, int err)
410 abdb293f Chrysostomos Nanakos
{
411 abdb293f Chrysostomos Nanakos
        struct vhd_image image;
412 abdb293f Chrysostomos Nanakos
413 abdb293f Chrysostomos Nanakos
        memset(&image, 0, sizeof(image));
414 abdb293f Chrysostomos Nanakos
        image.name    = (char *)file;
415 abdb293f Chrysostomos Nanakos
        image.error   = err;
416 abdb293f Chrysostomos Nanakos
        image.message = "failure scanning target";
417 abdb293f Chrysostomos Nanakos
418 abdb293f Chrysostomos Nanakos
        vhd_util_scan_print_image(&image);
419 abdb293f Chrysostomos Nanakos
420 abdb293f Chrysostomos Nanakos
        /*
421 abdb293f Chrysostomos Nanakos
        if (flags & VHD_SCAN_NOFAIL)
422 abdb293f Chrysostomos Nanakos
                return 0;
423 abdb293f Chrysostomos Nanakos
        */
424 abdb293f Chrysostomos Nanakos
425 abdb293f Chrysostomos Nanakos
        return err;
426 abdb293f Chrysostomos Nanakos
}
427 abdb293f Chrysostomos Nanakos
428 abdb293f Chrysostomos Nanakos
static vhd_parent_locator_t *
429 abdb293f Chrysostomos Nanakos
vhd_util_scan_get_parent_locator(vhd_context_t *vhd)
430 abdb293f Chrysostomos Nanakos
{
431 abdb293f Chrysostomos Nanakos
        int i;
432 abdb293f Chrysostomos Nanakos
        vhd_parent_locator_t *loc;
433 abdb293f Chrysostomos Nanakos
434 abdb293f Chrysostomos Nanakos
        loc = NULL;
435 abdb293f Chrysostomos Nanakos
436 abdb293f Chrysostomos Nanakos
        for (i = 0; i < 8; i++) {
437 abdb293f Chrysostomos Nanakos
                if (vhd->header.loc[i].code == PLAT_CODE_MACX) {
438 abdb293f Chrysostomos Nanakos
                        loc = vhd->header.loc + i;
439 abdb293f Chrysostomos Nanakos
                        break;
440 abdb293f Chrysostomos Nanakos
                }
441 abdb293f Chrysostomos Nanakos
442 abdb293f Chrysostomos Nanakos
                if (vhd->header.loc[i].code == PLAT_CODE_W2RU)
443 abdb293f Chrysostomos Nanakos
                        loc = vhd->header.loc + i;
444 abdb293f Chrysostomos Nanakos
445 abdb293f Chrysostomos Nanakos
                if (!loc && vhd->header.loc[i].code != PLAT_CODE_NONE)
446 abdb293f Chrysostomos Nanakos
                        loc = vhd->header.loc + i;
447 abdb293f Chrysostomos Nanakos
        }
448 abdb293f Chrysostomos Nanakos
449 abdb293f Chrysostomos Nanakos
        return loc;
450 abdb293f Chrysostomos Nanakos
}
451 abdb293f Chrysostomos Nanakos
452 abdb293f Chrysostomos Nanakos
static inline int
453 abdb293f Chrysostomos Nanakos
copy_name(char *dst, const char *src)
454 abdb293f Chrysostomos Nanakos
{
455 abdb293f Chrysostomos Nanakos
        if (snprintf(dst, VHD_MAX_NAME_LEN, "%s", src) < VHD_MAX_NAME_LEN)
456 abdb293f Chrysostomos Nanakos
                return 0;
457 abdb293f Chrysostomos Nanakos
458 abdb293f Chrysostomos Nanakos
        return -ENAMETOOLONG;
459 abdb293f Chrysostomos Nanakos
}
460 abdb293f Chrysostomos Nanakos
461 abdb293f Chrysostomos Nanakos
/*
462 abdb293f Chrysostomos Nanakos
 * LVHD stores realpath(parent) in parent locators, so
463 abdb293f Chrysostomos Nanakos
 * /dev/<vol-group>/<lv-name> becomes /dev/mapper/<vol--group>-<lv--name>
464 abdb293f Chrysostomos Nanakos
 */
465 abdb293f Chrysostomos Nanakos
static int
466 abdb293f Chrysostomos Nanakos
vhd_util_scan_extract_volume_name(char *dst, const char *src)
467 abdb293f Chrysostomos Nanakos
{
468 abdb293f Chrysostomos Nanakos
        char copy[VHD_MAX_NAME_LEN], *name, *s, *c;
469 abdb293f Chrysostomos Nanakos
470 abdb293f Chrysostomos Nanakos
        name = strrchr(src, '/');
471 abdb293f Chrysostomos Nanakos
        if (!name)
472 abdb293f Chrysostomos Nanakos
                name = (char *)src;
473 abdb293f Chrysostomos Nanakos
474 abdb293f Chrysostomos Nanakos
        /* convert single dashes to slashes, double dashes to single dashes */
475 abdb293f Chrysostomos Nanakos
        for (c = copy, s = name; *s != '\0'; s++, c++) {
476 abdb293f Chrysostomos Nanakos
                if (*s == '-') {
477 abdb293f Chrysostomos Nanakos
                        if (s[1] != '-')
478 abdb293f Chrysostomos Nanakos
                                *c = '/';
479 abdb293f Chrysostomos Nanakos
                        else {
480 abdb293f Chrysostomos Nanakos
                                s++;
481 abdb293f Chrysostomos Nanakos
                                *c = '-';
482 abdb293f Chrysostomos Nanakos
                        }
483 abdb293f Chrysostomos Nanakos
                } else
484 abdb293f Chrysostomos Nanakos
                        *c = *s;
485 abdb293f Chrysostomos Nanakos
        }
486 abdb293f Chrysostomos Nanakos
487 abdb293f Chrysostomos Nanakos
        *c = '\0';
488 abdb293f Chrysostomos Nanakos
        c = strrchr(copy, '/');
489 abdb293f Chrysostomos Nanakos
        if (c == name) {
490 abdb293f Chrysostomos Nanakos
                /* unrecognized format */
491 abdb293f Chrysostomos Nanakos
                strcpy(dst, src);
492 abdb293f Chrysostomos Nanakos
                return -EINVAL;
493 abdb293f Chrysostomos Nanakos
        }
494 abdb293f Chrysostomos Nanakos
495 abdb293f Chrysostomos Nanakos
        strcpy(dst, ++c);
496 abdb293f Chrysostomos Nanakos
        return 0;
497 abdb293f Chrysostomos Nanakos
}
498 abdb293f Chrysostomos Nanakos
499 abdb293f Chrysostomos Nanakos
static int
500 abdb293f Chrysostomos Nanakos
vhd_util_scan_get_volume_parent(vhd_context_t *vhd, struct vhd_image *image)
501 abdb293f Chrysostomos Nanakos
{
502 abdb293f Chrysostomos Nanakos
        int err;
503 abdb293f Chrysostomos Nanakos
        char name[VHD_MAX_NAME_LEN];
504 abdb293f Chrysostomos Nanakos
        vhd_parent_locator_t *loc, copy;
505 abdb293f Chrysostomos Nanakos
506 abdb293f Chrysostomos Nanakos
        if (flags & VHD_SCAN_FAST) {
507 abdb293f Chrysostomos Nanakos
                err = vhd_header_decode_parent(vhd,
508 abdb293f Chrysostomos Nanakos
                                               &vhd->header, &image->parent);
509 abdb293f Chrysostomos Nanakos
                if (!err)
510 abdb293f Chrysostomos Nanakos
                        goto found;
511 abdb293f Chrysostomos Nanakos
        }
512 abdb293f Chrysostomos Nanakos
513 abdb293f Chrysostomos Nanakos
        loc = vhd_util_scan_get_parent_locator(vhd);
514 abdb293f Chrysostomos Nanakos
        if (!loc)
515 abdb293f Chrysostomos Nanakos
                return -EINVAL;
516 abdb293f Chrysostomos Nanakos
517 abdb293f Chrysostomos Nanakos
        copy = *loc;
518 abdb293f Chrysostomos Nanakos
        copy.data_offset += image->target->start;
519 abdb293f Chrysostomos Nanakos
        err = vhd_parent_locator_read(vhd, &copy, &image->parent);
520 abdb293f Chrysostomos Nanakos
        if (err)
521 abdb293f Chrysostomos Nanakos
                return err;
522 abdb293f Chrysostomos Nanakos
523 abdb293f Chrysostomos Nanakos
found:
524 abdb293f Chrysostomos Nanakos
        err = vhd_util_scan_extract_volume_name(name, image->parent);
525 abdb293f Chrysostomos Nanakos
        if (!err)
526 abdb293f Chrysostomos Nanakos
                return copy_name(image->parent, name);
527 abdb293f Chrysostomos Nanakos
528 abdb293f Chrysostomos Nanakos
        return 0;
529 abdb293f Chrysostomos Nanakos
}
530 abdb293f Chrysostomos Nanakos
531 abdb293f Chrysostomos Nanakos
static int
532 abdb293f Chrysostomos Nanakos
vhd_util_scan_get_parent(vhd_context_t *vhd, struct vhd_image *image)
533 abdb293f Chrysostomos Nanakos
{
534 abdb293f Chrysostomos Nanakos
        int err;
535 abdb293f Chrysostomos Nanakos
        vhd_parent_locator_t *loc;
536 abdb293f Chrysostomos Nanakos
537 abdb293f Chrysostomos Nanakos
        if (!target_vhd(image->target->type)) {
538 abdb293f Chrysostomos Nanakos
                image->parent = NULL;
539 abdb293f Chrysostomos Nanakos
                return 0;
540 abdb293f Chrysostomos Nanakos
        }
541 abdb293f Chrysostomos Nanakos
542 abdb293f Chrysostomos Nanakos
        loc = NULL;
543 abdb293f Chrysostomos Nanakos
544 abdb293f Chrysostomos Nanakos
        if (target_volume(image->target->type))
545 abdb293f Chrysostomos Nanakos
                return vhd_util_scan_get_volume_parent(vhd, image);
546 abdb293f Chrysostomos Nanakos
547 abdb293f Chrysostomos Nanakos
        if (flags & VHD_SCAN_FAST) {
548 abdb293f Chrysostomos Nanakos
                err = vhd_header_decode_parent(vhd,
549 abdb293f Chrysostomos Nanakos
                                               &vhd->header, &image->parent);
550 abdb293f Chrysostomos Nanakos
                if (!err)
551 abdb293f Chrysostomos Nanakos
                        return 0;
552 abdb293f Chrysostomos Nanakos
        } else {
553 abdb293f Chrysostomos Nanakos
                /*
554 abdb293f Chrysostomos Nanakos
                 * vhd_parent_locator_get checks for the existence of the 
555 abdb293f Chrysostomos Nanakos
                 * parent file. if this call succeeds, all is well; if not,
556 abdb293f Chrysostomos Nanakos
                 * we'll try to return whatever string we have before failing
557 abdb293f Chrysostomos Nanakos
                 * outright.
558 abdb293f Chrysostomos Nanakos
                 */
559 abdb293f Chrysostomos Nanakos
                err = vhd_parent_locator_get(vhd, &image->parent);
560 abdb293f Chrysostomos Nanakos
                if (!err)
561 abdb293f Chrysostomos Nanakos
                        return 0;
562 abdb293f Chrysostomos Nanakos
        }
563 abdb293f Chrysostomos Nanakos
564 abdb293f Chrysostomos Nanakos
        loc = vhd_util_scan_get_parent_locator(vhd);
565 abdb293f Chrysostomos Nanakos
        if (!loc)
566 abdb293f Chrysostomos Nanakos
                return -EINVAL;
567 abdb293f Chrysostomos Nanakos
568 abdb293f Chrysostomos Nanakos
        return vhd_parent_locator_read(vhd, loc, &image->parent);
569 abdb293f Chrysostomos Nanakos
}
570 abdb293f Chrysostomos Nanakos
571 abdb293f Chrysostomos Nanakos
static int
572 abdb293f Chrysostomos Nanakos
vhd_util_scan_get_hidden(vhd_context_t *vhd, struct vhd_image *image)
573 abdb293f Chrysostomos Nanakos
{
574 abdb293f Chrysostomos Nanakos
        int err, hidden;
575 abdb293f Chrysostomos Nanakos
576 abdb293f Chrysostomos Nanakos
        err    = 0;
577 abdb293f Chrysostomos Nanakos
        hidden = 0;
578 abdb293f Chrysostomos Nanakos
579 abdb293f Chrysostomos Nanakos
        if (target_vhd(image->target->type))
580 abdb293f Chrysostomos Nanakos
                err = vhd_hidden(vhd, &hidden);
581 abdb293f Chrysostomos Nanakos
        else
582 abdb293f Chrysostomos Nanakos
                hidden = 1;
583 abdb293f Chrysostomos Nanakos
584 abdb293f Chrysostomos Nanakos
        if (err)
585 abdb293f Chrysostomos Nanakos
                return err;
586 abdb293f Chrysostomos Nanakos
587 abdb293f Chrysostomos Nanakos
        image->hidden = hidden;
588 abdb293f Chrysostomos Nanakos
        return 0;
589 abdb293f Chrysostomos Nanakos
}
590 abdb293f Chrysostomos Nanakos
591 abdb293f Chrysostomos Nanakos
static int
592 abdb293f Chrysostomos Nanakos
vhd_util_scan_get_marker(vhd_context_t *vhd, struct vhd_image *image)
593 abdb293f Chrysostomos Nanakos
{
594 abdb293f Chrysostomos Nanakos
        int err;
595 abdb293f Chrysostomos Nanakos
        char marker;
596 abdb293f Chrysostomos Nanakos
597 abdb293f Chrysostomos Nanakos
        err    = 0;
598 abdb293f Chrysostomos Nanakos
        marker = 0;
599 abdb293f Chrysostomos Nanakos
600 abdb293f Chrysostomos Nanakos
        if (target_vhd(image->target->type) && vhd_has_batmap(vhd))
601 abdb293f Chrysostomos Nanakos
                err = vhd_marker(vhd, &marker);
602 abdb293f Chrysostomos Nanakos
603 abdb293f Chrysostomos Nanakos
        image->marker = marker;
604 abdb293f Chrysostomos Nanakos
        return err;
605 abdb293f Chrysostomos Nanakos
}
606 abdb293f Chrysostomos Nanakos
607 abdb293f Chrysostomos Nanakos
static int
608 abdb293f Chrysostomos Nanakos
vhd_util_scan_get_size(vhd_context_t *vhd, struct vhd_image *image)
609 abdb293f Chrysostomos Nanakos
{
610 abdb293f Chrysostomos Nanakos
        image->size = image->target->size;
611 abdb293f Chrysostomos Nanakos
612 abdb293f Chrysostomos Nanakos
        if (target_vhd(image->target->type))
613 abdb293f Chrysostomos Nanakos
                image->capacity = vhd->footer.curr_size;
614 abdb293f Chrysostomos Nanakos
        else
615 abdb293f Chrysostomos Nanakos
                image->capacity = image->size;
616 abdb293f Chrysostomos Nanakos
617 abdb293f Chrysostomos Nanakos
        return 0;
618 abdb293f Chrysostomos Nanakos
}
619 abdb293f Chrysostomos Nanakos
620 abdb293f Chrysostomos Nanakos
static int
621 abdb293f Chrysostomos Nanakos
vhd_util_scan_open_file(vhd_context_t *vhd, struct vhd_image *image)
622 abdb293f Chrysostomos Nanakos
{
623 abdb293f Chrysostomos Nanakos
        int err, vhd_flags;
624 abdb293f Chrysostomos Nanakos
625 abdb293f Chrysostomos Nanakos
        if (!target_vhd(image->target->type))
626 abdb293f Chrysostomos Nanakos
                return 0;
627 abdb293f Chrysostomos Nanakos
628 abdb293f Chrysostomos Nanakos
        vhd_flags = VHD_OPEN_RDONLY | VHD_OPEN_IGNORE_DISABLED;
629 abdb293f Chrysostomos Nanakos
        if (flags & VHD_SCAN_FAST)
630 abdb293f Chrysostomos Nanakos
                vhd_flags |= VHD_OPEN_FAST;
631 abdb293f Chrysostomos Nanakos
632 abdb293f Chrysostomos Nanakos
        err = vhd_open(vhd, image->name, vhd_flags);
633 abdb293f Chrysostomos Nanakos
        if (err) {
634 abdb293f Chrysostomos Nanakos
                vhd->file      = NULL;
635 abdb293f Chrysostomos Nanakos
                image->message = "opening file";
636 abdb293f Chrysostomos Nanakos
                image->error   = err;
637 abdb293f Chrysostomos Nanakos
                return image->error;
638 abdb293f Chrysostomos Nanakos
        }
639 abdb293f Chrysostomos Nanakos
640 abdb293f Chrysostomos Nanakos
        return 0;
641 abdb293f Chrysostomos Nanakos
}
642 abdb293f Chrysostomos Nanakos
643 abdb293f Chrysostomos Nanakos
static int
644 abdb293f Chrysostomos Nanakos
vhd_util_scan_read_volume_headers(vhd_context_t *vhd, struct vhd_image *image)
645 abdb293f Chrysostomos Nanakos
{
646 abdb293f Chrysostomos Nanakos
        int err;
647 abdb293f Chrysostomos Nanakos
        void *buf;
648 abdb293f Chrysostomos Nanakos
        size_t size;
649 abdb293f Chrysostomos Nanakos
        struct target *target;
650 abdb293f Chrysostomos Nanakos
651 abdb293f Chrysostomos Nanakos
        buf    = NULL;
652 abdb293f Chrysostomos Nanakos
        target = image->target;
653 abdb293f Chrysostomos Nanakos
        size   = sizeof(vhd_footer_t) + sizeof(vhd_header_t);
654 abdb293f Chrysostomos Nanakos
655 abdb293f Chrysostomos Nanakos
        err = posix_memalign(&buf, VHD_SECTOR_SIZE, size);
656 abdb293f Chrysostomos Nanakos
        if (err) {
657 abdb293f Chrysostomos Nanakos
                buf            = NULL;
658 abdb293f Chrysostomos Nanakos
                image->message = "allocating image";
659 abdb293f Chrysostomos Nanakos
                image->error   = -err;
660 abdb293f Chrysostomos Nanakos
                goto out;
661 abdb293f Chrysostomos Nanakos
        }
662 abdb293f Chrysostomos Nanakos
663 abdb293f Chrysostomos Nanakos
        err = vhd_seek(vhd, target->start, SEEK_SET);
664 abdb293f Chrysostomos Nanakos
        if (err) {
665 abdb293f Chrysostomos Nanakos
                image->message = "seeking to headers";
666 abdb293f Chrysostomos Nanakos
                image->error   = err;
667 abdb293f Chrysostomos Nanakos
                goto out;
668 abdb293f Chrysostomos Nanakos
        }
669 abdb293f Chrysostomos Nanakos
670 abdb293f Chrysostomos Nanakos
        err = vhd_read(vhd, buf, size);
671 abdb293f Chrysostomos Nanakos
        if (err) {
672 abdb293f Chrysostomos Nanakos
                image->message = "reading headers";
673 abdb293f Chrysostomos Nanakos
                image->error   = err;
674 abdb293f Chrysostomos Nanakos
                goto out;
675 abdb293f Chrysostomos Nanakos
        }
676 abdb293f Chrysostomos Nanakos
677 abdb293f Chrysostomos Nanakos
        memcpy(&vhd->footer, buf, sizeof(vhd_footer_t));
678 abdb293f Chrysostomos Nanakos
        vhd_footer_in(&vhd->footer);
679 abdb293f Chrysostomos Nanakos
        err = vhd_validate_footer(&vhd->footer);
680 abdb293f Chrysostomos Nanakos
        if (err) {
681 abdb293f Chrysostomos Nanakos
                image->message = "invalid footer";
682 abdb293f Chrysostomos Nanakos
                image->error   = err;
683 abdb293f Chrysostomos Nanakos
                goto out;
684 abdb293f Chrysostomos Nanakos
        }
685 abdb293f Chrysostomos Nanakos
686 abdb293f Chrysostomos Nanakos
        /* lvhd vhds should always be dynamic */
687 abdb293f Chrysostomos Nanakos
        if (vhd_type_dynamic(vhd)) {
688 abdb293f Chrysostomos Nanakos
                if (vhd->footer.data_offset != sizeof(vhd_footer_t))
689 abdb293f Chrysostomos Nanakos
                        err = vhd_read_header_at(vhd, &vhd->header,
690 abdb293f Chrysostomos Nanakos
                                                 vhd->footer.data_offset +
691 abdb293f Chrysostomos Nanakos
                                                 target->start);
692 abdb293f Chrysostomos Nanakos
                else {
693 abdb293f Chrysostomos Nanakos
                        memcpy(&vhd->header,
694 abdb293f Chrysostomos Nanakos
                               buf + sizeof(vhd_footer_t),
695 abdb293f Chrysostomos Nanakos
                               sizeof(vhd_header_t));
696 abdb293f Chrysostomos Nanakos
                        vhd_header_in(&vhd->header);
697 abdb293f Chrysostomos Nanakos
                        err = vhd_validate_header(&vhd->header);
698 abdb293f Chrysostomos Nanakos
                }
699 abdb293f Chrysostomos Nanakos
700 abdb293f Chrysostomos Nanakos
                if (err) {
701 abdb293f Chrysostomos Nanakos
                        image->message = "reading header";
702 abdb293f Chrysostomos Nanakos
                        image->error   = err;
703 abdb293f Chrysostomos Nanakos
                        goto out;
704 abdb293f Chrysostomos Nanakos
                }
705 abdb293f Chrysostomos Nanakos
706 abdb293f Chrysostomos Nanakos
                vhd->spb = vhd->header.block_size >> VHD_SECTOR_SHIFT;
707 abdb293f Chrysostomos Nanakos
                vhd->bm_secs = secs_round_up_no_zero(vhd->spb >> 3);
708 abdb293f Chrysostomos Nanakos
        }
709 abdb293f Chrysostomos Nanakos
710 abdb293f Chrysostomos Nanakos
out:
711 abdb293f Chrysostomos Nanakos
        free(buf);
712 abdb293f Chrysostomos Nanakos
        return image->error;
713 abdb293f Chrysostomos Nanakos
}
714 abdb293f Chrysostomos Nanakos
715 abdb293f Chrysostomos Nanakos
static int
716 abdb293f Chrysostomos Nanakos
vhd_util_scan_open_volume(vhd_context_t *vhd, struct vhd_image *image)
717 abdb293f Chrysostomos Nanakos
{
718 abdb293f Chrysostomos Nanakos
        struct target *target;
719 abdb293f Chrysostomos Nanakos
720 abdb293f Chrysostomos Nanakos
        target = image->target;
721 abdb293f Chrysostomos Nanakos
        memset(vhd, 0, sizeof(*vhd));
722 abdb293f Chrysostomos Nanakos
        vhd->oflags = VHD_OPEN_RDONLY | VHD_OPEN_FAST;
723 abdb293f Chrysostomos Nanakos
724 abdb293f Chrysostomos Nanakos
        if (target->end - target->start < 4096) {
725 abdb293f Chrysostomos Nanakos
                image->message = "device too small";
726 abdb293f Chrysostomos Nanakos
                image->error   = -EINVAL;
727 abdb293f Chrysostomos Nanakos
                return image->error;
728 abdb293f Chrysostomos Nanakos
        }
729 abdb293f Chrysostomos Nanakos
730 abdb293f Chrysostomos Nanakos
        vhd->file = strdup(image->name);
731 abdb293f Chrysostomos Nanakos
        if (!vhd->file) {
732 abdb293f Chrysostomos Nanakos
                image->message = "allocating device";
733 abdb293f Chrysostomos Nanakos
                image->error   = -ENOMEM;
734 abdb293f Chrysostomos Nanakos
                return image->error;
735 abdb293f Chrysostomos Nanakos
        }
736 abdb293f Chrysostomos Nanakos
737 abdb293f Chrysostomos Nanakos
        vhd->fd = open(target->device, O_RDONLY | O_DIRECT | O_LARGEFILE);
738 abdb293f Chrysostomos Nanakos
        if (vhd->fd == -1) {
739 abdb293f Chrysostomos Nanakos
                free(vhd->file);
740 abdb293f Chrysostomos Nanakos
                vhd->file = NULL;
741 abdb293f Chrysostomos Nanakos
742 abdb293f Chrysostomos Nanakos
                image->message = "opening device";
743 abdb293f Chrysostomos Nanakos
                image->error   = -errno;
744 abdb293f Chrysostomos Nanakos
                return image->error;
745 abdb293f Chrysostomos Nanakos
        }
746 abdb293f Chrysostomos Nanakos
747 abdb293f Chrysostomos Nanakos
        if (target_vhd(target->type))
748 abdb293f Chrysostomos Nanakos
                return vhd_util_scan_read_volume_headers(vhd, image);
749 abdb293f Chrysostomos Nanakos
750 abdb293f Chrysostomos Nanakos
        return 0;
751 abdb293f Chrysostomos Nanakos
}
752 abdb293f Chrysostomos Nanakos
753 abdb293f Chrysostomos Nanakos
static int
754 abdb293f Chrysostomos Nanakos
vhd_util_scan_open(vhd_context_t *vhd, struct vhd_image *image)
755 abdb293f Chrysostomos Nanakos
{
756 abdb293f Chrysostomos Nanakos
        struct target *target;
757 abdb293f Chrysostomos Nanakos
758 abdb293f Chrysostomos Nanakos
        target = image->target;
759 abdb293f Chrysostomos Nanakos
760 abdb293f Chrysostomos Nanakos
        if (target_volume(image->target->type) || !(flags & VHD_SCAN_PRETTY))
761 abdb293f Chrysostomos Nanakos
                image->name = target->name;
762 abdb293f Chrysostomos Nanakos
        else {
763 abdb293f Chrysostomos Nanakos
                char __image_name[PATH_MAX];
764 abdb293f Chrysostomos Nanakos
765 abdb293f Chrysostomos Nanakos
                image->name = realpath(target->name, __image_name);
766 abdb293f Chrysostomos Nanakos
                if (image->name)
767 abdb293f Chrysostomos Nanakos
                        image->name = strdup(__image_name);
768 abdb293f Chrysostomos Nanakos
                if (!image->name) {
769 abdb293f Chrysostomos Nanakos
                        image->name    = target->name;
770 abdb293f Chrysostomos Nanakos
                        image->message = "resolving name";
771 abdb293f Chrysostomos Nanakos
                        image->error   = -errno;
772 abdb293f Chrysostomos Nanakos
                        return image->error;
773 abdb293f Chrysostomos Nanakos
                }
774 abdb293f Chrysostomos Nanakos
        }
775 abdb293f Chrysostomos Nanakos
776 abdb293f Chrysostomos Nanakos
        if (target_volume(target->type))
777 abdb293f Chrysostomos Nanakos
                return vhd_util_scan_open_volume(vhd, image);
778 abdb293f Chrysostomos Nanakos
        else
779 abdb293f Chrysostomos Nanakos
                return vhd_util_scan_open_file(vhd, image);
780 abdb293f Chrysostomos Nanakos
}
781 abdb293f Chrysostomos Nanakos
782 abdb293f Chrysostomos Nanakos
static int
783 abdb293f Chrysostomos Nanakos
vhd_util_scan_init_file_target(struct target *target,
784 abdb293f Chrysostomos Nanakos
                               const char *file, uint8_t type)
785 abdb293f Chrysostomos Nanakos
{
786 abdb293f Chrysostomos Nanakos
        int err;
787 abdb293f Chrysostomos Nanakos
        struct stat stats;
788 abdb293f Chrysostomos Nanakos
789 abdb293f Chrysostomos Nanakos
        err = stat(file, &stats);
790 abdb293f Chrysostomos Nanakos
        if (err == -1)
791 abdb293f Chrysostomos Nanakos
                return -errno;
792 abdb293f Chrysostomos Nanakos
793 abdb293f Chrysostomos Nanakos
        err = copy_name(target->name, file);
794 abdb293f Chrysostomos Nanakos
        if (err)
795 abdb293f Chrysostomos Nanakos
                return err;
796 abdb293f Chrysostomos Nanakos
797 abdb293f Chrysostomos Nanakos
        err = copy_name(target->device, file);
798 abdb293f Chrysostomos Nanakos
        if (err)
799 abdb293f Chrysostomos Nanakos
                return err;
800 abdb293f Chrysostomos Nanakos
801 abdb293f Chrysostomos Nanakos
        target->type  = type;
802 abdb293f Chrysostomos Nanakos
        target->start = 0;
803 abdb293f Chrysostomos Nanakos
        target->size  = stats.st_size;
804 abdb293f Chrysostomos Nanakos
        target->end   = stats.st_size;
805 abdb293f Chrysostomos Nanakos
806 abdb293f Chrysostomos Nanakos
        return 0;
807 abdb293f Chrysostomos Nanakos
}
808 abdb293f Chrysostomos Nanakos
809 abdb293f Chrysostomos Nanakos
static int
810 abdb293f Chrysostomos Nanakos
vhd_util_scan_init_volume_target(struct target *target,
811 abdb293f Chrysostomos Nanakos
                                 struct lv *lv, uint8_t type)
812 abdb293f Chrysostomos Nanakos
{
813 abdb293f Chrysostomos Nanakos
        int err;
814 abdb293f Chrysostomos Nanakos
815 abdb293f Chrysostomos Nanakos
        if (lv->first_segment.type != LVM_SEG_TYPE_LINEAR)
816 abdb293f Chrysostomos Nanakos
                return -ENOSYS;
817 abdb293f Chrysostomos Nanakos
818 abdb293f Chrysostomos Nanakos
        err = copy_name(target->name, lv->name);
819 abdb293f Chrysostomos Nanakos
        if (err) {
820 abdb293f Chrysostomos Nanakos
                EPRINTF("copy target name failed: '%s'\n", lv->name);
821 abdb293f Chrysostomos Nanakos
                return err;
822 abdb293f Chrysostomos Nanakos
        }
823 abdb293f Chrysostomos Nanakos
824 abdb293f Chrysostomos Nanakos
        err = copy_name(target->device, lv->first_segment.device);
825 abdb293f Chrysostomos Nanakos
        if (err) {
826 abdb293f Chrysostomos Nanakos
                EPRINTF("copy target device failed: '%s'\n",
827 abdb293f Chrysostomos Nanakos
                                lv->first_segment.device);
828 abdb293f Chrysostomos Nanakos
                return err;
829 abdb293f Chrysostomos Nanakos
        }
830 abdb293f Chrysostomos Nanakos
831 abdb293f Chrysostomos Nanakos
        target->type  = type;
832 abdb293f Chrysostomos Nanakos
        target->size  = lv->size;
833 abdb293f Chrysostomos Nanakos
        target->start = lv->first_segment.pe_start;
834 abdb293f Chrysostomos Nanakos
        target->end   = target->start + lv->first_segment.pe_size;
835 abdb293f Chrysostomos Nanakos
836 abdb293f Chrysostomos Nanakos
        return 0;
837 abdb293f Chrysostomos Nanakos
}
838 abdb293f Chrysostomos Nanakos
839 abdb293f Chrysostomos Nanakos
static int
840 abdb293f Chrysostomos Nanakos
iterator_init(struct iterator *itr, int cnt, struct target *targets)
841 abdb293f Chrysostomos Nanakos
{
842 abdb293f Chrysostomos Nanakos
        memset(itr, 0, sizeof(*itr));
843 abdb293f Chrysostomos Nanakos
844 abdb293f Chrysostomos Nanakos
        itr->targets = malloc(sizeof(struct target) * cnt);
845 abdb293f Chrysostomos Nanakos
        if (!itr->targets)
846 abdb293f Chrysostomos Nanakos
                return -ENOMEM;
847 abdb293f Chrysostomos Nanakos
848 abdb293f Chrysostomos Nanakos
        memcpy(itr->targets, targets, sizeof(struct target) * cnt);
849 abdb293f Chrysostomos Nanakos
850 abdb293f Chrysostomos Nanakos
        itr->cur      = 0;
851 abdb293f Chrysostomos Nanakos
        itr->cur_size = cnt;
852 abdb293f Chrysostomos Nanakos
        itr->max_size = cnt;
853 abdb293f Chrysostomos Nanakos
854 abdb293f Chrysostomos Nanakos
        return 0;
855 abdb293f Chrysostomos Nanakos
}
856 abdb293f Chrysostomos Nanakos
857 abdb293f Chrysostomos Nanakos
static struct target *
858 abdb293f Chrysostomos Nanakos
iterator_next(struct iterator *itr)
859 abdb293f Chrysostomos Nanakos
{
860 abdb293f Chrysostomos Nanakos
        if (itr->cur == itr->cur_size)
861 abdb293f Chrysostomos Nanakos
                return NULL;
862 abdb293f Chrysostomos Nanakos
863 abdb293f Chrysostomos Nanakos
        return itr->targets + itr->cur++;
864 abdb293f Chrysostomos Nanakos
}
865 abdb293f Chrysostomos Nanakos
866 abdb293f Chrysostomos Nanakos
static int
867 abdb293f Chrysostomos Nanakos
iterator_add_file(struct iterator *itr,
868 abdb293f Chrysostomos Nanakos
                  struct target *target, const char *parent, uint8_t type)
869 abdb293f Chrysostomos Nanakos
{
870 abdb293f Chrysostomos Nanakos
        int i;
871 abdb293f Chrysostomos Nanakos
        struct target *t;
872 abdb293f Chrysostomos Nanakos
        char *lname, *rname;
873 abdb293f Chrysostomos Nanakos
874 abdb293f Chrysostomos Nanakos
        for (i = 0; i < itr->cur_size; i++) {
875 abdb293f Chrysostomos Nanakos
                t = itr->targets + i;
876 abdb293f Chrysostomos Nanakos
                lname = basename((char *)t->name);
877 abdb293f Chrysostomos Nanakos
                rname = basename((char *)parent);
878 abdb293f Chrysostomos Nanakos
879 abdb293f Chrysostomos Nanakos
                if (!strcmp(lname, rname))
880 abdb293f Chrysostomos Nanakos
                        return -EEXIST;
881 abdb293f Chrysostomos Nanakos
        }
882 abdb293f Chrysostomos Nanakos
883 abdb293f Chrysostomos Nanakos
        return vhd_util_scan_init_file_target(target, parent, type);
884 abdb293f Chrysostomos Nanakos
}
885 abdb293f Chrysostomos Nanakos
886 abdb293f Chrysostomos Nanakos
static int
887 abdb293f Chrysostomos Nanakos
iterator_add_volume(struct iterator *itr,
888 abdb293f Chrysostomos Nanakos
                    struct target *target, const char *parent, uint8_t type)
889 abdb293f Chrysostomos Nanakos
{
890 abdb293f Chrysostomos Nanakos
        int i, err;
891 abdb293f Chrysostomos Nanakos
        struct lv *lv;
892 abdb293f Chrysostomos Nanakos
893 abdb293f Chrysostomos Nanakos
        lv  = NULL;
894 abdb293f Chrysostomos Nanakos
        err = -ENOENT;
895 abdb293f Chrysostomos Nanakos
896 abdb293f Chrysostomos Nanakos
        for (i = 0; i < itr->cur_size; i++)
897 abdb293f Chrysostomos Nanakos
                if (!strcmp(parent, itr->targets[i].name))
898 abdb293f Chrysostomos Nanakos
                        return -EEXIST;
899 abdb293f Chrysostomos Nanakos
900 abdb293f Chrysostomos Nanakos
        for (i = 0; i < vg.lv_cnt; i++) {
901 abdb293f Chrysostomos Nanakos
                err = fnmatch(parent, vg.lvs[i].name, FNM_PATHNAME);
902 abdb293f Chrysostomos Nanakos
                if (err != FNM_NOMATCH) {
903 abdb293f Chrysostomos Nanakos
                        lv = vg.lvs + i;
904 abdb293f Chrysostomos Nanakos
                        break;
905 abdb293f Chrysostomos Nanakos
                }
906 abdb293f Chrysostomos Nanakos
        }
907 abdb293f Chrysostomos Nanakos
908 abdb293f Chrysostomos Nanakos
        if (err && err != FNM_PATHNAME)
909 abdb293f Chrysostomos Nanakos
                return err;
910 abdb293f Chrysostomos Nanakos
911 abdb293f Chrysostomos Nanakos
        if (!lv)
912 abdb293f Chrysostomos Nanakos
                return -ENOENT;
913 abdb293f Chrysostomos Nanakos
914 abdb293f Chrysostomos Nanakos
        return vhd_util_scan_init_volume_target(target, lv, type);
915 abdb293f Chrysostomos Nanakos
}
916 abdb293f Chrysostomos Nanakos
917 abdb293f Chrysostomos Nanakos
static int
918 abdb293f Chrysostomos Nanakos
iterator_add(struct iterator *itr, const char *parent, uint8_t type)
919 abdb293f Chrysostomos Nanakos
{
920 abdb293f Chrysostomos Nanakos
        int err;
921 abdb293f Chrysostomos Nanakos
        struct target *target;
922 abdb293f Chrysostomos Nanakos
923 abdb293f Chrysostomos Nanakos
        if (itr->cur_size == itr->max_size) {
924 abdb293f Chrysostomos Nanakos
                struct target *new;
925 abdb293f Chrysostomos Nanakos
926 abdb293f Chrysostomos Nanakos
                new = realloc(itr->targets,
927 abdb293f Chrysostomos Nanakos
                              sizeof(struct target) *
928 abdb293f Chrysostomos Nanakos
                              itr->max_size * 2);
929 abdb293f Chrysostomos Nanakos
                if (!new)
930 abdb293f Chrysostomos Nanakos
                        return -ENOMEM;
931 abdb293f Chrysostomos Nanakos
932 abdb293f Chrysostomos Nanakos
                itr->max_size *= 2;
933 abdb293f Chrysostomos Nanakos
                itr->targets   = new;
934 abdb293f Chrysostomos Nanakos
        }
935 abdb293f Chrysostomos Nanakos
936 abdb293f Chrysostomos Nanakos
        target = itr->targets + itr->cur_size;
937 abdb293f Chrysostomos Nanakos
938 abdb293f Chrysostomos Nanakos
        if (target_volume(type))
939 abdb293f Chrysostomos Nanakos
                err = iterator_add_volume(itr, target, parent, type);
940 abdb293f Chrysostomos Nanakos
        else
941 abdb293f Chrysostomos Nanakos
                err = iterator_add_file(itr, target, parent, type);
942 abdb293f Chrysostomos Nanakos
943 abdb293f Chrysostomos Nanakos
        if (err)
944 abdb293f Chrysostomos Nanakos
                memset(target, 0, sizeof(*target));
945 abdb293f Chrysostomos Nanakos
        else
946 abdb293f Chrysostomos Nanakos
                itr->cur_size++;
947 abdb293f Chrysostomos Nanakos
948 abdb293f Chrysostomos Nanakos
        return (err == -EEXIST ? 0 : err);
949 abdb293f Chrysostomos Nanakos
}
950 abdb293f Chrysostomos Nanakos
951 abdb293f Chrysostomos Nanakos
static void
952 abdb293f Chrysostomos Nanakos
iterator_free(struct iterator *itr)
953 abdb293f Chrysostomos Nanakos
{
954 abdb293f Chrysostomos Nanakos
        free(itr->targets);
955 abdb293f Chrysostomos Nanakos
        memset(itr, 0, sizeof(*itr));
956 abdb293f Chrysostomos Nanakos
}
957 abdb293f Chrysostomos Nanakos
958 abdb293f Chrysostomos Nanakos
static void
959 abdb293f Chrysostomos Nanakos
vhd_util_scan_add_parent(struct iterator *itr,
960 abdb293f Chrysostomos Nanakos
                         vhd_context_t *vhd, struct vhd_image *image)
961 abdb293f Chrysostomos Nanakos
{
962 abdb293f Chrysostomos Nanakos
        int err;
963 abdb293f Chrysostomos Nanakos
        uint8_t type;
964 abdb293f Chrysostomos Nanakos
965 abdb293f Chrysostomos Nanakos
        if (vhd_parent_raw(vhd))
966 abdb293f Chrysostomos Nanakos
                type = target_volume(image->target->type) ? 
967 abdb293f Chrysostomos Nanakos
                        VHD_TYPE_RAW_VOLUME : VHD_TYPE_RAW_FILE;
968 abdb293f Chrysostomos Nanakos
        else
969 abdb293f Chrysostomos Nanakos
                type = target_volume(image->target->type) ? 
970 abdb293f Chrysostomos Nanakos
                        VHD_TYPE_VHD_VOLUME : VHD_TYPE_VHD_FILE;
971 abdb293f Chrysostomos Nanakos
972 abdb293f Chrysostomos Nanakos
        err = iterator_add(itr, image->parent, type);
973 abdb293f Chrysostomos Nanakos
        if (err)
974 abdb293f Chrysostomos Nanakos
                vhd_util_scan_error(image->parent, err);
975 abdb293f Chrysostomos Nanakos
}
976 abdb293f Chrysostomos Nanakos
977 abdb293f Chrysostomos Nanakos
static int
978 abdb293f Chrysostomos Nanakos
vhd_util_scan_targets(int cnt, struct target *targets)
979 abdb293f Chrysostomos Nanakos
{
980 abdb293f Chrysostomos Nanakos
        int ret, err;
981 abdb293f Chrysostomos Nanakos
        vhd_context_t vhd;
982 abdb293f Chrysostomos Nanakos
        struct iterator itr;
983 abdb293f Chrysostomos Nanakos
        struct target *target;
984 abdb293f Chrysostomos Nanakos
        struct vhd_image image;
985 abdb293f Chrysostomos Nanakos
986 abdb293f Chrysostomos Nanakos
        ret = 0;
987 abdb293f Chrysostomos Nanakos
        err = 0;
988 abdb293f Chrysostomos Nanakos
989 abdb293f Chrysostomos Nanakos
        err = iterator_init(&itr, cnt, targets);
990 abdb293f Chrysostomos Nanakos
        if (err)
991 abdb293f Chrysostomos Nanakos
                return err;
992 abdb293f Chrysostomos Nanakos
993 abdb293f Chrysostomos Nanakos
        while ((target = iterator_next(&itr))) {
994 abdb293f Chrysostomos Nanakos
                memset(&vhd, 0, sizeof(vhd));
995 abdb293f Chrysostomos Nanakos
                memset(&image, 0, sizeof(image));
996 abdb293f Chrysostomos Nanakos
997 abdb293f Chrysostomos Nanakos
                image.target = target;
998 abdb293f Chrysostomos Nanakos
999 abdb293f Chrysostomos Nanakos
                err = vhd_util_scan_open(&vhd, &image);
1000 abdb293f Chrysostomos Nanakos
                if (err) {
1001 abdb293f Chrysostomos Nanakos
                        ret = -EAGAIN;
1002 abdb293f Chrysostomos Nanakos
                        goto end;
1003 abdb293f Chrysostomos Nanakos
                }
1004 abdb293f Chrysostomos Nanakos
1005 abdb293f Chrysostomos Nanakos
                err = vhd_util_scan_get_size(&vhd, &image);
1006 abdb293f Chrysostomos Nanakos
                if (err) {
1007 abdb293f Chrysostomos Nanakos
                        ret           = -EAGAIN;
1008 abdb293f Chrysostomos Nanakos
                        image.message = "getting physical size";
1009 abdb293f Chrysostomos Nanakos
                        image.error   = err;
1010 abdb293f Chrysostomos Nanakos
                        goto end;
1011 abdb293f Chrysostomos Nanakos
                }
1012 abdb293f Chrysostomos Nanakos
1013 abdb293f Chrysostomos Nanakos
                err = vhd_util_scan_get_hidden(&vhd, &image);
1014 abdb293f Chrysostomos Nanakos
                if (err) {
1015 abdb293f Chrysostomos Nanakos
                        ret           = -EAGAIN;
1016 abdb293f Chrysostomos Nanakos
                        image.message = "checking 'hidden' field";
1017 abdb293f Chrysostomos Nanakos
                        image.error   = err;
1018 abdb293f Chrysostomos Nanakos
                        goto end;
1019 abdb293f Chrysostomos Nanakos
                }
1020 abdb293f Chrysostomos Nanakos
1021 abdb293f Chrysostomos Nanakos
                if (flags & VHD_SCAN_MARKERS) {
1022 abdb293f Chrysostomos Nanakos
                        err = vhd_util_scan_get_marker(&vhd, &image);
1023 abdb293f Chrysostomos Nanakos
                        if (err) {
1024 abdb293f Chrysostomos Nanakos
                                ret           = -EAGAIN;
1025 abdb293f Chrysostomos Nanakos
                                image.message = "checking marker";
1026 abdb293f Chrysostomos Nanakos
                                image.error   = err;
1027 abdb293f Chrysostomos Nanakos
                                goto end;
1028 abdb293f Chrysostomos Nanakos
                        }
1029 abdb293f Chrysostomos Nanakos
                }
1030 abdb293f Chrysostomos Nanakos
1031 abdb293f Chrysostomos Nanakos
                if (vhd.footer.type == HD_TYPE_DIFF) {
1032 abdb293f Chrysostomos Nanakos
                        err = vhd_util_scan_get_parent(&vhd, &image);
1033 abdb293f Chrysostomos Nanakos
                        if (err) {
1034 abdb293f Chrysostomos Nanakos
                                ret           = -EAGAIN;
1035 abdb293f Chrysostomos Nanakos
                                image.message = "getting parent";
1036 abdb293f Chrysostomos Nanakos
                                image.error   = err;
1037 abdb293f Chrysostomos Nanakos
                                goto end;
1038 abdb293f Chrysostomos Nanakos
                        }
1039 abdb293f Chrysostomos Nanakos
                }
1040 abdb293f Chrysostomos Nanakos
1041 abdb293f Chrysostomos Nanakos
        end:
1042 abdb293f Chrysostomos Nanakos
                vhd_util_scan_print_image(&image);
1043 abdb293f Chrysostomos Nanakos
1044 abdb293f Chrysostomos Nanakos
                if (flags & VHD_SCAN_PARENTS && image.parent)
1045 abdb293f Chrysostomos Nanakos
                        vhd_util_scan_add_parent(&itr, &vhd, &image);
1046 abdb293f Chrysostomos Nanakos
1047 abdb293f Chrysostomos Nanakos
                if (vhd.file)
1048 abdb293f Chrysostomos Nanakos
                        vhd_close(&vhd);
1049 abdb293f Chrysostomos Nanakos
                if (image.name != target->name)
1050 abdb293f Chrysostomos Nanakos
                        free(image.name);
1051 abdb293f Chrysostomos Nanakos
                free(image.parent);
1052 abdb293f Chrysostomos Nanakos
1053 abdb293f Chrysostomos Nanakos
                if (err && !(flags & VHD_SCAN_NOFAIL))
1054 abdb293f Chrysostomos Nanakos
                        break;
1055 abdb293f Chrysostomos Nanakos
        }
1056 abdb293f Chrysostomos Nanakos
1057 abdb293f Chrysostomos Nanakos
        iterator_free(&itr);
1058 abdb293f Chrysostomos Nanakos
1059 abdb293f Chrysostomos Nanakos
        if (flags & VHD_SCAN_NOFAIL)
1060 abdb293f Chrysostomos Nanakos
                return ret;
1061 abdb293f Chrysostomos Nanakos
1062 abdb293f Chrysostomos Nanakos
        return err;
1063 abdb293f Chrysostomos Nanakos
}
1064 abdb293f Chrysostomos Nanakos
1065 abdb293f Chrysostomos Nanakos
static int
1066 abdb293f Chrysostomos Nanakos
vhd_util_scan_targets_pretty(int cnt, struct target *targets)
1067 abdb293f Chrysostomos Nanakos
{
1068 abdb293f Chrysostomos Nanakos
        int err;
1069 abdb293f Chrysostomos Nanakos
1070 abdb293f Chrysostomos Nanakos
        err = vhd_util_scan_pretty_allocate_list(cnt);
1071 abdb293f Chrysostomos Nanakos
        if (err) {
1072 abdb293f Chrysostomos Nanakos
                printf("scan failed: no memory\n");
1073 abdb293f Chrysostomos Nanakos
                return -ENOMEM;
1074 abdb293f Chrysostomos Nanakos
        }
1075 abdb293f Chrysostomos Nanakos
1076 abdb293f Chrysostomos Nanakos
        err = vhd_util_scan_targets(cnt, targets);
1077 abdb293f Chrysostomos Nanakos
1078 abdb293f Chrysostomos Nanakos
        vhd_util_scan_pretty_print_images();
1079 abdb293f Chrysostomos Nanakos
        vhd_util_scan_pretty_free_list();
1080 abdb293f Chrysostomos Nanakos
1081 abdb293f Chrysostomos Nanakos
        return ((flags & VHD_SCAN_NOFAIL) ? 0 : err);
1082 abdb293f Chrysostomos Nanakos
}
1083 abdb293f Chrysostomos Nanakos
1084 abdb293f Chrysostomos Nanakos
static int
1085 abdb293f Chrysostomos Nanakos
vhd_util_scan_find_file_targets(int cnt, char **names,
1086 abdb293f Chrysostomos Nanakos
                                const char *filter,
1087 abdb293f Chrysostomos Nanakos
                                struct target **_targets, int *_total)
1088 abdb293f Chrysostomos Nanakos
{
1089 abdb293f Chrysostomos Nanakos
        glob_t g;
1090 abdb293f Chrysostomos Nanakos
        struct target *targets;
1091 abdb293f Chrysostomos Nanakos
        int i, globs, err, total;
1092 abdb293f Chrysostomos Nanakos
1093 abdb293f Chrysostomos Nanakos
        total     = cnt;
1094 abdb293f Chrysostomos Nanakos
        globs     = 0;
1095 abdb293f Chrysostomos Nanakos
        *_total   = 0;
1096 abdb293f Chrysostomos Nanakos
        *_targets = NULL;
1097 abdb293f Chrysostomos Nanakos
        
1098 abdb293f Chrysostomos Nanakos
        memset(&g, 0, sizeof(g));
1099 abdb293f Chrysostomos Nanakos
1100 abdb293f Chrysostomos Nanakos
        if (filter) {
1101 abdb293f Chrysostomos Nanakos
                int gflags = ((flags & VHD_SCAN_FAST) ? GLOB_NOSORT : 0);
1102 abdb293f Chrysostomos Nanakos
1103 abdb293f Chrysostomos Nanakos
                errno = 0;
1104 abdb293f Chrysostomos Nanakos
                err   = glob(filter, gflags, vhd_util_scan_error, &g);
1105 abdb293f Chrysostomos Nanakos
1106 abdb293f Chrysostomos Nanakos
                switch (err) {
1107 abdb293f Chrysostomos Nanakos
                case GLOB_NOSPACE:
1108 abdb293f Chrysostomos Nanakos
                        err = -ENOMEM;
1109 abdb293f Chrysostomos Nanakos
                        break;
1110 abdb293f Chrysostomos Nanakos
                case GLOB_ABORTED:
1111 abdb293f Chrysostomos Nanakos
                        err = -EIO;
1112 abdb293f Chrysostomos Nanakos
                        break;
1113 abdb293f Chrysostomos Nanakos
                case GLOB_NOMATCH:
1114 abdb293f Chrysostomos Nanakos
                        err = -errno;
1115 abdb293f Chrysostomos Nanakos
                        break;
1116 abdb293f Chrysostomos Nanakos
                }
1117 abdb293f Chrysostomos Nanakos
1118 abdb293f Chrysostomos Nanakos
                if (err) {
1119 abdb293f Chrysostomos Nanakos
                        vhd_util_scan_error(filter, err);
1120 abdb293f Chrysostomos Nanakos
                        return err;
1121 abdb293f Chrysostomos Nanakos
                }
1122 abdb293f Chrysostomos Nanakos
1123 abdb293f Chrysostomos Nanakos
                globs  = g.gl_pathc;
1124 abdb293f Chrysostomos Nanakos
                total += globs;
1125 abdb293f Chrysostomos Nanakos
        }
1126 abdb293f Chrysostomos Nanakos
1127 abdb293f Chrysostomos Nanakos
        targets = calloc(total, sizeof(struct target));
1128 abdb293f Chrysostomos Nanakos
        if (!targets) {
1129 abdb293f Chrysostomos Nanakos
                err = -ENOMEM;
1130 abdb293f Chrysostomos Nanakos
                goto out;
1131 abdb293f Chrysostomos Nanakos
        }
1132 abdb293f Chrysostomos Nanakos
1133 abdb293f Chrysostomos Nanakos
        for (i = 0; i < g.gl_pathc; i++) {
1134 abdb293f Chrysostomos Nanakos
                err = vhd_util_scan_init_file_target(targets + i,
1135 abdb293f Chrysostomos Nanakos
                                                     g.gl_pathv[i],
1136 abdb293f Chrysostomos Nanakos
                                                     VHD_TYPE_VHD_FILE);
1137 abdb293f Chrysostomos Nanakos
                if (err) {
1138 abdb293f Chrysostomos Nanakos
                        vhd_util_scan_error(g.gl_pathv[i], err);
1139 abdb293f Chrysostomos Nanakos
                        if (!(flags & VHD_SCAN_NOFAIL))
1140 abdb293f Chrysostomos Nanakos
                                goto out;
1141 abdb293f Chrysostomos Nanakos
                }
1142 abdb293f Chrysostomos Nanakos
        }
1143 abdb293f Chrysostomos Nanakos
1144 abdb293f Chrysostomos Nanakos
        for (i = 0; i + globs < total; i++) {
1145 abdb293f Chrysostomos Nanakos
                err = vhd_util_scan_init_file_target(targets + i + globs,
1146 abdb293f Chrysostomos Nanakos
                                                     names[i],
1147 abdb293f Chrysostomos Nanakos
                                                     VHD_TYPE_VHD_FILE);
1148 abdb293f Chrysostomos Nanakos
                if (err) {
1149 abdb293f Chrysostomos Nanakos
                        vhd_util_scan_error(names[i], err);
1150 abdb293f Chrysostomos Nanakos
                        if (!(flags & VHD_SCAN_NOFAIL))
1151 abdb293f Chrysostomos Nanakos
                                goto out;
1152 abdb293f Chrysostomos Nanakos
                }
1153 abdb293f Chrysostomos Nanakos
        }
1154 abdb293f Chrysostomos Nanakos
1155 abdb293f Chrysostomos Nanakos
        err       = 0;
1156 abdb293f Chrysostomos Nanakos
        *_total   = total;
1157 abdb293f Chrysostomos Nanakos
        *_targets = targets;
1158 abdb293f Chrysostomos Nanakos
1159 abdb293f Chrysostomos Nanakos
out:
1160 abdb293f Chrysostomos Nanakos
        if (err)
1161 abdb293f Chrysostomos Nanakos
                free(targets);
1162 abdb293f Chrysostomos Nanakos
        if (filter)
1163 abdb293f Chrysostomos Nanakos
                globfree(&g);
1164 abdb293f Chrysostomos Nanakos
1165 abdb293f Chrysostomos Nanakos
        return err;
1166 abdb293f Chrysostomos Nanakos
}
1167 abdb293f Chrysostomos Nanakos
1168 abdb293f Chrysostomos Nanakos
static inline void
1169 abdb293f Chrysostomos Nanakos
swap_volume(struct lv *lvs, int dst, int src)
1170 abdb293f Chrysostomos Nanakos
{
1171 abdb293f Chrysostomos Nanakos
        struct lv copy, *ldst, *lsrc;
1172 abdb293f Chrysostomos Nanakos
1173 abdb293f Chrysostomos Nanakos
        if (dst == src)
1174 abdb293f Chrysostomos Nanakos
                return;
1175 abdb293f Chrysostomos Nanakos
1176 abdb293f Chrysostomos Nanakos
        lsrc = lvs + src;
1177 abdb293f Chrysostomos Nanakos
        ldst = lvs + dst;
1178 abdb293f Chrysostomos Nanakos
1179 abdb293f Chrysostomos Nanakos
        memcpy(&copy, ldst, sizeof(copy));
1180 abdb293f Chrysostomos Nanakos
        memcpy(ldst, lsrc, sizeof(*ldst));
1181 abdb293f Chrysostomos Nanakos
        memcpy(lsrc, &copy, sizeof(copy));
1182 abdb293f Chrysostomos Nanakos
}
1183 abdb293f Chrysostomos Nanakos
1184 abdb293f Chrysostomos Nanakos
static int
1185 abdb293f Chrysostomos Nanakos
vhd_util_scan_sort_volumes(struct lv *lvs, int cnt,
1186 abdb293f Chrysostomos Nanakos
                           const char *filter, int *_matches)
1187 abdb293f Chrysostomos Nanakos
{
1188 abdb293f Chrysostomos Nanakos
        struct lv *lv;
1189 abdb293f Chrysostomos Nanakos
        int i, err, matches;
1190 abdb293f Chrysostomos Nanakos
1191 abdb293f Chrysostomos Nanakos
        matches   = 0;
1192 abdb293f Chrysostomos Nanakos
        *_matches = 0;
1193 abdb293f Chrysostomos Nanakos
1194 abdb293f Chrysostomos Nanakos
        if (!filter)
1195 abdb293f Chrysostomos Nanakos
                return 0;
1196 abdb293f Chrysostomos Nanakos
1197 abdb293f Chrysostomos Nanakos
        for (i = 0; i < cnt; i++) {
1198 abdb293f Chrysostomos Nanakos
                lv  = lvs + i;
1199 abdb293f Chrysostomos Nanakos
1200 abdb293f Chrysostomos Nanakos
                err = fnmatch(filter, lv->name, FNM_PATHNAME);
1201 abdb293f Chrysostomos Nanakos
                if (err) {
1202 abdb293f Chrysostomos Nanakos
                        if (err != FNM_NOMATCH) {
1203 abdb293f Chrysostomos Nanakos
                                EPRINTF("fnmatch failed: '%s', '%s'\n", 
1204 abdb293f Chrysostomos Nanakos
                                                filter, lv->name);
1205 abdb293f Chrysostomos Nanakos
                                vhd_util_scan_error(lv->name, err);
1206 abdb293f Chrysostomos Nanakos
                                if (!(flags & VHD_SCAN_NOFAIL))
1207 abdb293f Chrysostomos Nanakos
                                        return err;
1208 abdb293f Chrysostomos Nanakos
                        }
1209 abdb293f Chrysostomos Nanakos
1210 abdb293f Chrysostomos Nanakos
                        continue;
1211 abdb293f Chrysostomos Nanakos
                }
1212 abdb293f Chrysostomos Nanakos
1213 abdb293f Chrysostomos Nanakos
                swap_volume(lvs, matches++, i);
1214 abdb293f Chrysostomos Nanakos
        }
1215 abdb293f Chrysostomos Nanakos
1216 abdb293f Chrysostomos Nanakos
        *_matches = matches;
1217 abdb293f Chrysostomos Nanakos
        return 0;
1218 abdb293f Chrysostomos Nanakos
}
1219 abdb293f Chrysostomos Nanakos
1220 abdb293f Chrysostomos Nanakos
static int
1221 abdb293f Chrysostomos Nanakos
vhd_util_scan_find_volume_targets(int cnt, char **names,
1222 abdb293f Chrysostomos Nanakos
                                  const char *volume, const char *filter,
1223 abdb293f Chrysostomos Nanakos
                                  struct target **_targets, int *_total)
1224 abdb293f Chrysostomos Nanakos
{
1225 abdb293f Chrysostomos Nanakos
        struct target *targets;
1226 abdb293f Chrysostomos Nanakos
        int i, err, total, matches;
1227 abdb293f Chrysostomos Nanakos
1228 abdb293f Chrysostomos Nanakos
        *_total   = 0;
1229 abdb293f Chrysostomos Nanakos
        *_targets = NULL;
1230 abdb293f Chrysostomos Nanakos
        targets   = NULL;
1231 abdb293f Chrysostomos Nanakos
1232 abdb293f Chrysostomos Nanakos
        err = lvm_scan_vg(volume, &vg);
1233 abdb293f Chrysostomos Nanakos
        if (err)
1234 abdb293f Chrysostomos Nanakos
                return err;
1235 abdb293f Chrysostomos Nanakos
1236 abdb293f Chrysostomos Nanakos
        err = vhd_util_scan_sort_volumes(vg.lvs, vg.lv_cnt,
1237 abdb293f Chrysostomos Nanakos
                                         filter, &matches);
1238 abdb293f Chrysostomos Nanakos
        if (err)
1239 abdb293f Chrysostomos Nanakos
                goto out;
1240 abdb293f Chrysostomos Nanakos
1241 abdb293f Chrysostomos Nanakos
        total = matches;
1242 abdb293f Chrysostomos Nanakos
        for (i = 0; i < cnt; i++) {
1243 abdb293f Chrysostomos Nanakos
                err = vhd_util_scan_sort_volumes(vg.lvs + total,
1244 abdb293f Chrysostomos Nanakos
                                                 vg.lv_cnt - total,
1245 abdb293f Chrysostomos Nanakos
                                                 names[i], &matches);
1246 abdb293f Chrysostomos Nanakos
                if (err)
1247 abdb293f Chrysostomos Nanakos
                        goto out;
1248 abdb293f Chrysostomos Nanakos
1249 abdb293f Chrysostomos Nanakos
                total += matches;
1250 abdb293f Chrysostomos Nanakos
        }
1251 abdb293f Chrysostomos Nanakos
1252 abdb293f Chrysostomos Nanakos
        targets = calloc(total, sizeof(struct target));
1253 abdb293f Chrysostomos Nanakos
        if (!targets) {
1254 abdb293f Chrysostomos Nanakos
                err = -ENOMEM;
1255 abdb293f Chrysostomos Nanakos
                goto out;
1256 abdb293f Chrysostomos Nanakos
        }
1257 abdb293f Chrysostomos Nanakos
1258 abdb293f Chrysostomos Nanakos
        for (i = 0; i < total; i++) {
1259 abdb293f Chrysostomos Nanakos
                err = vhd_util_scan_init_volume_target(targets + i,
1260 abdb293f Chrysostomos Nanakos
                                                       vg.lvs + i,
1261 abdb293f Chrysostomos Nanakos
                                                       VHD_TYPE_VHD_VOLUME);
1262 abdb293f Chrysostomos Nanakos
                if (err) {
1263 abdb293f Chrysostomos Nanakos
                        vhd_util_scan_error(vg.lvs[i].name, err);
1264 abdb293f Chrysostomos Nanakos
                        if (!(flags & VHD_SCAN_NOFAIL))
1265 abdb293f Chrysostomos Nanakos
                                goto out;
1266 abdb293f Chrysostomos Nanakos
                }
1267 abdb293f Chrysostomos Nanakos
        }
1268 abdb293f Chrysostomos Nanakos
1269 abdb293f Chrysostomos Nanakos
        err       = 0;
1270 abdb293f Chrysostomos Nanakos
        *_total   = total;
1271 abdb293f Chrysostomos Nanakos
        *_targets = targets;
1272 abdb293f Chrysostomos Nanakos
1273 abdb293f Chrysostomos Nanakos
out:
1274 abdb293f Chrysostomos Nanakos
        if (err)
1275 abdb293f Chrysostomos Nanakos
                free(targets);
1276 abdb293f Chrysostomos Nanakos
        return err;
1277 abdb293f Chrysostomos Nanakos
}
1278 abdb293f Chrysostomos Nanakos
1279 abdb293f Chrysostomos Nanakos
static int
1280 abdb293f Chrysostomos Nanakos
vhd_util_scan_find_targets(int cnt, char **names,
1281 abdb293f Chrysostomos Nanakos
                           const char *volume, const char *filter,
1282 abdb293f Chrysostomos Nanakos
                           struct target **targets, int *total)
1283 abdb293f Chrysostomos Nanakos
{
1284 abdb293f Chrysostomos Nanakos
        if (flags & VHD_SCAN_VOLUME)
1285 abdb293f Chrysostomos Nanakos
                return vhd_util_scan_find_volume_targets(cnt, names,
1286 abdb293f Chrysostomos Nanakos
                                                         volume, filter,
1287 abdb293f Chrysostomos Nanakos
                                                         targets, total);
1288 abdb293f Chrysostomos Nanakos
        return vhd_util_scan_find_file_targets(cnt, names,
1289 abdb293f Chrysostomos Nanakos
                                               filter, targets, total);
1290 abdb293f Chrysostomos Nanakos
}
1291 abdb293f Chrysostomos Nanakos
1292 abdb293f Chrysostomos Nanakos
int
1293 abdb293f Chrysostomos Nanakos
vhd_util_scan(int argc, char **argv)
1294 abdb293f Chrysostomos Nanakos
{
1295 abdb293f Chrysostomos Nanakos
        int c, err, cnt;
1296 abdb293f Chrysostomos Nanakos
        char *filter, *volume;
1297 abdb293f Chrysostomos Nanakos
        struct target *targets;
1298 abdb293f Chrysostomos Nanakos
1299 abdb293f Chrysostomos Nanakos
        cnt     = 0;
1300 abdb293f Chrysostomos Nanakos
        err     = 0;
1301 abdb293f Chrysostomos Nanakos
        flags   = 0;
1302 abdb293f Chrysostomos Nanakos
        filter  = NULL;
1303 abdb293f Chrysostomos Nanakos
        volume  = NULL;
1304 abdb293f Chrysostomos Nanakos
        targets = NULL;
1305 abdb293f Chrysostomos Nanakos
1306 abdb293f Chrysostomos Nanakos
        optind = 0;
1307 abdb293f Chrysostomos Nanakos
        while ((c = getopt(argc, argv, "m:fcl:pavMh")) != -1) {
1308 abdb293f Chrysostomos Nanakos
                switch (c) {
1309 abdb293f Chrysostomos Nanakos
                case 'm':
1310 abdb293f Chrysostomos Nanakos
                        filter = optarg;
1311 abdb293f Chrysostomos Nanakos
                        break;
1312 abdb293f Chrysostomos Nanakos
                case 'f':
1313 abdb293f Chrysostomos Nanakos
                        flags |= VHD_SCAN_FAST;
1314 abdb293f Chrysostomos Nanakos
                        break;
1315 abdb293f Chrysostomos Nanakos
                case 'c':
1316 abdb293f Chrysostomos Nanakos
                        flags |= VHD_SCAN_NOFAIL;
1317 abdb293f Chrysostomos Nanakos
                        break;
1318 abdb293f Chrysostomos Nanakos
                case 'l':
1319 abdb293f Chrysostomos Nanakos
                        volume = optarg;
1320 abdb293f Chrysostomos Nanakos
                        flags |= VHD_SCAN_VOLUME;
1321 abdb293f Chrysostomos Nanakos
                        break;
1322 abdb293f Chrysostomos Nanakos
                case 'p':
1323 abdb293f Chrysostomos Nanakos
                        flags |= VHD_SCAN_PRETTY;
1324 abdb293f Chrysostomos Nanakos
                        break;
1325 abdb293f Chrysostomos Nanakos
                case 'a':
1326 abdb293f Chrysostomos Nanakos
                        flags |= VHD_SCAN_PARENTS;
1327 abdb293f Chrysostomos Nanakos
                        break;
1328 abdb293f Chrysostomos Nanakos
                case 'v':
1329 abdb293f Chrysostomos Nanakos
                        flags |= VHD_SCAN_VERBOSE;
1330 abdb293f Chrysostomos Nanakos
                        break;
1331 abdb293f Chrysostomos Nanakos
                case 'M':
1332 abdb293f Chrysostomos Nanakos
                        flags |= VHD_SCAN_MARKERS;
1333 abdb293f Chrysostomos Nanakos
                        break;
1334 abdb293f Chrysostomos Nanakos
                case 'h':
1335 abdb293f Chrysostomos Nanakos
                        goto usage;
1336 abdb293f Chrysostomos Nanakos
                default:
1337 abdb293f Chrysostomos Nanakos
                        err = -EINVAL;
1338 abdb293f Chrysostomos Nanakos
                        goto usage;
1339 abdb293f Chrysostomos Nanakos
                }
1340 abdb293f Chrysostomos Nanakos
        }
1341 abdb293f Chrysostomos Nanakos
1342 abdb293f Chrysostomos Nanakos
        if (!filter && argc - optind == 0) {
1343 abdb293f Chrysostomos Nanakos
                err = -EINVAL;
1344 abdb293f Chrysostomos Nanakos
                goto usage;
1345 abdb293f Chrysostomos Nanakos
        }
1346 abdb293f Chrysostomos Nanakos
1347 abdb293f Chrysostomos Nanakos
        if (flags & VHD_SCAN_PRETTY)
1348 abdb293f Chrysostomos Nanakos
                flags &= ~VHD_SCAN_FAST;
1349 abdb293f Chrysostomos Nanakos
1350 abdb293f Chrysostomos Nanakos
        err = vhd_util_scan_find_targets(argc - optind, argv + optind,
1351 abdb293f Chrysostomos Nanakos
                                         volume, filter, &targets, &cnt);
1352 abdb293f Chrysostomos Nanakos
        if (err) {
1353 abdb293f Chrysostomos Nanakos
                printf("scan failed: %d\n", err);
1354 abdb293f Chrysostomos Nanakos
                return err;
1355 abdb293f Chrysostomos Nanakos
        }
1356 abdb293f Chrysostomos Nanakos
1357 abdb293f Chrysostomos Nanakos
        if (!cnt)
1358 abdb293f Chrysostomos Nanakos
                return 0;
1359 abdb293f Chrysostomos Nanakos
1360 abdb293f Chrysostomos Nanakos
        if (flags & VHD_SCAN_PRETTY)
1361 abdb293f Chrysostomos Nanakos
                err = vhd_util_scan_targets_pretty(cnt, targets);
1362 abdb293f Chrysostomos Nanakos
        else
1363 abdb293f Chrysostomos Nanakos
                err = vhd_util_scan_targets(cnt, targets);
1364 abdb293f Chrysostomos Nanakos
1365 abdb293f Chrysostomos Nanakos
        free(targets);
1366 abdb293f Chrysostomos Nanakos
        lvm_free_vg(&vg);
1367 abdb293f Chrysostomos Nanakos
1368 abdb293f Chrysostomos Nanakos
        return ((flags & VHD_SCAN_NOFAIL) ? 0 : err);
1369 abdb293f Chrysostomos Nanakos
1370 abdb293f Chrysostomos Nanakos
usage:
1371 abdb293f Chrysostomos Nanakos
        printf("usage: [OPTIONS] FILES\n"
1372 abdb293f Chrysostomos Nanakos
               "options: [-m match filter] [-f fast] [-c continue on failure] "
1373 abdb293f Chrysostomos Nanakos
               "[-l LVM volume] [-p pretty print] [-a scan parents] "
1374 abdb293f Chrysostomos Nanakos
               "[-v verbose] [-h help] [-M show markers]\n");
1375 abdb293f Chrysostomos Nanakos
        return err;
1376 abdb293f Chrysostomos Nanakos
}