2 * Source: copy of util-linux' partx partx.c
4 * Copyrights of the original file applies
5 * Copyright (c) 2004, 2005 Christophe Varoqui
6 * Copyright (c) 2005 Kiyoshi Ueda
7 * Copyright (c) 2005 Lars Soltau
11 * Given a block device and a partition table type,
12 * try to parse the partition table, and list the
13 * contents. Optionally add or remove partitions.
15 * Read wholedisk and add all partitions:
16 * kpartx [-a|-d|-l] [-v] wholedisk
29 #include <sys/types.h>
31 #include <libdevmapper.h>
32 #include <linux/kdev_t.h>
34 #include "devmapper.h"
39 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
41 #define READ_SIZE 1024
44 #define DM_TARGET "linear"
45 #define LO_NAME_SIZE 64
46 #define PARTNAME_SIZE 128
49 struct slice slices[MAXSLICES];
51 enum action { LIST, ADD, DELETE };
61 addpts(char *t, ptreader f)
63 if (ptct >= MAXTYPES) {
64 fprintf(stderr, "addpts: too many types\n");
75 addpts("gpt", read_gpt_pt);
76 addpts("dos", read_dos_pt);
77 addpts("bsd", read_bsd_pt);
78 addpts("solaris", read_solaris_pt);
79 addpts("unixware", read_unixware_pt);
82 static char short_opts[] = "ladgvnp:t:";
89 printf("usage : kpartx [-a|-d|-l] [-v] wholedisk\n");
90 printf("\t-a add partition devmappings\n");
91 printf("\t-d del partition devmappings\n");
92 printf("\t-l list partitions devmappings that would be added by -a\n");
93 printf("\t-p set device name-partition number delimiter\n");
94 printf("\t-v verbose\n");
99 set_delimiter (char * device, char * delimiter)
103 while (*(p++) != 0x0)
106 if (isdigit(*(p - 2)))
111 strip_slash (char * device)
115 while (*(p++) != 0x0) {
123 find_devname_offset (char * device)
133 return (int)(q - device) + 1;
137 get_hotplug_device(void)
139 unsigned int major, minor, off, len;
141 char *devname = NULL;
146 var = getenv("ACTION");
148 if (!var || strcmp(var, "add"))
151 /* Get dm mapname for hotpluged device. */
152 if (!(devname = getenv("DEVNAME")))
155 if (stat(devname, &buf))
158 major = (unsigned int)MAJOR(buf.st_rdev);
159 minor = (unsigned int)MINOR(buf.st_rdev);
161 if (!(mapname = dm_mapname(major, minor))) /* Not dm device. */
164 off = find_devname_offset(devname);
165 len = strlen(mapname);
167 /* Dirname + mapname + \0 */
168 if (!(device = (char *)malloc(sizeof(char) * (off + len + 1))))
171 /* Create new device name. */
172 snprintf(device, off + 1, "%s", devname);
173 snprintf(device + off, len + 1, "%s", mapname);
175 if (strlen(device) != (off + len))
182 main(int argc, char **argv){
183 int fd, i, j, k, n, op, off, arg;
186 enum action what = LIST;
187 char *p, *type, *diskdevice, *device, *progname;
190 char partname[PARTNAME_SIZE], params[PARTNAME_SIZE + 16];
191 char * loopdev = NULL;
201 type = device = diskdevice = NULL;
202 memset(&all, 0, sizeof(all));
203 memset(&partname, 0, sizeof(partname));
205 /* Check whether hotplug mode. */
206 progname = strrchr(argv[0], '/');
213 if (!strcmp(progname, "kpartx.dev")) { /* Hotplug mode */
216 /* Setup for original kpartx variables */
217 if (!(device = get_hotplug_device()))
222 } else if (argc < 2) {
227 while ((arg = getopt(argc, argv, short_opts)) != EOF) switch(arg) {
240 if ((p[1] == '-') && p[2])
262 if (dm_prereq(DM_TARGET, 0, 0, 0) && (what == ADD || what == DELETE)) {
263 fprintf(stderr, "device mapper prerequisites not met\n");
268 /* already got [disk]device */
269 } else if (optind == argc-2) {
270 device = argv[optind];
271 diskdevice = argv[optind+1];
272 } else if (optind == argc-1) {
273 diskdevice = device = argv[optind];
279 if (stat(device, &buf)) {
280 printf("failed to stat() %s\n", device);
284 if (S_ISREG (buf.st_mode)) {
285 loopdev = malloc(LO_NAME_SIZE * sizeof(char));
290 /* already looped file ? */
291 loopdev = find_loop_by_file(device);
293 if (!loopdev && what == DELETE)
297 loopdev = find_unused_loop_device();
299 if (set_loop(loopdev, device, 0, &loopro)) {
300 fprintf(stderr, "can't set up loop\n");
308 delim = malloc(DELIM_SIZE);
309 memset(delim, 0, DELIM_SIZE);
310 set_delimiter(device, delim);
313 off = find_devname_offset(device);
314 fd = open(device, O_RDONLY);
323 /* add/remove partitions to the kernel devmapper tables */
324 for (i = 0; i < ptct; i++) {
327 if (type && strcmp(type, ptp->type))
330 /* here we get partitions */
331 n = ptp->fn(fd, all, slices, SIZE(slices));
335 printf("%s: %d slices\n", ptp->type, n);
344 * test for overlap, as in the case of an extended partition
345 * zero their size to avoid mapping
347 for (j=0; j<n; j++) {
348 for (k=j+1; k<n; k++) {
349 if (slices[k].start > slices[j].start &&
350 slices[k].start < slices[j].start +
358 for (j = 0; j < n; j++) {
359 if (slices[j].size == 0)
362 printf("%s%s%d : 0 %lu %s %lu\n",
363 device + off, delim, j+1,
364 (unsigned long) slices[j].size, device,
365 (unsigned long) slices[j].start);
370 for (j = 0; j < n; j++) {
371 if (safe_sprintf(partname, "%s%s%d",
372 device + off , delim, j+1)) {
373 fprintf(stderr, "partname too small\n");
376 strip_slash(partname);
378 if (!slices[j].size || !dm_map_present(partname))
381 if (!dm_simplecmd(DM_DEVICE_REMOVE, partname))
385 printf("del devmap : %s\n", partname);
388 if (S_ISREG (buf.st_mode)) {
389 if (del_loop(device)) {
391 printf("can't del loop : %s\n",
395 printf("loop deleted : %s\n", device);
400 for (j=0; j<n; j++) {
401 if (slices[j].size == 0)
404 if (safe_sprintf(partname, "%s%s%d",
405 device + off , delim, j+1)) {
406 fprintf(stderr, "partname too small\n");
409 strip_slash(partname);
411 if (safe_sprintf(params, "%s %lu", device,
412 (unsigned long)slices[j].start)) {
413 fprintf(stderr, "params too small\n");
417 op = (dm_map_present(partname) ?
418 DM_DEVICE_RELOAD : DM_DEVICE_CREATE);
420 dm_addmap(op, partname, DM_TARGET, params,
423 if (op == DM_DEVICE_RELOAD)
424 dm_simplecmd(DM_DEVICE_RESUME,
428 printf("add map %s : 0 %lu %s %s\n",
429 partname, slices[j].size,
448 xmalloc (size_t size) {
457 fprintf(stderr, "Out of memory\n");
465 * sseek: seek to specified sector
467 #if !defined (__alpha__) && !defined (__ia64__) && !defined (__x86_64__) \
468 && !defined (__s390x__)
469 #include <linux/unistd.h> /* _syscall */
471 _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
472 long long *, res, uint, wh);
476 sseek(int fd, unsigned int secnr) {
478 in = ((long long) secnr << 9);
481 #if !defined (__alpha__) && !defined (__ia64__) && !defined (__x86_64__) \
482 && !defined (__s390x__)
483 if (_llseek (fd, in>>32, in & 0xffffffff, &out, SEEK_SET) != 0
486 if ((out = lseek(fd, in, SEEK_SET)) != in)
489 fprintf(stderr, "llseek error\n");
503 getblock (int fd, unsigned int secnr) {
506 for (bp = blockhead; bp; bp = bp->next)
508 if (bp->secnr == secnr)
511 if (sseek(fd, secnr))
514 bp = xmalloc(sizeof(struct block));
516 bp->next = blockhead;
518 bp->block = (char *) xmalloc(READ_SIZE);
520 if (read(fd, bp->block, READ_SIZE) != READ_SIZE) {
521 fprintf(stderr, "read error, sector %d\n", secnr);