/* * Copyright (C) 2017 Karel Zak * * This file may be redistributed under the terms of the * GNU Lesser General Public License. * * * Libfdisk sample to create partitions by specify size, for example: * * mkpart --label dos --device /dev/sdc 2M 2M 2M 10M 1M - * * creates 6 partitions: * - 3 primary (3x 2M) * - 1 extended (1x 10M) * - 2 logical (1x 1M, 1x remaining-space-in-extended-partition) * * Notes: * The sample specifies size and partno for MBR, and size only for another * labels (e.g. GPT). * * The Ask-API does not use anything else than warning/info. The * partitionning has to be done non-interactive. */ #include #include #include #include #include #include #include #include #include "c.h" #include "nls.h" #include "strutils.h" #include "xalloc.h" #include "libfdisk.h" static int ask_callback(struct fdisk_context *cxt __attribute__((__unused__)), struct fdisk_ask *ask, void *data) { switch(fdisk_ask_get_type(ask)) { case FDISK_ASKTYPE_INFO: fputs(fdisk_ask_print_get_mesg(ask), stdout); fputc('\n', stdout); break; case FDISK_ASKTYPE_WARNX: fflush(stdout); fputs(fdisk_ask_print_get_mesg(ask), stderr); fputc('\n', stderr); break; case FDISK_ASKTYPE_WARN: fflush(stdout); fputs(fdisk_ask_print_get_mesg(ask), stderr); errno = fdisk_ask_print_get_errno(ask); fprintf(stderr, ": %m\n"); break; default: break; } return 0; } int main(int argc, char *argv[]) { struct fdisk_context *cxt; struct fdisk_partition *pa; const char *label = NULL, *device = NULL; int n = 0, c, nopartno = 0; unsigned int sectorsize; uint64_t grain = 0; static const struct option longopts[] = { { "label", required_argument, NULL, 'x' }, { "device", required_argument, NULL, 'd' }, { "nopartno", no_argument, NULL, 'p' }, { "grain", required_argument, NULL, 'g' }, { "help", no_argument, NULL, 'h' }, { NULL, 0, NULL, 0 }, }; setlocale(LC_ALL, ""); /* just to have enable UTF8 chars */ fdisk_init_debug(0); while((c = getopt_long(argc, argv, "g:x:d:h", longopts, NULL)) != -1) { switch(c) { case 'x': label = optarg; break; case 'd': device = optarg; break; case 'p': nopartno = 1; break; case 'g': grain = strtosize_or_err(optarg, "failed to parse grain"); break; case 'h': printf("%s [options] ...", program_invocation_short_name); fputs(USAGE_SEPARATOR, stdout); fputs("Make disklabel and partitions.\n", stdout); fputs(USAGE_OPTIONS, stdout); fputs(" -x, --label disk label type\n", stdout); fputs(" -d, --device block device\n", stdout); fputs(" -p, --nopartno don't set partno (use default)\n", stdout); fputs(" -h, --help this help\n", stdout); fputs(USAGE_SEPARATOR, stdout); return EXIT_SUCCESS; } } if (!device) errx(EXIT_FAILURE, "no device specified"); if (!label) label = "dos"; cxt = fdisk_new_context(); if (!cxt) err_oom(); fdisk_set_ask(cxt, ask_callback, NULL); if (grain) fdisk_save_user_grain(cxt, grain); pa = fdisk_new_partition(); if (!pa) err_oom(); if (fdisk_assign_device(cxt, device, 0)) err(EXIT_FAILURE, "failed to assign device"); if (fdisk_create_disklabel(cxt, label)) err(EXIT_FAILURE, "failed to create disk label"); sectorsize = fdisk_get_sector_size(cxt); fdisk_disable_dialogs(cxt, 1); while (optind < argc) { int rc; uint64_t size; const char *str = argv[optind]; /* defaults */ fdisk_partition_start_follow_default(pa, 1); fdisk_partition_end_follow_default(pa, 1); fdisk_partition_partno_follow_default(pa, 1); /* set size */ if (isdigit(*str)) { size = strtosize_or_err(argv[optind], "failed to parse partition size"); fdisk_partition_set_size(pa, size / sectorsize); fdisk_partition_end_follow_default(pa, 0); } else if (*str == '-') { fdisk_partition_end_follow_default(pa, 1); } if (fdisk_is_label(cxt, DOS)) { /* For MBR we want to avoid primary/logical dialog. * This is possible by explicitly specified partition * number, <4 means primary, >=4 means logical. */ if (!nopartno) { fdisk_partition_partno_follow_default(pa, 0); fdisk_partition_set_partno(pa, n); } /* Make sure last primary partition is extended if user * wants more than 4 partitions. */ if (n == 3 && optind + 1 < argc) { struct fdisk_parttype *type = fdisk_label_parse_parttype( fdisk_get_label(cxt, NULL), "05"); if (!type) err_oom(); fdisk_partition_set_type(pa, type); fdisk_unref_parttype(type); } } rc = fdisk_add_partition(cxt, pa, NULL); if (rc) { errno = -rc; errx(EXIT_FAILURE, "failed to add #%d partition", n + 1); } fdisk_reset_partition(pa); optind++; n++; } if (fdisk_write_disklabel(cxt)) err(EXIT_FAILURE, "failed to write disk label"); fdisk_deassign_device(cxt, 1); fdisk_unref_context(cxt); fdisk_unref_partition(pa); return EXIT_SUCCESS; }