]> git.ipfire.org Git - thirdparty/util-linux.git/blame - libfdisk/samples/mkpart.c
wipefs: add --lock and LOCK_BLOCK_DEVICE
[thirdparty/util-linux.git] / libfdisk / samples / mkpart.c
CommitLineData
1c1d30c7
KZ
1/*
2 * Copyright (C) 2017 Karel Zak <kzak@redhat.com>
3 *
4 * This file may be redistributed under the terms of the
5 * GNU Lesser General Public License.
5fb427c8
KZ
6 *
7 *
8 * Libfdisk sample to create partitions by specify size, for example:
9 *
10 * mkpart --label dos --device /dev/sdc 2M 2M 2M 10M 1M -
11 *
12 * creates 6 partitions:
13 * - 3 primary (3x 2M)
14 * - 1 extended (1x 10M)
15 * - 2 logical (1x 1M, 1x remaining-space-in-extended-partition)
16 *
17 * Notes:
18 * The sample specifies size and partno for MBR, and size only for another
19 * labels (e.g. GPT).
20 *
21 * The Ask-API does not use anything else than warning/info. The
22 * partitionning has to be done non-interactive.
23 */
1c1d30c7
KZ
24#include <stdlib.h>
25#include <unistd.h>
26#include <string.h>
27#include <errno.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <dirent.h>
31#include <getopt.h>
32
33#include "c.h"
34#include "nls.h"
35#include "strutils.h"
36#include "xalloc.h"
37
38#include "libfdisk.h"
39
40static int ask_callback(struct fdisk_context *cxt __attribute__((__unused__)),
41 struct fdisk_ask *ask,
42 void *data)
43{
44 switch(fdisk_ask_get_type(ask)) {
45 case FDISK_ASKTYPE_INFO:
46 fputs(fdisk_ask_print_get_mesg(ask), stdout);
47 fputc('\n', stdout);
48 break;
49 case FDISK_ASKTYPE_WARNX:
50 fflush(stdout);
51 fputs(fdisk_ask_print_get_mesg(ask), stderr);
52 fputc('\n', stderr);
53 break;
54 case FDISK_ASKTYPE_WARN:
55 fflush(stdout);
56 fputs(fdisk_ask_print_get_mesg(ask), stderr);
57 errno = fdisk_ask_print_get_errno(ask);
58 fprintf(stderr, ": %m\n");
59 break;
60 default:
61 break;
62 }
63 return 0;
64}
65
66int main(int argc, char *argv[])
67{
68 struct fdisk_context *cxt;
69 struct fdisk_partition *pa;
70 const char *label = NULL, *device = NULL;
dd3b72b3 71 int n = 0, c, nopartno = 0;
1c1d30c7 72 unsigned int sectorsize;
27c284b8 73 uint64_t grain = 0;
1c1d30c7
KZ
74
75 static const struct option longopts[] = {
71f08e97
SK
76 { "label", required_argument, NULL, 'x' },
77 { "device", required_argument, NULL, 'd' },
dd3b72b3 78 { "nopartno", no_argument, NULL, 'p' },
27c284b8 79 { "grain", required_argument, NULL, 'g' },
71f08e97
SK
80 { "help", no_argument, NULL, 'h' },
81 { NULL, 0, NULL, 0 },
1c1d30c7
KZ
82 };
83
84 setlocale(LC_ALL, ""); /* just to have enable UTF8 chars */
85
86 fdisk_init_debug(0);
87
27c284b8 88 while((c = getopt_long(argc, argv, "g:x:d:h", longopts, NULL)) != -1) {
1c1d30c7
KZ
89 switch(c) {
90 case 'x':
91 label = optarg;
92 break;
93 case 'd':
94 device = optarg;
95 break;
dd3b72b3
KZ
96 case 'p':
97 nopartno = 1;
98 break;
27c284b8
KZ
99 case 'g':
100 grain = strtosize_or_err(optarg, "failed to parse grain");
101 break;
1c1d30c7
KZ
102 case 'h':
103 printf("%s [options] <size> ...", program_invocation_short_name);
104 fputs(USAGE_SEPARATOR, stdout);
105 fputs("Make disklabel and partitions.\n", stdout);
106 fputs(USAGE_OPTIONS, stdout);
107 fputs(" -x, --label <dos,gpt,...> disk label type\n", stdout);
108 fputs(" -d, --device <path> block device\n", stdout);
dd3b72b3 109 fputs(" -p, --nopartno don't set partno (use default)\n", stdout);
1c1d30c7
KZ
110 fputs(" -h, --help this help\n", stdout);
111 fputs(USAGE_SEPARATOR, stdout);
112 return EXIT_SUCCESS;
113 }
114 }
115
116 if (!device)
117 errx(EXIT_FAILURE, "no device specified");
118 if (!label)
119 label = "dos";
120
121 cxt = fdisk_new_context();
122 if (!cxt)
123 err_oom();
124 fdisk_set_ask(cxt, ask_callback, NULL);
125
27c284b8
KZ
126 if (grain)
127 fdisk_save_user_grain(cxt, grain);
128
1c1d30c7
KZ
129 pa = fdisk_new_partition();
130 if (!pa)
131 err_oom();
132
133 if (fdisk_assign_device(cxt, device, 0))
134 err(EXIT_FAILURE, "failed to assign device");
f2b6a0c0 135 if (fdisk_create_disklabel(cxt, label))
1c1d30c7
KZ
136 err(EXIT_FAILURE, "failed to create disk label");
137
138 sectorsize = fdisk_get_sector_size(cxt);
139
dd3b72b3
KZ
140 fdisk_disable_dialogs(cxt, 1);
141
1c1d30c7
KZ
142 while (optind < argc) {
143 int rc;
144 uint64_t size;
145 const char *str = argv[optind];
146
147 /* defaults */
148 fdisk_partition_start_follow_default(pa, 1);
149 fdisk_partition_end_follow_default(pa, 1);
dd3b72b3 150 fdisk_partition_partno_follow_default(pa, 1);
1c1d30c7
KZ
151
152 /* set size */
153 if (isdigit(*str)) {
154 size = strtosize_or_err(argv[optind], "failed to parse partition size");
155 fdisk_partition_set_size(pa, size / sectorsize);
156 fdisk_partition_end_follow_default(pa, 0);
157
158 } else if (*str == '-') {
159 fdisk_partition_end_follow_default(pa, 1);
160 }
161
162 if (fdisk_is_label(cxt, DOS)) {
163 /* For MBR we want to avoid primary/logical dialog.
164 * This is possible by explicitly specified partition
165 * number, <4 means primary, >=4 means logical.
166 */
dd3b72b3
KZ
167 if (!nopartno) {
168 fdisk_partition_partno_follow_default(pa, 0);
169 fdisk_partition_set_partno(pa, n);
170 }
1c1d30c7
KZ
171
172 /* Make sure last primary partition is extended if user
173 * wants more than 4 partitions.
174 */
175 if (n == 3 && optind + 1 < argc) {
176 struct fdisk_parttype *type =
177 fdisk_label_parse_parttype(
178 fdisk_get_label(cxt, NULL), "05");
179 if (!type)
180 err_oom();
181 fdisk_partition_set_type(pa, type);
182 fdisk_unref_parttype(type);
183 }
dd3b72b3 184 }
1c1d30c7
KZ
185
186 rc = fdisk_add_partition(cxt, pa, NULL);
187 if (rc) {
188 errno = -rc;
288acb4e 189 errx(EXIT_FAILURE, "failed to add #%d partition", n + 1);
1c1d30c7
KZ
190 }
191
192 fdisk_reset_partition(pa);
193 optind++;
194 n++;
195 }
196
197 if (fdisk_write_disklabel(cxt))
198 err(EXIT_FAILURE, "failed to write disk label");
199
200 fdisk_deassign_device(cxt, 1);
201 fdisk_unref_context(cxt);
202 fdisk_unref_partition(pa);
203
204 return EXIT_SUCCESS;
205}