]>
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; | |
71 | int n = 0, c; | |
72 | unsigned int sectorsize; | |
73 | ||
74 | static const struct option longopts[] = { | |
71f08e97 SK |
75 | { "label", required_argument, NULL, 'x' }, |
76 | { "device", required_argument, NULL, 'd' }, | |
77 | { "help", no_argument, NULL, 'h' }, | |
78 | { NULL, 0, NULL, 0 }, | |
1c1d30c7 KZ |
79 | }; |
80 | ||
81 | setlocale(LC_ALL, ""); /* just to have enable UTF8 chars */ | |
82 | ||
83 | fdisk_init_debug(0); | |
84 | ||
85 | while((c = getopt_long(argc, argv, "x:d:h", longopts, NULL)) != -1) { | |
86 | switch(c) { | |
87 | case 'x': | |
88 | label = optarg; | |
89 | break; | |
90 | case 'd': | |
91 | device = optarg; | |
92 | break; | |
93 | case 'h': | |
94 | printf("%s [options] <size> ...", program_invocation_short_name); | |
95 | fputs(USAGE_SEPARATOR, stdout); | |
96 | fputs("Make disklabel and partitions.\n", stdout); | |
97 | fputs(USAGE_OPTIONS, stdout); | |
98 | fputs(" -x, --label <dos,gpt,...> disk label type\n", stdout); | |
99 | fputs(" -d, --device <path> block device\n", stdout); | |
100 | fputs(" -h, --help this help\n", stdout); | |
101 | fputs(USAGE_SEPARATOR, stdout); | |
102 | return EXIT_SUCCESS; | |
103 | } | |
104 | } | |
105 | ||
106 | if (!device) | |
107 | errx(EXIT_FAILURE, "no device specified"); | |
108 | if (!label) | |
109 | label = "dos"; | |
110 | ||
111 | cxt = fdisk_new_context(); | |
112 | if (!cxt) | |
113 | err_oom(); | |
114 | fdisk_set_ask(cxt, ask_callback, NULL); | |
115 | ||
116 | pa = fdisk_new_partition(); | |
117 | if (!pa) | |
118 | err_oom(); | |
119 | ||
120 | if (fdisk_assign_device(cxt, device, 0)) | |
121 | err(EXIT_FAILURE, "failed to assign device"); | |
122 | if (fdisk_create_disklabel(cxt, "dos")) | |
123 | err(EXIT_FAILURE, "failed to create disk label"); | |
124 | ||
125 | sectorsize = fdisk_get_sector_size(cxt); | |
126 | ||
127 | while (optind < argc) { | |
128 | int rc; | |
129 | uint64_t size; | |
130 | const char *str = argv[optind]; | |
131 | ||
132 | /* defaults */ | |
133 | fdisk_partition_start_follow_default(pa, 1); | |
134 | fdisk_partition_end_follow_default(pa, 1); | |
135 | ||
136 | /* set size */ | |
137 | if (isdigit(*str)) { | |
138 | size = strtosize_or_err(argv[optind], "failed to parse partition size"); | |
139 | fdisk_partition_set_size(pa, size / sectorsize); | |
140 | fdisk_partition_end_follow_default(pa, 0); | |
141 | ||
142 | } else if (*str == '-') { | |
143 | fdisk_partition_end_follow_default(pa, 1); | |
144 | } | |
145 | ||
146 | if (fdisk_is_label(cxt, DOS)) { | |
147 | /* For MBR we want to avoid primary/logical dialog. | |
148 | * This is possible by explicitly specified partition | |
149 | * number, <4 means primary, >=4 means logical. | |
150 | */ | |
151 | fdisk_partition_partno_follow_default(pa, 0); | |
152 | fdisk_partition_set_partno(pa, n); | |
153 | ||
154 | /* Make sure last primary partition is extended if user | |
155 | * wants more than 4 partitions. | |
156 | */ | |
157 | if (n == 3 && optind + 1 < argc) { | |
158 | struct fdisk_parttype *type = | |
159 | fdisk_label_parse_parttype( | |
160 | fdisk_get_label(cxt, NULL), "05"); | |
161 | if (!type) | |
162 | err_oom(); | |
163 | fdisk_partition_set_type(pa, type); | |
164 | fdisk_unref_parttype(type); | |
165 | } | |
166 | } else | |
167 | fdisk_partition_partno_follow_default(pa, 1); | |
168 | ||
169 | ||
170 | rc = fdisk_add_partition(cxt, pa, NULL); | |
171 | if (rc) { | |
172 | errno = -rc; | |
173 | err(EXIT_FAILURE, "failed to add #%d partition", n + 1); | |
174 | } | |
175 | ||
176 | fdisk_reset_partition(pa); | |
177 | optind++; | |
178 | n++; | |
179 | } | |
180 | ||
181 | if (fdisk_write_disklabel(cxt)) | |
182 | err(EXIT_FAILURE, "failed to write disk label"); | |
183 | ||
184 | fdisk_deassign_device(cxt, 1); | |
185 | fdisk_unref_context(cxt); | |
186 | fdisk_unref_partition(pa); | |
187 | ||
188 | return EXIT_SUCCESS; | |
189 | } |