]> git.ipfire.org Git - thirdparty/util-linux.git/blame - fdisks/fdisk.c
sfdisk: merge partname.c
[thirdparty/util-linux.git] / fdisks / fdisk.c
CommitLineData
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>
6dbe3af9 24
3f0ac587 25#include "c.h"
52b38677 26#include "xalloc.h"
e916600f 27#include "all-io.h"
22853e4a 28#include "nls.h"
e66ac5d3 29#include "rpmatch.h"
810f986b 30#include "blkdev.h"
b8d22034 31#include "mbsalign.h"
726f69e2 32#include "fdisk.h"
929f243f 33#include "wholedisk.h"
6bec8710
KZ
34#include "pathnames.h"
35#include "canonicalize.h"
20aa2570 36#include "strutils.h"
b2d28533 37#include "closestream.h"
5c36a0eb 38
b4bfbadd 39#include "pt-sun.h" /* to toggle flags */
5c36a0eb 40
48d7b13a 41#ifdef HAVE_LINUX_COMPILER_H
3f0ac587 42# include <linux/compiler.h>
48d7b13a
KZ
43#endif
44#ifdef HAVE_LINUX_BLKPG_H
3f0ac587 45# include <linux/blkpg.h>
7eda085c 46#endif
6dbe3af9 47
3f0ac587
KZ
48static void __attribute__ ((__noreturn__)) usage(FILE *out)
49{
50 fputs(USAGE_HEADER, out);
51
52 fprintf(out,
38d663a6
KZ
53 _(" %1$s [options] <disk> change partition table\n"
54 " %1$s [options] -l [<disk>] list partition table(s)\n"),
3f0ac587
KZ
55 program_invocation_short_name);
56
57 fputs(USAGE_OPTIONS, out);
58 fputs(_(" -b <size> sector size (512, 1024, 2048 or 4096)\n"), out);
59 fputs(_(" -c[=<mode>] compatible mode: 'dos' or 'nondos' (default)\n"), out);
60 fputs(_(" -h print this help text\n"), out);
80a1712f
KZ
61 fputs(_(" -c[=<mode>] compatible mode: 'dos' or 'nondos' (default)\n"), out);
62 fputs(_(" -L[=<when>] colorize output (auto, always or never)\n"), out);
565b7da6 63 fputs(_(" -t <type> force fdisk to recognize specified partition table type only\n"), out);
3f0ac587
KZ
64 fputs(_(" -u[=<unit>] display units: 'cylinders' or 'sectors' (default)\n"), out);
65 fputs(_(" -v print program version\n"), out);
66 fputs(_(" -C <number> specify the number of cylinders\n"), out);
67 fputs(_(" -H <number> specify the number of heads\n"), out);
68 fputs(_(" -S <number> specify the number of sectors per track\n"), out);
69
70 fprintf(out, USAGE_MAN_TAIL("fdisk(8)"));
71 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
72}
73
7b575fcc 74void list_partition_types(struct fdisk_context *cxt)
6dbe3af9 75{
7b575fcc 76 struct fdisk_parttype *types;
76f17cf2 77 size_t ntypes = 0;
6dbe3af9 78
7b575fcc
KZ
79 if (!cxt || !cxt->label || !cxt->label->parttypes)
80 return;
2b6fc908 81
7b575fcc 82 types = cxt->label->parttypes;
76f17cf2 83 ntypes = cxt->label->nparttypes;
6dbe3af9 84
7b575fcc
KZ
85 if (types[0].typestr == NULL) {
86 /*
87 * Prints in 4 columns in format <hex> <name>
88 */
76f17cf2
KZ
89 size_t last[4], done = 0, next = 0, size;
90 int i;
b8d22034 91
76f17cf2
KZ
92 size = ntypes;
93 if (types[ntypes - 1].name == NULL)
94 size--;
7b575fcc
KZ
95
96 for (i = 3; i >= 0; i--)
97 last[3 - i] = done += (size + i - done) / (i + 1);
98 i = done = 0;
99
100 do {
101 #define NAME_WIDTH 15
102 char name[NAME_WIDTH * MB_LEN_MAX];
103 size_t width = NAME_WIDTH;
104 struct fdisk_parttype *t = &types[next];
105 size_t ret;
106
76f17cf2
KZ
107 if (t->name) {
108 printf("%c%2x ", i ? ' ' : '\n', t->type);
109 ret = mbsalign(_(t->name), name, sizeof(name),
110 &width, MBS_ALIGN_LEFT, 0);
7b575fcc 111
76f17cf2
KZ
112 if (ret == (size_t)-1 || ret >= sizeof(name))
113 printf("%-15.15s", _(t->name));
114 else
115 fputs(name, stdout);
116 }
7b575fcc
KZ
117
118 next = last[i++] + done;
119 if (i > 3 || next >= last[i]) {
120 i = 0;
121 next = ++done;
122 }
123 } while (done < last[0]);
124
125 } else {
126 /*
127 * Prints 1 column in format <idx> <name> <typestr>
128 */
129 struct fdisk_parttype *t;
76f17cf2 130 size_t i;
7b575fcc 131
76f17cf2
KZ
132 for (i = 0, t = types; t && i < ntypes; t++, i++) {
133 if (t->name)
134 printf("%3zu %-30s %s\n", i + 1,
135 t->name, t->typestr);
136 }
7b575fcc 137 }
6dbe3af9
KZ
138 putchar('\n');
139}
140
f02fecd1 141void toggle_dos_compatibility_flag(struct fdisk_context *cxt)
852ce62b
KZ
142{
143 struct fdisk_label *lb = fdisk_context_get_label(cxt, "dos");
144 int flag;
145
146 if (!lb)
147 return;
148
149 flag = !fdisk_dos_is_compatible(lb);
09f0c3d9
KZ
150 fdisk_info(cxt, flag ?
151 _("DOS Compatibility flag is set (DEPRECATED!)") :
152 _("DOS Compatibility flag is not set"));
edd7b958 153
852ce62b
KZ
154 fdisk_dos_enable_compatible(lb, flag);
155
156 if (fdisk_is_disklabel(cxt, DOS))
09f0c3d9 157 fdisk_reset_alignment(cxt); /* reset the current label */
6dbe3af9
KZ
158}
159
27ddd4f1 160void change_partition_type(struct fdisk_context *cxt)
e53ced85 161{
641a75ca 162 size_t i;
85151521
KZ
163 struct fdisk_parttype *t = NULL;
164 struct fdisk_partition *pa = NULL;
165 const char *old = NULL;
6dbe3af9 166
e3661531
KZ
167 assert(cxt);
168 assert(cxt->label);
169
641a75ca 170 if (fdisk_ask_partnum(cxt, &i, FALSE))
24f4bbff 171 return;
2b6fc908 172
85151521
KZ
173 if (fdisk_get_partition(cxt, i, &pa)) {
174 fdisk_warnx(cxt, _("Partition %zu does not exist yet!"), i + 1);
175 return;
176 }
177
178 t = (struct fdisk_parttype *) fdisk_partition_get_type(pa);
179 old = t ? t->name : _("Unknown");
180
181 do {
182 t = ask_partition_type(cxt);
183 } while (!t);
184
85151521
KZ
185 if (fdisk_set_partition_type(cxt, i, t) == 0)
186 fdisk_sinfo(cxt, FDISK_INFO_SUCCESS,
187 _("Changed type of partition '%s' to '%s'."),
188 old, t ? t->name : _("Unknown"));
189 else
190 fdisk_info(cxt,
191 _("Type of partition %zu is unchanged: %s."),
192 i + 1, old);
193
d6cfa8b3 194 fdisk_unref_partition(pa);
6dbe3af9
KZ
195}
196
89309968 197void list_disk_geometry(struct fdisk_context *cxt)
21fe3dde
KZ
198{
199 char *id = NULL;
9af73f84
KZ
200 uint64_t bytes = cxt->total_sectors * cxt->sector_size;
201 char *strsz = size_to_human_string(SIZE_SUFFIX_SPACE
202 | SIZE_SUFFIX_3LETTER, bytes);
203
48d4d931 204 fdisk_colon(cxt, _("Disk %s: %s, %ju bytes, %ju sectors"),
e39966c6 205 cxt->dev_path, strsz,
48d4d931 206 bytes, (uintmax_t) cxt->total_sectors);
9af73f84 207 free(strsz);
b1b1a7b7 208
96dc2798 209 if (fdisk_require_geometry(cxt) || fdisk_context_use_cylinders(cxt))
ac1a559a 210 fdisk_colon(cxt, _("Geometry: %d heads, %llu sectors/track, %llu cylinders"),
9af73f84 211 cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders);
b1b1a7b7 212
ac1a559a 213 fdisk_colon(cxt, _("Units: %s of %d * %ld = %ld bytes"),
ec10aa67
KZ
214 fdisk_context_get_unit(cxt, PLURAL),
215 fdisk_context_get_units_per_sector(cxt),
216 cxt->sector_size,
217 fdisk_context_get_units_per_sector(cxt) * cxt->sector_size);
05dc9645 218
ac1a559a 219 fdisk_colon(cxt, _("Sector size (logical/physical): %lu bytes / %lu bytes"),
e53ced85 220 cxt->sector_size, cxt->phy_sector_size);
ac1a559a 221 fdisk_colon(cxt, _("I/O size (minimum/optimal): %lu bytes / %lu bytes"),
e53ced85
DB
222 cxt->min_io_size, cxt->io_size);
223 if (cxt->alignment_offset)
ac1a559a 224 fdisk_colon(cxt, _("Alignment offset: %lu bytes"),
9af73f84 225 cxt->alignment_offset);
b546d442 226 if (fdisk_dev_has_disklabel(cxt))
fd56121a 227 fdisk_colon(cxt, _("Disklabel type: %s"), cxt->label->name);
21fe3dde
KZ
228
229 if (fdisk_get_disklabel_id(cxt, &id) == 0 && id)
ac1a559a 230 fdisk_colon(cxt, _("Disk identifier: %s"), id);
5c36a0eb
KZ
231}
232
9f670072
KZ
233void list_disklabel(struct fdisk_context *cxt)
234{
235 struct fdisk_table *tb = NULL;
236 char *str;
237
238 /* print label specific stuff by libfdisk FDISK_ASK_INFO API */
239 fdisk_list_disklabel(cxt);
240
241 /* print partitions */
2cec7949 242 if (fdisk_get_partitions(cxt, &tb))
9f670072
KZ
243 return;
244 if (fdisk_table_to_string(tb, cxt, NULL, 0, &str) == 0) {
245 fputc('\n', stdout);
849968b9
KZ
246 if (str && *str)
247 fputs(str, stdout);
9f670072
KZ
248 }
249 fdisk_unref_table(tb);
250}
251
e916600f
KZ
252static size_t skip_empty(const unsigned char *buf, size_t i, size_t sz)
253{
254 size_t next;
255 const unsigned char *p0 = buf + i;
256
257 for (next = i + 16; next < sz; next += 16) {
258 if (memcmp(p0, buf + next, 16) != 0)
259 break;
260 }
261
262 return next == i + 16 ? i : next;
263}
6dbe3af9 264
e916600f 265static void dump_buffer(off_t base, unsigned char *buf, size_t sz, int all)
09f0c3d9 266{
e916600f
KZ
267 size_t i, l, next = 0;
268
269 if (!buf)
270 return;
271 for (i = 0, l = 0; i < sz; i++, l++) {
272 if (l == 0) {
273 if (all == 0 && !next)
274 next = skip_empty(buf, i, sz);
275 printf("%08jx ", base + i);
276 }
277 printf(" %02x", buf[i]);
278 if (l == 7) /* words separator */
279 fputs(" ", stdout);
280 else if (l == 15) {
281 fputc('\n', stdout); /* next line */
6dbe3af9 282 l = -1;
e916600f
KZ
283 if (next > i) {
284 printf("*\n");
285 i = next - 1;
286 }
287 next = 0;
6dbe3af9
KZ
288 }
289 }
290 if (l > 0)
291 printf("\n");
6dbe3af9
KZ
292}
293
e916600f
KZ
294static void dump_blkdev(struct fdisk_context *cxt, const char *name,
295 off_t offset, size_t size, int all)
e53ced85 296{
e916600f
KZ
297 fdisk_colon(cxt, _("\n%s: offset = %ju, size = %zu bytes."),
298 name, offset, size);
299
300 if (lseek(cxt->dev_fd, offset, SEEK_SET) == (off_t) -1)
301 fdisk_warn(cxt, _("cannot seek"));
5afed187
KZ
302 else {
303 unsigned char *buf = xmalloc(size);
304
305 if (read_all(cxt->dev_fd, (char *) buf, size) != (ssize_t) size)
306 fdisk_warn(cxt, _("cannot read"));
307 else
308 dump_buffer(offset, buf, size, all);
309 free(buf);
310 }
e916600f
KZ
311}
312
313void dump_firstsector(struct fdisk_context *cxt)
314{
315 int all = !isatty(STDOUT_FILENO);
316
e3661531
KZ
317 assert(cxt);
318 assert(cxt->label);
6dbe3af9 319
e916600f
KZ
320 dump_blkdev(cxt, _("First sector"), 0, cxt->sector_size, all);
321}
322
323void dump_disklabel(struct fdisk_context *cxt)
324{
325 int all = !isatty(STDOUT_FILENO);
326 int i = 0;
327 const char *name = NULL;
328 off_t offset = 0;
329 size_t size = 0;
330
331 assert(cxt);
332 assert(cxt->label);
e3661531 333
e916600f
KZ
334 while (fdisk_locate_disklabel(cxt, i++, &name, &offset, &size) == 0 && size)
335 dump_blkdev(cxt, name, offset, size, all);
6dbe3af9
KZ
336}
337
3b622ddd
DB
338static int is_ide_cdrom_or_tape(char *device)
339{
340 int fd, ret;
2b6fc908 341
1c6b3378 342 if ((fd = open(device, O_RDONLY)) < 0)
e8f26419 343 return 0;
3b622ddd 344 ret = blkdev_is_cdrom(fd);
2b6fc908 345
3b622ddd
DB
346 close(fd);
347 return ret;
2b6fc908
KZ
348}
349
6aa2ed3b 350static void print_device_pt(struct fdisk_context *cxt, char *device)
e27b42d5 351{
4e0e8253 352 if (fdisk_context_assign_device(cxt, device, 1) != 0) /* read-only */
289dcc90 353 err(EXIT_FAILURE, _("cannot open %s"), device);
823f0fd1 354
5e860870
KZ
355 list_disk_geometry(cxt);
356
b4fb2a61 357 if (fdisk_dev_has_disklabel(cxt))
9f670072 358 list_disklabel(cxt);
4ec31f10 359 fputc('\n', stdout);
6dbe3af9
KZ
360}
361
6aa2ed3b 362static void print_all_devices_pt(struct fdisk_context *cxt)
ea4824f1 363{
6aa2ed3b
KZ
364 FILE *f;
365 char line[128 + 1];
366
367 f = fopen(_PATH_PROC_PARTITIONS, "r");
368 if (!f) {
369 warn(_("cannot open %s"), _PATH_PROC_PARTITIONS);
eb63b9b8
KZ
370 return;
371 }
372
d31d3fc7
KZ
373 DBG(FRONTEND, dbgprint("reading "_PATH_PROC_PARTITIONS));
374
6aa2ed3b
KZ
375 while (fgets(line, sizeof(line), f)) {
376 char ptname[128 + 1], devname[256];
377
d31d3fc7 378 if (sscanf(line, " %*d %*d %*d %128[^\n ]", ptname) != 1)
eb63b9b8 379 continue;
6aa2ed3b 380
c07ebfa1 381 snprintf(devname, sizeof(devname), "/dev/%s", ptname);
d31d3fc7
KZ
382
383 DBG(FRONTEND, dbgprint("listing %s", devname));
384
6bec8710
KZ
385 if (is_whole_disk(devname)) {
386 char *cn = canonicalize_path(devname);
387 if (cn) {
0c48d371 388 if (!is_ide_cdrom_or_tape(cn))
6aa2ed3b 389 print_device_pt(cxt, cn);
6bec8710
KZ
390 free(cn);
391 }
392 }
eb63b9b8 393 }
6aa2ed3b 394 fclose(f);
eb63b9b8
KZ
395}
396
50dec1eb 397static sector_t get_dev_blocks(char *dev)
6da365de
DB
398{
399 int fd;
50dec1eb 400 sector_t size;
6da365de
DB
401
402 if ((fd = open(dev, O_RDONLY)) < 0)
289dcc90 403 err(EXIT_FAILURE, _("cannot open %s"), dev);
7737f698
DB
404 if (blkdev_get_sectors(fd, &size) == -1) {
405 close(fd);
406 err(EXIT_FAILURE, _("BLKGETSIZE ioctl failed on %s"), dev);
407 }
6da365de
DB
408 close(fd);
409 return size/2;
410}
411
5b72b3dd
KZ
412enum {
413 ACT_FDISK = 0, /* default */
414 ACT_LIST,
415 ACT_SHOWSIZE
416};
417
e1144767
DB
418int main(int argc, char **argv)
419{
5b72b3dd 420 int i, c, act = ACT_FDISK;
d0c9ddc3 421 int colormode = UL_COLORMODE_UNDEF;
4e0e8253 422 struct fdisk_context *cxt;
2b6fc908 423
7eda085c
KZ
424 setlocale(LC_ALL, "");
425 bindtextdomain(PACKAGE, LOCALEDIR);
426 textdomain(PACKAGE);
b2d28533 427 atexit(close_stdout);
2b6fc908 428
4e0e8253
KZ
429 fdisk_init_debug(0);
430 cxt = fdisk_new_context();
431 if (!cxt)
432 err(EXIT_FAILURE, _("failed to allocate libfdisk context"));
433
416c43a9
KZ
434 fdisk_context_set_ask(cxt, ask_callback, NULL);
435
565b7da6 436 while ((c = getopt(argc, argv, "b:c::C:hH:lL::sS:t:u::vV")) != -1) {
2b6fc908
KZ
437 switch (c) {
438 case 'b':
6bcd192c
KZ
439 {
440 size_t sz = strtou32_or_err(optarg,
441 _("invalid sector size argument"));
442 if (sz != 512 && sz != 1024 && sz != 2048 && sz != 4096)
7c1db6b4 443 usage(stderr);
6bcd192c 444 fdisk_save_user_sector_size(cxt, sz, sz);
2b6fc908 445 break;
6bcd192c 446 }
0e6f4a20 447 case 'C':
1653f0b0
KZ
448 fdisk_save_user_geometry(cxt,
449 strtou32_or_err(optarg,
450 _("invalid cylinders argument")),
451 0, 0);
0e6f4a20 452 break;
78498b7b 453 case 'c':
852ce62b 454 if (optarg) {
2b0bc17b
KZ
455 /* this setting is independent on the current
456 * actively used label */
5b72b3dd 457 struct fdisk_label *lb = fdisk_context_get_label(cxt, "dos");
852ce62b
KZ
458 if (!lb)
459 err(EXIT_FAILURE, _("not found DOS label driver"));
460 if (strcmp(optarg, "=dos") == 0)
461 fdisk_dos_enable_compatible(lb, TRUE);
462 else if (strcmp(optarg, "=nondos") == 0)
463 fdisk_dos_enable_compatible(lb, FALSE);
464 else
465 usage(stderr);
466 }
467 /* use default if no optarg specified */
78498b7b 468 break;
0e6f4a20 469 case 'H':
1653f0b0
KZ
470 fdisk_save_user_geometry(cxt, 0,
471 strtou32_or_err(optarg,
472 _("invalid heads argument")),
473 0);
0e6f4a20
KZ
474 break;
475 case 'S':
1653f0b0
KZ
476 fdisk_save_user_geometry(cxt, 0, 0,
477 strtou32_or_err(optarg,
478 _("invalid sectors argument")));
0e6f4a20 479 break;
2b6fc908 480 case 'l':
5b72b3dd 481 act = ACT_LIST;
2b6fc908 482 break;
80a1712f
KZ
483 case 'L':
484 if (optarg)
485 colormode = colormode_or_err(optarg,
486 _("unsupported color mode"));
487 break;
2b6fc908 488 case 's':
5b72b3dd 489 act = ACT_SHOWSIZE;
2b6fc908 490 break;
565b7da6
KZ
491 case 't':
492 {
493 struct fdisk_label *lb = NULL;
494
495 while (fdisk_context_next_label(cxt, &lb) == 0)
496 fdisk_label_set_disabled(lb, 1);
497
498 lb = fdisk_context_get_label(cxt, optarg);
499 if (!lb)
500 errx(EXIT_FAILURE, _("unsupported disklabel: %s"), optarg);
501 fdisk_label_set_disabled(lb, 0);
502 }
2b6fc908 503 case 'u':
ec10aa67
KZ
504 if (optarg && *optarg == '=')
505 optarg++;
506 if (fdisk_context_set_unit(cxt, optarg) != 0)
7c1db6b4 507 usage(stderr);
2b6fc908 508 break;
22853e4a 509 case 'V':
2b6fc908 510 case 'v':
a2482eb3
DB
511 printf(UTIL_LINUX_VERSION);
512 return EXIT_SUCCESS;
e1144767
DB
513 case 'h':
514 usage(stdout);
2b6fc908 515 default:
7c1db6b4 516 usage(stderr);
2b6fc908 517 }
6dbe3af9 518 }
2b6fc908 519
6bcd192c
KZ
520 if (argc-optind != 1 && fdisk_has_user_device_properties(cxt))
521 warnx(_("The device properties (sector size and geometry) should"
522 " be used with one specified device only."));
7eda085c 523
d0c9ddc3 524 colors_init(colormode, "fdisk");
ffcf0540 525
5b72b3dd
KZ
526 switch (act) {
527 case ACT_LIST:
c10937dc 528 fdisk_context_enable_listonly(cxt, 1);
ffcf0540 529
2b6fc908
KZ
530 if (argc > optind) {
531 int k;
c129767e 532 for (k = optind; k < argc; k++)
6aa2ed3b 533 print_device_pt(cxt, argv[k]);
ea4824f1 534 } else
6aa2ed3b 535 print_all_devices_pt(cxt);
5b72b3dd 536 break;
2b6fc908 537
5b72b3dd 538 case ACT_SHOWSIZE:
9564e46c 539 /* deprecated */
5b72b3dd 540 if (argc - optind <= 0)
7c1db6b4 541 usage(stderr);
2b6fc908 542
6da365de 543 for (i = optind; i < argc; i++) {
5b72b3dd 544 if (argc - optind == 1)
6da365de 545 printf("%llu\n", get_dev_blocks(argv[i]));
2b6fc908 546 else
6da365de 547 printf("%s: %llu\n", argv[i], get_dev_blocks(argv[i]));
6dbe3af9 548 }
5b72b3dd 549 break;
6dbe3af9 550
5b72b3dd
KZ
551 case ACT_FDISK:
552 if (argc-optind != 1)
553 usage(stderr);
7eda085c 554
5b72b3dd 555 /* Here starts interactive mode, use fdisk_{warn,info,..} functions */
80a1712f 556 color_enable(UL_COLOR_GREEN);
09f0c3d9 557 fdisk_info(cxt, _("Welcome to fdisk (%s)."), PACKAGE_STRING);
80a1712f
KZ
558 color_disable();
559 fdisk_info(cxt, _("Changes will remain in memory only, until you decide to write them.\n"
560 "Be careful before using the write command.\n"));
2d8988bd
KZ
561
562 if (fdisk_context_assign_device(cxt, argv[optind], 0) != 0)
563 err(EXIT_FAILURE, _("cannot open %s"), argv[optind]);
564
5b72b3dd 565 fflush(stdout);
56c07b96 566
5b72b3dd 567 if (!fdisk_dev_has_disklabel(cxt)) {
2d8988bd 568 fdisk_info(cxt, _("Device does not contain a recognized partition table."));
5b72b3dd 569 fdisk_create_disklabel(cxt, NULL);
433d05ff
KZ
570
571 } else if (fdisk_is_disklabel(cxt, GPT) && fdisk_gpt_is_hybrid(cxt))
572 fdisk_warnx(cxt, _(
573 "The hybrid GPT detected. You have to sync "
574 "the hybrid MBR manually (expert command 'M')."));
6dbe3af9 575
5b72b3dd
KZ
576 while (1)
577 process_fdisk_menu(&cxt);
578 }
9777759a 579
4e0e8253 580 fdisk_free_context(cxt);
5b72b3dd 581 return EXIT_SUCCESS;
6dbe3af9 582}