]>
Commit | Line | Data |
---|---|---|
3f0ac587 | 1 | /* |
6dbe3af9 | 2 | * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk) |
38b36353 | 3 | * Copyright (C) 2012 Davidlohr Bueso <dave@gnu.org> |
6dbe3af9 | 4 | * |
3f0ac587 KZ |
5 | * Copyright (C) 2007-2013 Karel Zak <kzak@redhat.com> |
6 | * | |
6dbe3af9 KZ |
7 | * This program is free software. You can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License as | |
9 | * published by the Free Software Foundation: either version 1 or | |
10 | * (at your option) any later version. | |
6dbe3af9 | 11 | */ |
6dbe3af9 KZ |
12 | #include <unistd.h> |
13 | #include <stdio.h> | |
14 | #include <stdlib.h> | |
15 | #include <string.h> | |
16 | #include <fcntl.h> | |
17 | #include <ctype.h> | |
6dbe3af9 | 18 | #include <errno.h> |
2b6fc908 | 19 | #include <getopt.h> |
2b6fc908 | 20 | #include <sys/stat.h> |
f26873dc | 21 | #include <sys/time.h> |
bb6aacfe | 22 | #include <time.h> |
ee5355e0 | 23 | #include <limits.h> |
d44115f3 | 24 | #include <libsmartcols.h> |
740c36f6 | 25 | #ifdef HAVE_LIBREADLINE |
57ebfde2 | 26 | # define _FUNCTION_DEF |
740c36f6 KZ |
27 | # include <readline/readline.h> |
28 | #endif | |
6dbe3af9 | 29 | |
3f0ac587 | 30 | #include "c.h" |
52b38677 | 31 | #include "xalloc.h" |
e916600f | 32 | #include "all-io.h" |
22853e4a | 33 | #include "nls.h" |
e66ac5d3 | 34 | #include "rpmatch.h" |
810f986b | 35 | #include "blkdev.h" |
b8d22034 | 36 | #include "mbsalign.h" |
6bec8710 KZ |
37 | #include "pathnames.h" |
38 | #include "canonicalize.h" | |
20aa2570 | 39 | #include "strutils.h" |
b2d28533 | 40 | #include "closestream.h" |
8d2f4498 | 41 | #include "pager.h" |
5c36a0eb | 42 | |
fdb006e8 KZ |
43 | #include "fdisk.h" |
44 | ||
b4bfbadd | 45 | #include "pt-sun.h" /* to toggle flags */ |
5c36a0eb | 46 | |
48d7b13a | 47 | #ifdef HAVE_LINUX_COMPILER_H |
3f0ac587 | 48 | # include <linux/compiler.h> |
48d7b13a KZ |
49 | #endif |
50 | #ifdef HAVE_LINUX_BLKPG_H | |
3f0ac587 | 51 | # include <linux/blkpg.h> |
7eda085c | 52 | #endif |
6dbe3af9 | 53 | |
ba465623 | 54 | int pwipemode = WIPEMODE_AUTO; |
fadd8e08 KZ |
55 | int device_is_used; |
56 | struct fdisk_table *original_layout; | |
57 | ||
5635d195 | 58 | static int wipemode = WIPEMODE_AUTO; |
ba465623 | 59 | |
e6d0c4c1 KZ |
60 | /* |
61 | * fdisk debug stuff (see fdisk.h and include/debug.h) | |
62 | */ | |
63 | UL_DEBUG_DEFINE_MASK(fdisk); | |
819d9a29 | 64 | UL_DEBUG_DEFINE_MASKNAMES(fdisk) = UL_DEBUG_EMPTY_MASKNAMES; |
d6b3ba41 | 65 | |
e6d0c4c1 KZ |
66 | static void fdiskprog_init_debug(void) |
67 | { | |
68 | __UL_INIT_DEBUG(fdisk, FDISKPROG_DEBUG_, 0, FDISK_DEBUG); | |
69 | } | |
d6b3ba41 | 70 | |
740c36f6 KZ |
71 | #ifdef HAVE_LIBREADLINE |
72 | static char *rl_fgets(char *s, int n, FILE *stream, const char *prompt) | |
73 | { | |
74 | char *p; | |
75 | ||
76 | rl_outstream = stream; | |
77 | p = readline(prompt); | |
78 | if (!p) | |
79 | return NULL; | |
80 | ||
84ab260a KZ |
81 | strncpy(s, p, n); |
82 | s[n - 1] = '\0'; | |
740c36f6 KZ |
83 | free(p); |
84 | return s; | |
85 | } | |
86 | #endif | |
87 | ||
55cf3716 VD |
88 | static char *wrap_fgets(char *s, int n, FILE *stream, const char *prompt) |
89 | { | |
90 | #ifdef HAVE_LIBREADLINE | |
91 | if (isatty(STDIN_FILENO)) { | |
92 | return rl_fgets(s, n, stream, prompt); | |
93 | } | |
94 | else | |
95 | #endif | |
96 | { | |
97 | fputs(prompt, stream); | |
98 | fflush(stream); | |
99 | return fgets(s, n, stdin); | |
100 | } | |
101 | } | |
102 | ||
d6b3ba41 KZ |
103 | int get_user_reply(struct fdisk_context *cxt, const char *prompt, |
104 | char *buf, size_t bufsz) | |
105 | { | |
106 | char *p; | |
107 | size_t sz; | |
108 | ||
109 | do { | |
55cf3716 VD |
110 | if (!wrap_fgets(buf, bufsz, stdout, prompt)) { |
111 | if (fdisk_label_is_changed(fdisk_get_label(cxt, NULL))) { | |
112 | if (wrap_fgets(buf, bufsz, stderr, | |
113 | _("\nDo you really want to quit? ")) | |
114 | && !rpmatch(buf)) | |
115 | continue; | |
116 | } | |
117 | fdisk_unref_context(cxt); | |
118 | exit(EXIT_FAILURE); | |
119 | } else | |
120 | break; | |
d6b3ba41 KZ |
121 | } while (1); |
122 | ||
123 | for (p = buf; *p && !isgraph(*p); p++); /* get first non-blank */ | |
124 | ||
125 | if (p > buf) | |
126 | memmove(buf, p, p - buf); /* remove blank space */ | |
127 | sz = strlen(buf); | |
128 | if (sz && *(buf + sz - 1) == '\n') | |
129 | *(buf + sz - 1) = '\0'; | |
130 | ||
88141067 | 131 | DBG(ASK, ul_debug("user's reply: >>>%s<<<", buf)); |
d6b3ba41 KZ |
132 | return 0; |
133 | } | |
134 | ||
135 | static int ask_menu(struct fdisk_context *cxt, struct fdisk_ask *ask, | |
136 | char *buf, size_t bufsz) | |
137 | ||
138 | { | |
139 | const char *q = fdisk_ask_get_query(ask); | |
140 | int dft = fdisk_ask_menu_get_default(ask); | |
141 | ||
142 | if (q) { | |
143 | fputs(q, stdout); /* print header */ | |
144 | fputc('\n', stdout); | |
145 | } | |
146 | ||
147 | do { | |
148 | char prompt[128]; | |
68ddb136 | 149 | int key, c, rc; |
d6b3ba41 KZ |
150 | const char *name, *desc; |
151 | size_t i = 0; | |
152 | ||
153 | /* print menu items */ | |
154 | while (fdisk_ask_menu_get_item(ask, i++, &key, &name, &desc) == 0) | |
155 | fprintf(stdout, " %c %s (%s)\n", key, name, desc); | |
156 | ||
157 | /* ask for key */ | |
158 | snprintf(prompt, sizeof(prompt), _("Select (default %c): "), dft); | |
68ddb136 KZ |
159 | rc = get_user_reply(cxt, prompt, buf, bufsz); |
160 | if (rc) | |
161 | return rc; | |
d6b3ba41 KZ |
162 | if (!*buf) { |
163 | fdisk_info(cxt, _("Using default response %c."), dft); | |
164 | c = dft; | |
165 | } else | |
166 | c = tolower(buf[0]); | |
167 | ||
168 | /* check result */ | |
169 | i = 0; | |
170 | while (fdisk_ask_menu_get_item(ask, i++, &key, NULL, NULL) == 0) { | |
171 | if (c == key) { | |
172 | fdisk_ask_menu_set_result(ask, c); | |
173 | return 0; /* success */ | |
174 | } | |
175 | } | |
176 | fdisk_warnx(cxt, _("Value out of range.")); | |
177 | } while (1); | |
178 | ||
179 | return -EINVAL; | |
180 | } | |
181 | ||
182 | ||
183 | #define tochar(num) ((int) ('a' + num - 1)) | |
184 | static int ask_number(struct fdisk_context *cxt, | |
185 | struct fdisk_ask *ask, | |
186 | char *buf, size_t bufsz) | |
187 | { | |
188 | char prompt[128] = { '\0' }; | |
189 | const char *q = fdisk_ask_get_query(ask); | |
190 | const char *range = fdisk_ask_number_get_range(ask); | |
191 | ||
192 | uint64_t dflt = fdisk_ask_number_get_default(ask), | |
193 | low = fdisk_ask_number_get_low(ask), | |
194 | high = fdisk_ask_number_get_high(ask); | |
195 | int inchar = fdisk_ask_number_inchars(ask); | |
196 | ||
197 | assert(q); | |
198 | ||
88141067 | 199 | DBG(ASK, ul_debug("asking for number " |
fdbd7bb9 | 200 | "['%s', <%"PRIu64",%"PRIu64">, default=%"PRIu64", range: %s]", |
d6b3ba41 KZ |
201 | q, low, high, dflt, range)); |
202 | ||
203 | if (range && dflt >= low && dflt <= high) { | |
204 | if (inchar) | |
205 | snprintf(prompt, sizeof(prompt), _("%s (%s, default %c): "), | |
206 | q, range, tochar(dflt)); | |
207 | else | |
fdbd7bb9 | 208 | snprintf(prompt, sizeof(prompt), _("%s (%s, default %"PRIu64"): "), |
d6b3ba41 KZ |
209 | q, range, dflt); |
210 | ||
211 | } else if (dflt >= low && dflt <= high) { | |
212 | if (inchar) | |
213 | snprintf(prompt, sizeof(prompt), _("%s (%c-%c, default %c): "), | |
214 | q, tochar(low), tochar(high), tochar(dflt)); | |
215 | else | |
fdbd7bb9 RM |
216 | snprintf(prompt, sizeof(prompt), |
217 | _("%s (%"PRIu64"-%"PRIu64", default %"PRIu64"): "), | |
d6b3ba41 KZ |
218 | q, low, high, dflt); |
219 | } else if (inchar) | |
220 | snprintf(prompt, sizeof(prompt), _("%s (%c-%c): "), | |
221 | q, tochar(low), tochar(high)); | |
222 | else | |
fdbd7bb9 | 223 | snprintf(prompt, sizeof(prompt), _("%s (%"PRIu64"-%"PRIu64"): "), |
d6b3ba41 KZ |
224 | q, low, high); |
225 | ||
226 | do { | |
227 | int rc = get_user_reply(cxt, prompt, buf, bufsz); | |
228 | uint64_t num; | |
229 | ||
230 | if (rc) | |
231 | return rc; | |
232 | if (!*buf && dflt >= low && dflt <= high) | |
233 | return fdisk_ask_number_set_result(ask, dflt); | |
234 | ||
235 | if (isdigit_string(buf)) { | |
236 | char *end; | |
237 | ||
238 | errno = 0; | |
239 | num = strtoumax(buf, &end, 10); | |
240 | if (errno || buf == end || (end && *end)) | |
241 | continue; | |
242 | } else if (inchar && isalpha(*buf)) { | |
243 | num = tolower(*buf) - 'a' + 1; | |
244 | } else | |
245 | rc = -EINVAL; | |
246 | ||
247 | if (rc == 0 && num >= low && num <= high) | |
248 | return fdisk_ask_number_set_result(ask, num); | |
249 | ||
250 | fdisk_warnx(cxt, _("Value out of range.")); | |
251 | } while (1); | |
252 | ||
253 | return -1; | |
254 | } | |
255 | ||
256 | static int ask_offset(struct fdisk_context *cxt, | |
257 | struct fdisk_ask *ask, | |
258 | char *buf, size_t bufsz) | |
259 | { | |
260 | char prompt[128] = { '\0' }; | |
261 | const char *q = fdisk_ask_get_query(ask); | |
262 | const char *range = fdisk_ask_number_get_range(ask); | |
263 | ||
264 | uint64_t dflt = fdisk_ask_number_get_default(ask), | |
265 | low = fdisk_ask_number_get_low(ask), | |
266 | high = fdisk_ask_number_get_high(ask), | |
267 | base = fdisk_ask_number_get_base(ask); | |
268 | ||
269 | assert(q); | |
270 | ||
fdbd7bb9 | 271 | DBG(ASK, ul_debug("asking for offset ['%s', <%"PRIu64",%"PRIu64">, base=%"PRIu64", default=%"PRIu64", range: %s]", |
d6b3ba41 KZ |
272 | q, low, high, base, dflt, range)); |
273 | ||
274 | if (range && dflt >= low && dflt <= high) | |
fdbd7bb9 RM |
275 | snprintf(prompt, sizeof(prompt), _("%s (%s, default %"PRIu64"): "), |
276 | q, range, dflt); | |
d6b3ba41 | 277 | else if (dflt >= low && dflt <= high) |
fdbd7bb9 RM |
278 | snprintf(prompt, sizeof(prompt), |
279 | _("%s (%"PRIu64"-%"PRIu64", default %"PRIu64"): "), | |
280 | q, low, high, dflt); | |
d6b3ba41 | 281 | else |
fdbd7bb9 RM |
282 | snprintf(prompt, sizeof(prompt), _("%s (%"PRIu64"-%"PRIu64"): "), |
283 | q, low, high); | |
d6b3ba41 KZ |
284 | |
285 | do { | |
262c94c2 | 286 | uintmax_t num = 0; |
d6b3ba41 KZ |
287 | char sig = 0, *p; |
288 | int pwr = 0; | |
289 | ||
290 | int rc = get_user_reply(cxt, prompt, buf, bufsz); | |
291 | if (rc) | |
292 | return rc; | |
293 | if (!*buf && dflt >= low && dflt <= high) | |
294 | return fdisk_ask_number_set_result(ask, dflt); | |
295 | ||
296 | p = buf; | |
297 | if (*p == '+' || *p == '-') { | |
298 | sig = *buf; | |
299 | p++; | |
300 | } | |
301 | ||
302 | rc = parse_size(p, &num, &pwr); | |
303 | if (rc) | |
304 | continue; | |
88141067 | 305 | DBG(ASK, ul_debug("parsed size: %ju", num)); |
d6b3ba41 KZ |
306 | if (sig && pwr) { |
307 | /* +{size}{K,M,...} specified, the "num" is in bytes */ | |
308 | uint64_t unit = fdisk_ask_number_get_unit(ask); | |
309 | num += unit/2; /* round */ | |
310 | num /= unit; | |
311 | } | |
312 | if (sig == '+') | |
313 | num += base; | |
314 | else if (sig == '-') | |
315 | num = base - num; | |
316 | ||
88141067 | 317 | DBG(ASK, ul_debug("final offset: %ju [sig: %c, power: %d, %s]", |
d6b3ba41 KZ |
318 | num, sig, pwr, |
319 | sig ? "relative" : "absolute")); | |
320 | if (num >= low && num <= high) { | |
8c73e509 | 321 | if (sig && pwr) |
d6b3ba41 | 322 | fdisk_ask_number_set_relative(ask, 1); |
262c94c2 | 323 | return fdisk_ask_number_set_result(ask, (uint64_t)num); |
d6b3ba41 KZ |
324 | } |
325 | fdisk_warnx(cxt, _("Value out of range.")); | |
326 | } while (1); | |
327 | ||
328 | return -1; | |
329 | } | |
330 | ||
331 | static unsigned int info_count; | |
332 | ||
412791a9 | 333 | static void fputs_info(struct fdisk_ask *ask, FILE *out) |
d6b3ba41 KZ |
334 | { |
335 | const char *msg; | |
d6b3ba41 KZ |
336 | assert(ask); |
337 | ||
338 | msg = fdisk_ask_print_get_mesg(ask); | |
d6b3ba41 KZ |
339 | if (!msg) |
340 | return; | |
341 | if (info_count == 1) | |
342 | fputc('\n', out); | |
412791a9 KZ |
343 | |
344 | fputs(msg, out); | |
d6b3ba41 KZ |
345 | fputc('\n', out); |
346 | } | |
347 | ||
348 | int ask_callback(struct fdisk_context *cxt, struct fdisk_ask *ask, | |
349 | void *data __attribute__((__unused__))) | |
350 | { | |
351 | int rc = 0; | |
352 | char buf[BUFSIZ]; | |
353 | ||
354 | assert(cxt); | |
355 | assert(ask); | |
356 | ||
357 | if (fdisk_ask_get_type(ask) != FDISK_ASKTYPE_INFO) | |
358 | info_count = 0; | |
359 | ||
360 | switch(fdisk_ask_get_type(ask)) { | |
361 | case FDISK_ASKTYPE_MENU: | |
362 | return ask_menu(cxt, ask, buf, sizeof(buf)); | |
363 | case FDISK_ASKTYPE_NUMBER: | |
364 | return ask_number(cxt, ask, buf, sizeof(buf)); | |
365 | case FDISK_ASKTYPE_OFFSET: | |
366 | return ask_offset(cxt, ask, buf, sizeof(buf)); | |
367 | case FDISK_ASKTYPE_INFO: | |
152788aa KZ |
368 | if (!fdisk_is_listonly(cxt)) |
369 | info_count++; | |
412791a9 | 370 | fputs_info(ask, stdout); |
d6b3ba41 KZ |
371 | break; |
372 | case FDISK_ASKTYPE_WARNX: | |
95aae4fc | 373 | fflush(stdout); |
496c979a | 374 | color_scheme_fenable("warn", UL_COLOR_RED, stderr); |
d6b3ba41 KZ |
375 | fputs(fdisk_ask_print_get_mesg(ask), stderr); |
376 | color_fdisable(stderr); | |
377 | fputc('\n', stderr); | |
378 | break; | |
379 | case FDISK_ASKTYPE_WARN: | |
95aae4fc | 380 | fflush(stdout); |
496c979a | 381 | color_scheme_fenable("warn", UL_COLOR_RED, stderr); |
d6b3ba41 KZ |
382 | fputs(fdisk_ask_print_get_mesg(ask), stderr); |
383 | errno = fdisk_ask_print_get_errno(ask); | |
384 | fprintf(stderr, ": %m\n"); | |
385 | color_fdisable(stderr); | |
386 | break; | |
387 | case FDISK_ASKTYPE_YESNO: | |
388 | fputc('\n', stdout); | |
2d129032 KZ |
389 | do { |
390 | int x; | |
391 | fputs(fdisk_ask_get_query(ask), stdout); | |
392 | rc = get_user_reply(cxt, _(" [Y]es/[N]o: "), buf, sizeof(buf)); | |
393 | if (rc) | |
394 | break; | |
395 | x = rpmatch(buf); | |
cd2a6f1c | 396 | if (x == RPMATCH_YES || x == RPMATCH_NO) { |
2d129032 KZ |
397 | fdisk_ask_yesno_set_result(ask, x); |
398 | break; | |
399 | } | |
400 | } while(1); | |
88141067 | 401 | DBG(ASK, ul_debug("yes-no ask: reply '%s' [rc=%d]", buf, rc)); |
d6b3ba41 KZ |
402 | break; |
403 | case FDISK_ASKTYPE_STRING: | |
404 | { | |
405 | char prmt[BUFSIZ]; | |
406 | snprintf(prmt, sizeof(prmt), "%s: ", fdisk_ask_get_query(ask)); | |
407 | fputc('\n', stdout); | |
408 | rc = get_user_reply(cxt, prmt, buf, sizeof(buf)); | |
409 | if (rc == 0) | |
410 | fdisk_ask_string_set_result(ask, xstrdup(buf)); | |
88141067 | 411 | DBG(ASK, ul_debug("string ask: reply '%s' [rc=%d]", buf, rc)); |
d6b3ba41 KZ |
412 | break; |
413 | } | |
414 | default: | |
415 | warnx(_("internal error: unsupported dialog type %d"), fdisk_ask_get_type(ask)); | |
416 | return -EINVAL; | |
417 | } | |
418 | return rc; | |
419 | } | |
420 | ||
4bd02cdf | 421 | static struct fdisk_parttype *ask_partition_type(struct fdisk_context *cxt) |
d6b3ba41 KZ |
422 | { |
423 | const char *q; | |
a745611d KZ |
424 | struct fdisk_label *lb; |
425 | ||
426 | assert(cxt); | |
427 | lb = fdisk_get_label(cxt, NULL); | |
d6b3ba41 | 428 | |
a745611d | 429 | if (!lb) |
d6b3ba41 KZ |
430 | return NULL; |
431 | ||
a745611d | 432 | q = fdisk_label_has_code_parttypes(lb) ? |
84111dba KZ |
433 | _("Hex code (type L to list all codes): ") : |
434 | _("Partition type (type L to list all types): "); | |
d6b3ba41 KZ |
435 | do { |
436 | char buf[256]; | |
437 | int rc = get_user_reply(cxt, q, buf, sizeof(buf)); | |
438 | ||
439 | if (rc) | |
440 | break; | |
441 | ||
442 | if (buf[1] == '\0' && toupper(*buf) == 'L') | |
443 | list_partition_types(cxt); | |
444 | else if (*buf) | |
a745611d | 445 | return fdisk_label_parse_parttype(lb, buf); |
d6b3ba41 KZ |
446 | } while (1); |
447 | ||
448 | return NULL; | |
449 | } | |
450 | ||
8d2f4498 | 451 | |
7b575fcc | 452 | void list_partition_types(struct fdisk_context *cxt) |
6dbe3af9 | 453 | { |
76f17cf2 | 454 | size_t ntypes = 0; |
f45f5c83 | 455 | struct fdisk_label *lb; |
6dbe3af9 | 456 | |
a745611d KZ |
457 | assert(cxt); |
458 | lb = fdisk_get_label(cxt, NULL); | |
459 | if (!lb) | |
460 | return; | |
461 | ntypes = fdisk_label_get_nparttypes(lb); | |
462 | if (!ntypes) | |
7b575fcc | 463 | return; |
2b6fc908 | 464 | |
a745611d | 465 | if (fdisk_label_has_code_parttypes(lb)) { |
7b575fcc KZ |
466 | /* |
467 | * Prints in 4 columns in format <hex> <name> | |
468 | */ | |
76f17cf2 KZ |
469 | size_t last[4], done = 0, next = 0, size; |
470 | int i; | |
b8d22034 | 471 | |
76f17cf2 | 472 | size = ntypes; |
7b575fcc KZ |
473 | |
474 | for (i = 3; i >= 0; i--) | |
475 | last[3 - i] = done += (size + i - done) / (i + 1); | |
476 | i = done = 0; | |
477 | ||
478 | do { | |
479 | #define NAME_WIDTH 15 | |
480 | char name[NAME_WIDTH * MB_LEN_MAX]; | |
481 | size_t width = NAME_WIDTH; | |
a745611d | 482 | const struct fdisk_parttype *t = fdisk_label_get_parttype(lb, next); |
7b575fcc KZ |
483 | size_t ret; |
484 | ||
e6d0c4c1 | 485 | if (fdisk_parttype_get_name(t)) { |
a745611d KZ |
486 | printf("%c%2x ", i ? ' ' : '\n', |
487 | fdisk_parttype_get_code(t)); | |
488 | ret = mbsalign(_(fdisk_parttype_get_name(t)), | |
489 | name, sizeof(name), | |
490 | &width, MBS_ALIGN_LEFT, 0); | |
7b575fcc | 491 | |
76f17cf2 | 492 | if (ret == (size_t)-1 || ret >= sizeof(name)) |
a745611d KZ |
493 | printf("%-15.15s", |
494 | _(fdisk_parttype_get_name(t))); | |
76f17cf2 KZ |
495 | else |
496 | fputs(name, stdout); | |
497 | } | |
7b575fcc KZ |
498 | |
499 | next = last[i++] + done; | |
500 | if (i > 3 || next >= last[i]) { | |
501 | i = 0; | |
502 | next = ++done; | |
503 | } | |
504 | } while (done < last[0]); | |
505 | ||
506 | } else { | |
507 | /* | |
508 | * Prints 1 column in format <idx> <name> <typestr> | |
509 | */ | |
76f17cf2 | 510 | size_t i; |
7b575fcc | 511 | |
8d2f4498 KZ |
512 | pager_open(); |
513 | ||
a745611d KZ |
514 | for (i = 0; i < ntypes; i++) { |
515 | const struct fdisk_parttype *t = fdisk_label_get_parttype(lb, i); | |
516 | printf("%3zu %-30s %s\n", i + 1, | |
517 | fdisk_parttype_get_name(t), | |
518 | fdisk_parttype_get_string(t)); | |
76f17cf2 | 519 | } |
8d2f4498 KZ |
520 | |
521 | pager_close(); | |
7b575fcc | 522 | } |
6dbe3af9 KZ |
523 | putchar('\n'); |
524 | } | |
525 | ||
f02fecd1 | 526 | void toggle_dos_compatibility_flag(struct fdisk_context *cxt) |
852ce62b | 527 | { |
6a632136 | 528 | struct fdisk_label *lb = fdisk_get_label(cxt, "dos"); |
852ce62b KZ |
529 | int flag; |
530 | ||
531 | if (!lb) | |
532 | return; | |
533 | ||
534 | flag = !fdisk_dos_is_compatible(lb); | |
09f0c3d9 KZ |
535 | fdisk_info(cxt, flag ? |
536 | _("DOS Compatibility flag is set (DEPRECATED!)") : | |
537 | _("DOS Compatibility flag is not set")); | |
edd7b958 | 538 | |
852ce62b KZ |
539 | fdisk_dos_enable_compatible(lb, flag); |
540 | ||
aa36c2cf | 541 | if (fdisk_is_label(cxt, DOS)) |
09f0c3d9 | 542 | fdisk_reset_alignment(cxt); /* reset the current label */ |
6dbe3af9 KZ |
543 | } |
544 | ||
27ddd4f1 | 545 | void change_partition_type(struct fdisk_context *cxt) |
e53ced85 | 546 | { |
641a75ca | 547 | size_t i; |
85151521 KZ |
548 | struct fdisk_parttype *t = NULL; |
549 | struct fdisk_partition *pa = NULL; | |
550 | const char *old = NULL; | |
6dbe3af9 | 551 | |
e3661531 | 552 | assert(cxt); |
e3661531 | 553 | |
641a75ca | 554 | if (fdisk_ask_partnum(cxt, &i, FALSE)) |
24f4bbff | 555 | return; |
2b6fc908 | 556 | |
85151521 KZ |
557 | if (fdisk_get_partition(cxt, i, &pa)) { |
558 | fdisk_warnx(cxt, _("Partition %zu does not exist yet!"), i + 1); | |
559 | return; | |
560 | } | |
561 | ||
562 | t = (struct fdisk_parttype *) fdisk_partition_get_type(pa); | |
e6d0c4c1 | 563 | old = t ? fdisk_parttype_get_name(t) : _("Unknown"); |
85151521 KZ |
564 | |
565 | do { | |
566 | t = ask_partition_type(cxt); | |
567 | } while (!t); | |
568 | ||
85151521 | 569 | if (fdisk_set_partition_type(cxt, i, t) == 0) |
0477369a | 570 | fdisk_info(cxt, |
85151521 | 571 | _("Changed type of partition '%s' to '%s'."), |
a745611d | 572 | old, t ? fdisk_parttype_get_name(t) : _("Unknown")); |
85151521 KZ |
573 | else |
574 | fdisk_info(cxt, | |
575 | _("Type of partition %zu is unchanged: %s."), | |
576 | i + 1, old); | |
577 | ||
d6cfa8b3 | 578 | fdisk_unref_partition(pa); |
4bd02cdf | 579 | fdisk_unref_parttype(t); |
6dbe3af9 KZ |
580 | } |
581 | ||
3e3b51b3 JLB |
582 | int print_partition_info(struct fdisk_context *cxt) |
583 | { | |
584 | struct fdisk_partition *pa = NULL; | |
6360bcca | 585 | int rc = 0; |
3e3b51b3 JLB |
586 | size_t i, nfields; |
587 | int *fields = NULL; | |
588 | struct fdisk_label *lb = fdisk_get_label(cxt, NULL); | |
589 | ||
590 | if ((rc = fdisk_ask_partnum(cxt, &i, FALSE))) | |
591 | return rc; | |
592 | ||
593 | if ((rc = fdisk_get_partition(cxt, i, &pa))) { | |
594 | fdisk_warnx(cxt, _("Partition %zu does not exist yet!"), i + 1); | |
595 | return rc; | |
596 | } | |
597 | ||
6360bcca | 598 | if ((rc = fdisk_label_get_fields_ids_all(lb, cxt, &fields, &nfields))) |
3e3b51b3 | 599 | goto clean_data; |
3e3b51b3 JLB |
600 | |
601 | for (i = 0; i < nfields; ++i) { | |
602 | int id = fields[i]; | |
603 | char *data = NULL; | |
604 | const struct fdisk_field *fd = fdisk_label_get_field(lb, id); | |
605 | ||
606 | if (!fd) | |
607 | continue; | |
608 | ||
609 | rc = fdisk_partition_to_string(pa, cxt, id, &data); | |
610 | if (rc < 0) | |
611 | goto clean_data; | |
6360bcca KZ |
612 | if (!data || !*data) |
613 | continue; | |
3e3b51b3 JLB |
614 | fdisk_info(cxt, _("%15s: %s"), fdisk_field_get_name(fd), data); |
615 | free(data); | |
616 | } | |
617 | ||
618 | clean_data: | |
619 | fdisk_unref_partition(pa); | |
620 | free(fields); | |
621 | return rc; | |
622 | } | |
623 | ||
e916600f KZ |
624 | static size_t skip_empty(const unsigned char *buf, size_t i, size_t sz) |
625 | { | |
626 | size_t next; | |
627 | const unsigned char *p0 = buf + i; | |
628 | ||
629 | for (next = i + 16; next < sz; next += 16) { | |
630 | if (memcmp(p0, buf + next, 16) != 0) | |
631 | break; | |
632 | } | |
633 | ||
634 | return next == i + 16 ? i : next; | |
635 | } | |
6dbe3af9 | 636 | |
e916600f | 637 | static void dump_buffer(off_t base, unsigned char *buf, size_t sz, int all) |
09f0c3d9 | 638 | { |
e916600f KZ |
639 | size_t i, l, next = 0; |
640 | ||
641 | if (!buf) | |
642 | return; | |
643 | for (i = 0, l = 0; i < sz; i++, l++) { | |
644 | if (l == 0) { | |
645 | if (all == 0 && !next) | |
646 | next = skip_empty(buf, i, sz); | |
fdbd7bb9 | 647 | printf("%08jx ", (intmax_t)base + i); |
e916600f KZ |
648 | } |
649 | printf(" %02x", buf[i]); | |
650 | if (l == 7) /* words separator */ | |
651 | fputs(" ", stdout); | |
652 | else if (l == 15) { | |
653 | fputc('\n', stdout); /* next line */ | |
6dbe3af9 | 654 | l = -1; |
e916600f KZ |
655 | if (next > i) { |
656 | printf("*\n"); | |
657 | i = next - 1; | |
658 | } | |
659 | next = 0; | |
6dbe3af9 KZ |
660 | } |
661 | } | |
662 | if (l > 0) | |
663 | printf("\n"); | |
6dbe3af9 KZ |
664 | } |
665 | ||
e916600f | 666 | static void dump_blkdev(struct fdisk_context *cxt, const char *name, |
9bbcf43f | 667 | uint64_t offset, size_t size, int all) |
e53ced85 | 668 | { |
8eccde20 KZ |
669 | int fd = fdisk_get_devfd(cxt); |
670 | ||
fdbd7bb9 | 671 | fdisk_info(cxt, _("\n%s: offset = %"PRIu64", size = %zu bytes."), |
e916600f KZ |
672 | name, offset, size); |
673 | ||
8eccde20 KZ |
674 | assert(fd >= 0); |
675 | ||
9bbcf43f | 676 | if (lseek(fd, (off_t) offset, SEEK_SET) == (off_t) -1) |
e916600f | 677 | fdisk_warn(cxt, _("cannot seek")); |
5afed187 KZ |
678 | else { |
679 | unsigned char *buf = xmalloc(size); | |
680 | ||
8eccde20 | 681 | if (read_all(fd, (char *) buf, size) != (ssize_t) size) |
5afed187 KZ |
682 | fdisk_warn(cxt, _("cannot read")); |
683 | else | |
684 | dump_buffer(offset, buf, size, all); | |
685 | free(buf); | |
686 | } | |
e916600f KZ |
687 | } |
688 | ||
689 | void dump_firstsector(struct fdisk_context *cxt) | |
690 | { | |
691 | int all = !isatty(STDOUT_FILENO); | |
692 | ||
e3661531 | 693 | assert(cxt); |
6dbe3af9 | 694 | |
8eccde20 | 695 | dump_blkdev(cxt, _("First sector"), 0, fdisk_get_sector_size(cxt), all); |
e916600f KZ |
696 | } |
697 | ||
698 | void dump_disklabel(struct fdisk_context *cxt) | |
699 | { | |
700 | int all = !isatty(STDOUT_FILENO); | |
701 | int i = 0; | |
702 | const char *name = NULL; | |
9bbcf43f | 703 | uint64_t offset = 0; |
e916600f KZ |
704 | size_t size = 0; |
705 | ||
706 | assert(cxt); | |
e3661531 | 707 | |
e916600f KZ |
708 | while (fdisk_locate_disklabel(cxt, i++, &name, &offset, &size) == 0 && size) |
709 | dump_blkdev(cxt, name, offset, size, all); | |
6dbe3af9 KZ |
710 | } |
711 | ||
0073a4cf | 712 | static fdisk_sector_t get_dev_blocks(char *dev) |
6da365de | 713 | { |
bbe67996 | 714 | int fd, ret; |
0073a4cf | 715 | fdisk_sector_t size; |
6da365de DB |
716 | |
717 | if ((fd = open(dev, O_RDONLY)) < 0) | |
289dcc90 | 718 | err(EXIT_FAILURE, _("cannot open %s"), dev); |
0073a4cf | 719 | ret = blkdev_get_sectors(fd, (unsigned long long *) &size); |
6da365de | 720 | close(fd); |
bbe67996 SK |
721 | if (ret < 0) |
722 | err(EXIT_FAILURE, _("BLKGETSIZE ioctl failed on %s"), dev); | |
6da365de DB |
723 | return size/2; |
724 | } | |
725 | ||
5635d195 KZ |
726 | |
727 | void follow_wipe_mode(struct fdisk_context *cxt) | |
728 | { | |
729 | int dowipe = wipemode == WIPEMODE_ALWAYS ? 1 : 0; | |
730 | ||
731 | if (isatty(STDIN_FILENO) && wipemode == WIPEMODE_AUTO) | |
732 | dowipe = 1; /* do it in interactive mode */ | |
733 | ||
734 | if (fdisk_is_ptcollision(cxt) && wipemode != WIPEMODE_NEVER) | |
735 | dowipe = 1; /* always remove old PT */ | |
736 | ||
737 | fdisk_enable_wipe(cxt, dowipe); | |
738 | if (dowipe) | |
739 | fdisk_warnx(cxt, _( | |
740 | "The old %s signature will be removed by a write command."), | |
741 | fdisk_get_collision(cxt)); | |
742 | else | |
743 | fdisk_warnx(cxt, _( | |
744 | "The old %s signature may remain on the device. " | |
745 | "It is recommended to wipe the device with wipefs(8) or " | |
746 | "fdisk --wipe, in order to avoid possible collisions."), | |
747 | fdisk_get_collision(cxt)); | |
748 | } | |
749 | ||
6e1eda6f | 750 | static void __attribute__((__noreturn__)) usage(void) |
e3a4aaa7 | 751 | { |
6e1eda6f RM |
752 | FILE *out = stdout; |
753 | ||
e3a4aaa7 KZ |
754 | fputs(USAGE_HEADER, out); |
755 | ||
756 | fprintf(out, | |
757 | _(" %1$s [options] <disk> change partition table\n" | |
758 | " %1$s [options] -l [<disk>] list partition table(s)\n"), | |
759 | program_invocation_short_name); | |
760 | ||
451dbcfa BS |
761 | fputs(USAGE_SEPARATOR, out); |
762 | fputs(_("Display or manipulate a disk partition table.\n"), out); | |
763 | ||
e3a4aaa7 KZ |
764 | fputs(USAGE_OPTIONS, out); |
765 | fputs(_(" -b, --sector-size <size> physical and logical sector size\n"), out); | |
718b6f0c | 766 | fputs(_(" -B, --protect-boot don't erase bootbits when creating a new label\n"), out); |
e3a4aaa7 KZ |
767 | fputs(_(" -c, --compatibility[=<mode>] mode is 'dos' or 'nondos' (default)\n"), out); |
768 | fputs(_(" -L, --color[=<when>] colorize output (auto, always or never)\n"), out); | |
5d51dc2a KZ |
769 | fprintf(out, |
770 | " %s\n", USAGE_COLORS_DEFAULT); | |
9e930041 | 771 | fputs(_(" -l, --list display partitions and exit\n"), out); |
2d7dffeb | 772 | fputs(_(" -o, --output <list> output columns\n"), out); |
e3a4aaa7 KZ |
773 | fputs(_(" -t, --type <type> recognize specified partition table type only\n"), out); |
774 | fputs(_(" -u, --units[=<unit>] display units: 'cylinders' or 'sectors' (default)\n"), out); | |
775 | fputs(_(" -s, --getsz display device size in 512-byte sectors [DEPRECATED]\n"), out); | |
354f8cc8 | 776 | fputs(_(" --bytes print SIZE in bytes rather than in human readable format\n"), out); |
cb9a4b00 | 777 | fputs(_(" -w, --wipe <mode> wipe signatures (auto, always or never)\n"), out); |
ba465623 | 778 | fputs(_(" -W, --wipe-partitions <mode> wipe signatures from new partitions (auto, always or never)\n"), out); |
e3a4aaa7 KZ |
779 | |
780 | fputs(USAGE_SEPARATOR, out); | |
4b4e391a KZ |
781 | fputs(_(" -C, --cylinders <number> specify the number of cylinders\n"), out); |
782 | fputs(_(" -H, --heads <number> specify the number of heads\n"), out); | |
783 | fputs(_(" -S, --sectors <number> specify the number of sectors per track\n"), out); | |
e3a4aaa7 KZ |
784 | |
785 | fputs(USAGE_SEPARATOR, out); | |
f45f3ec3 | 786 | printf(USAGE_HELP_OPTIONS(31)); |
e3a4aaa7 | 787 | |
fff8ad58 KZ |
788 | list_available_columns(out); |
789 | ||
f45f3ec3 | 790 | printf(USAGE_MAN_TAIL("fdisk(8)")); |
6e1eda6f | 791 | exit(EXIT_SUCCESS); |
e3a4aaa7 KZ |
792 | } |
793 | ||
794 | ||
5b72b3dd KZ |
795 | enum { |
796 | ACT_FDISK = 0, /* default */ | |
797 | ACT_LIST, | |
798 | ACT_SHOWSIZE | |
799 | }; | |
800 | ||
e1144767 DB |
801 | int main(int argc, char **argv) |
802 | { | |
e146ae4e | 803 | int rc, i, c, act = ACT_FDISK; |
d0c9ddc3 | 804 | int colormode = UL_COLORMODE_UNDEF; |
4e0e8253 | 805 | struct fdisk_context *cxt; |
fff8ad58 | 806 | char *outarg = NULL; |
354f8cc8 KZ |
807 | enum { |
808 | OPT_BYTES = CHAR_MAX + 1 | |
809 | }; | |
e3a4aaa7 | 810 | static const struct option longopts[] = { |
354f8cc8 | 811 | { "bytes", no_argument, NULL, OPT_BYTES }, |
e3a4aaa7 KZ |
812 | { "color", optional_argument, NULL, 'L' }, |
813 | { "compatibility", optional_argument, NULL, 'c' }, | |
4b4e391a KZ |
814 | { "cylinders", required_argument, NULL, 'C' }, |
815 | { "heads", required_argument, NULL, 'H' }, | |
816 | { "sectors", required_argument, NULL, 'S' }, | |
e3a4aaa7 KZ |
817 | { "getsz", no_argument, NULL, 's' }, |
818 | { "help", no_argument, NULL, 'h' }, | |
819 | { "list", no_argument, NULL, 'l' }, | |
820 | { "sector-size", required_argument, NULL, 'b' }, | |
821 | { "type", required_argument, NULL, 't' }, | |
822 | { "units", optional_argument, NULL, 'u' }, | |
823 | { "version", no_argument, NULL, 'V' }, | |
2d7dffeb | 824 | { "output", no_argument, NULL, 'o' }, |
aeb9a30b | 825 | { "protect-boot", no_argument, NULL, 'B' }, |
cb9a4b00 | 826 | { "wipe", required_argument, NULL, 'w' }, |
ba465623 | 827 | { "wipe-partitions",required_argument, NULL, 'W' }, |
e3a4aaa7 KZ |
828 | { NULL, 0, NULL, 0 } |
829 | }; | |
830 | ||
7eda085c KZ |
831 | setlocale(LC_ALL, ""); |
832 | bindtextdomain(PACKAGE, LOCALEDIR); | |
833 | textdomain(PACKAGE); | |
b2d28533 | 834 | atexit(close_stdout); |
2b6fc908 | 835 | |
4e0e8253 | 836 | fdisk_init_debug(0); |
053939a4 | 837 | scols_init_debug(0); |
e6d0c4c1 KZ |
838 | fdiskprog_init_debug(); |
839 | ||
4e0e8253 KZ |
840 | cxt = fdisk_new_context(); |
841 | if (!cxt) | |
842 | err(EXIT_FAILURE, _("failed to allocate libfdisk context")); | |
843 | ||
6a632136 | 844 | fdisk_set_ask(cxt, ask_callback, NULL); |
416c43a9 | 845 | |
ba465623 | 846 | while ((c = getopt_long(argc, argv, "b:Bc::C:hH:lL::o:sS:t:u::vVw:W:", |
e3a4aaa7 | 847 | longopts, NULL)) != -1) { |
2b6fc908 KZ |
848 | switch (c) { |
849 | case 'b': | |
6bcd192c KZ |
850 | { |
851 | size_t sz = strtou32_or_err(optarg, | |
852 | _("invalid sector size argument")); | |
853 | if (sz != 512 && sz != 1024 && sz != 2048 && sz != 4096) | |
6e1eda6f | 854 | errx(EXIT_FAILURE, _("invalid sector size argument")); |
6bcd192c | 855 | fdisk_save_user_sector_size(cxt, sz, sz); |
2b6fc908 | 856 | break; |
6bcd192c | 857 | } |
9ff89c5d | 858 | case 'B': |
aeb9a30b KZ |
859 | fdisk_enable_bootbits_protection(cxt, 1); |
860 | break; | |
0e6f4a20 | 861 | case 'C': |
1653f0b0 KZ |
862 | fdisk_save_user_geometry(cxt, |
863 | strtou32_or_err(optarg, | |
864 | _("invalid cylinders argument")), | |
865 | 0, 0); | |
0e6f4a20 | 866 | break; |
78498b7b | 867 | case 'c': |
852ce62b | 868 | if (optarg) { |
2b0bc17b | 869 | /* this setting is independent on the current |
e3a4aaa7 KZ |
870 | * actively used label |
871 | */ | |
872 | char *p = *optarg == '=' ? optarg + 1 : optarg; | |
6a632136 | 873 | struct fdisk_label *lb = fdisk_get_label(cxt, "dos"); |
e3a4aaa7 | 874 | |
852ce62b KZ |
875 | if (!lb) |
876 | err(EXIT_FAILURE, _("not found DOS label driver")); | |
e3a4aaa7 | 877 | if (strcmp(p, "dos") == 0) |
852ce62b | 878 | fdisk_dos_enable_compatible(lb, TRUE); |
e3a4aaa7 | 879 | else if (strcmp(p, "nondos") == 0) |
852ce62b | 880 | fdisk_dos_enable_compatible(lb, FALSE); |
6e1eda6f RM |
881 | else |
882 | errx(EXIT_FAILURE, _("unknown compatibility mode '%s'"), p); | |
852ce62b KZ |
883 | } |
884 | /* use default if no optarg specified */ | |
78498b7b | 885 | break; |
0e6f4a20 | 886 | case 'H': |
1653f0b0 KZ |
887 | fdisk_save_user_geometry(cxt, 0, |
888 | strtou32_or_err(optarg, | |
889 | _("invalid heads argument")), | |
890 | 0); | |
0e6f4a20 KZ |
891 | break; |
892 | case 'S': | |
1653f0b0 KZ |
893 | fdisk_save_user_geometry(cxt, 0, 0, |
894 | strtou32_or_err(optarg, | |
895 | _("invalid sectors argument"))); | |
0e6f4a20 | 896 | break; |
2b6fc908 | 897 | case 'l': |
5b72b3dd | 898 | act = ACT_LIST; |
2b6fc908 | 899 | break; |
80a1712f | 900 | case 'L': |
5d51dc2a | 901 | colormode = UL_COLORMODE_AUTO; |
80a1712f KZ |
902 | if (optarg) |
903 | colormode = colormode_or_err(optarg, | |
904 | _("unsupported color mode")); | |
905 | break; | |
fff8ad58 KZ |
906 | case 'o': |
907 | outarg = optarg; | |
908 | break; | |
2b6fc908 | 909 | case 's': |
5b72b3dd | 910 | act = ACT_SHOWSIZE; |
2b6fc908 | 911 | break; |
565b7da6 KZ |
912 | case 't': |
913 | { | |
914 | struct fdisk_label *lb = NULL; | |
915 | ||
6a632136 | 916 | while (fdisk_next_label(cxt, &lb) == 0) |
565b7da6 KZ |
917 | fdisk_label_set_disabled(lb, 1); |
918 | ||
6a632136 | 919 | lb = fdisk_get_label(cxt, optarg); |
565b7da6 KZ |
920 | if (!lb) |
921 | errx(EXIT_FAILURE, _("unsupported disklabel: %s"), optarg); | |
922 | fdisk_label_set_disabled(lb, 0); | |
1ce1a112 | 923 | break; |
565b7da6 | 924 | } |
2b6fc908 | 925 | case 'u': |
ec10aa67 KZ |
926 | if (optarg && *optarg == '=') |
927 | optarg++; | |
6a632136 | 928 | if (fdisk_set_unit(cxt, optarg) != 0) |
6e1eda6f | 929 | errx(EXIT_FAILURE, _("unsupported unit")); |
2b6fc908 | 930 | break; |
e3a4aaa7 KZ |
931 | case 'V': /* preferred for util-linux */ |
932 | case 'v': /* for backward compatibility only */ | |
a2482eb3 DB |
933 | printf(UTIL_LINUX_VERSION); |
934 | return EXIT_SUCCESS; | |
cb9a4b00 KZ |
935 | case 'w': |
936 | wipemode = wipemode_from_string(optarg); | |
937 | if (wipemode < 0) | |
938 | errx(EXIT_FAILURE, _("unsupported wipe mode")); | |
939 | break; | |
ba465623 KZ |
940 | case 'W': |
941 | pwipemode = wipemode_from_string(optarg); | |
942 | if (pwipemode < 0) | |
943 | errx(EXIT_FAILURE, _("unsupported wipe mode")); | |
944 | break; | |
e1144767 | 945 | case 'h': |
6e1eda6f | 946 | usage(); |
354f8cc8 KZ |
947 | case OPT_BYTES: |
948 | fdisk_set_size_unit(cxt, FDISK_SIZEUNIT_BYTES); | |
949 | break; | |
2b6fc908 | 950 | default: |
677ec86c | 951 | errtryhelp(EXIT_FAILURE); |
2b6fc908 | 952 | } |
6dbe3af9 | 953 | } |
2b6fc908 | 954 | |
6bcd192c KZ |
955 | if (argc-optind != 1 && fdisk_has_user_device_properties(cxt)) |
956 | warnx(_("The device properties (sector size and geometry) should" | |
957 | " be used with one specified device only.")); | |
7eda085c | 958 | |
d0c9ddc3 | 959 | colors_init(colormode, "fdisk"); |
ffcf0540 | 960 | |
5b72b3dd KZ |
961 | switch (act) { |
962 | case ACT_LIST: | |
6a632136 | 963 | fdisk_enable_listonly(cxt, 1); |
fff8ad58 | 964 | init_fields(cxt, outarg, NULL); |
ffcf0540 | 965 | |
2b6fc908 KZ |
966 | if (argc > optind) { |
967 | int k; | |
04c163ed | 968 | int ct = 0; |
8fdd483c KZ |
969 | |
970 | for (rc = 0, k = optind; k < argc; k++) { | |
04c163ed TV |
971 | if (ct) |
972 | fputs("\n\n", stdout); | |
8fdd483c KZ |
973 | |
974 | rc += print_device_pt(cxt, argv[k], 1, 0); | |
04c163ed | 975 | ct++; |
04c163ed | 976 | } |
8fdd483c KZ |
977 | if (rc) |
978 | return EXIT_FAILURE; | |
ea4824f1 | 979 | } else |
d2c47697 | 980 | print_all_devices_pt(cxt, 0); |
5b72b3dd | 981 | break; |
2b6fc908 | 982 | |
5b72b3dd | 983 | case ACT_SHOWSIZE: |
9564e46c | 984 | /* deprecated */ |
6e1eda6f RM |
985 | if (argc - optind <= 0) { |
986 | warnx(_("bad usage")); | |
987 | errtryhelp(EXIT_FAILURE); | |
988 | } | |
6da365de | 989 | for (i = optind; i < argc; i++) { |
0073a4cf KZ |
990 | uintmax_t blks = get_dev_blocks(argv[i]); |
991 | ||
5b72b3dd | 992 | if (argc - optind == 1) |
0073a4cf | 993 | printf("%ju\n", blks); |
2b6fc908 | 994 | else |
0073a4cf | 995 | printf("%s: %ju\n", argv[i], blks); |
6dbe3af9 | 996 | } |
5b72b3dd | 997 | break; |
6dbe3af9 | 998 | |
5b72b3dd | 999 | case ACT_FDISK: |
6e1eda6f RM |
1000 | if (argc-optind != 1) { |
1001 | warnx(_("bad usage")); | |
1002 | errtryhelp(EXIT_FAILURE); | |
1003 | } | |
7eda085c | 1004 | |
5b72b3dd | 1005 | /* Here starts interactive mode, use fdisk_{warn,info,..} functions */ |
496c979a | 1006 | color_scheme_enable("welcome", UL_COLOR_GREEN); |
09f0c3d9 | 1007 | fdisk_info(cxt, _("Welcome to fdisk (%s)."), PACKAGE_STRING); |
80a1712f KZ |
1008 | color_disable(); |
1009 | fdisk_info(cxt, _("Changes will remain in memory only, until you decide to write them.\n" | |
1010 | "Be careful before using the write command.\n")); | |
2d8988bd | 1011 | |
6a632136 | 1012 | rc = fdisk_assign_device(cxt, argv[optind], 0); |
e146ae4e | 1013 | if (rc == -EACCES) { |
6a632136 | 1014 | rc = fdisk_assign_device(cxt, argv[optind], 1); |
e146ae4e | 1015 | if (rc == 0) |
62eea9ce | 1016 | fdisk_warnx(cxt, _("Device is open in read-only mode.")); |
e146ae4e KZ |
1017 | } |
1018 | if (rc) | |
2d8988bd KZ |
1019 | err(EXIT_FAILURE, _("cannot open %s"), argv[optind]); |
1020 | ||
5b72b3dd | 1021 | fflush(stdout); |
56c07b96 | 1022 | |
5635d195 KZ |
1023 | if (fdisk_get_collision(cxt)) |
1024 | follow_wipe_mode(cxt); | |
cb9a4b00 | 1025 | |
aa36c2cf | 1026 | if (!fdisk_has_label(cxt)) { |
2d8988bd | 1027 | fdisk_info(cxt, _("Device does not contain a recognized partition table.")); |
5b72b3dd | 1028 | fdisk_create_disklabel(cxt, NULL); |
433d05ff | 1029 | |
aa36c2cf | 1030 | } else if (fdisk_is_label(cxt, GPT) && fdisk_gpt_is_hybrid(cxt)) |
433d05ff | 1031 | fdisk_warnx(cxt, _( |
09af3db4 | 1032 | "A hybrid GPT was detected. You have to sync " |
433d05ff | 1033 | "the hybrid MBR manually (expert command 'M').")); |
6dbe3af9 | 1034 | |
fff8ad58 KZ |
1035 | init_fields(cxt, outarg, NULL); /* -o <columns> */ |
1036 | ||
fadd8e08 KZ |
1037 | if (!fdisk_is_readonly(cxt)) { |
1038 | fdisk_get_partitions(cxt, &original_layout); | |
1039 | device_is_used = fdisk_device_is_used(cxt); | |
1040 | } | |
1041 | ||
5b72b3dd KZ |
1042 | while (1) |
1043 | process_fdisk_menu(&cxt); | |
1044 | } | |
9777759a | 1045 | |
c7119037 | 1046 | fdisk_unref_context(cxt); |
5b72b3dd | 1047 | return EXIT_SUCCESS; |
6dbe3af9 | 1048 | } |