]>
Commit | Line | Data |
---|---|---|
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 | ||
40 | static 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 | ||
66 | int 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 | } |