]> git.ipfire.org Git - thirdparty/util-linux.git/blame - disk-utils/sfdisk.c
libfdisk: add fdisk_copy_parttype()
[thirdparty/util-linux.git] / disk-utils / sfdisk.c
CommitLineData
fd6b7a7f 1/*
fd6b7a7f 2 * Copyright (C) 1995 Andries E. Brouwer (aeb@cwi.nl)
1881390d 3 * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
fd6b7a7f
KZ
4 *
5 * This program is free software. You can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation: either Version 1
8 * or (at your option) any later version.
9 *
10 * A.V. Le Blanc (LeBlanc@mcc.ac.uk) wrote Linux fdisk 1992-1994,
11 * patched by various people (faith@cs.unc.edu, martin@cs.unc.edu,
12 * leisner@sdsp.mc.xerox.com, esr@snark.thyrsus.com, aeb@cwi.nl)
13 * 1993-1995, with version numbers (as far as I have seen) 0.93 - 2.0e.
14 * This program had (head,sector,cylinder) as basic unit, and was
15 * (therefore) broken in several ways for the use on larger disks -
16 * for example, my last patch (from 2.0d to 2.0e) was required
17 * to allow a partition to cross cylinder 8064, and to write an
18 * extended partition past the 4GB mark.
19 *
1881390d
KZ
20 * Karel Zak wrote new sfdisk based on libfdisk from util-linux
21 * in 2014.
fd6b7a7f
KZ
22 */
23
1881390d 24#include <unistd.h>
fd6b7a7f 25#include <stdio.h>
1881390d
KZ
26#include <stdlib.h>
27#include <string.h>
fd6b7a7f 28#include <ctype.h>
1881390d 29#include <errno.h>
fd6b7a7f 30#include <getopt.h>
fd6b7a7f 31#include <sys/stat.h>
9c1f9dd3 32#include <assert.h>
11ef0c35
KZ
33
34#include "c.h"
109dbc4f 35#include "xalloc.h"
1881390d
KZ
36#include "nls.h"
37#include "debug.h"
9912f01b 38#include "strutils.h"
1881390d 39#include "closestream.h"
9c1f9dd3 40#include "colors.h"
d2eb1457 41#include "blkdev.h"
fd6b7a7f 42
1881390d 43#include "libfdisk.h"
9c1f9dd3 44#include "fdisk-list.h"
fd6b7a7f
KZ
45
46/*
1881390d 47 * sfdisk debug stuff (see fdisk.h and include/debug.h)
fd6b7a7f 48 */
1881390d
KZ
49UL_DEBUG_DEFINE_MASK(sfdisk);
50UL_DEBUG_DEFINE_MASKANEMS(sfdisk) = UL_DEBUG_EMPTY_MASKNAMES;
fd6b7a7f 51
1881390d
KZ
52#define SFDISKPROG_DEBUG_INIT (1 << 1)
53#define SFDISKPROG_DEBUG_PARSE (1 << 2)
54#define SFDISKPROG_DEBUG_MISC (1 << 3)
e8813494 55#define SFDISKPROG_DEBUG_ASK (1 << 4)
1881390d 56#define SFDISKPROG_DEBUG_ALL 0xFFFF
fd6b7a7f 57
1881390d
KZ
58#define DBG(m, x) __UL_DBG(sfdisk, SFDISKPROG_DEBUG_, m, x)
59#define ON_DBG(m, x) __UL_DBG_CALL(sfdisk, SFDISKPROG_DEBUG_, m, x)
fd6b7a7f 60
9c1f9dd3
KZ
61enum {
62 ACT_FDISK = 0, /* default */
63
64 ACT_ACTIVATE,
65 ACT_CHANGE_ID,
66 ACT_DUMP,
67 ACT_LIST,
9c1f9dd3 68 ACT_LIST_TYPES,
d2eb1457 69 ACT_SHOW_SIZE,
9c1f9dd3
KZ
70 ACT_VERIFY
71};
72
73struct sfdisk {
74 int act; /* action */
7324f1bf
KZ
75 int partno; /* -N <partno>, default -1 */
76 const char *label; /* --label <label> */
9c1f9dd3
KZ
77
78 struct fdisk_context *cxt; /* libfdisk context */
79};
80
fd6b7a7f 81
1881390d
KZ
82static void sfdiskprog_init_debug(void)
83{
84 __UL_INIT_DEBUG(sfdisk, SFDISKPROG_DEBUG_, 0, SFDISK_DEBUG);
fd6b7a7f
KZ
85}
86
e8813494
KZ
87
88static int get_user_reply(const char *prompt, char *buf, size_t bufsz)
89{
90 char *p;
91 size_t sz;
92
93 fputs(prompt, stdout);
94 fflush(stdout);
95
96 if (!fgets(buf, bufsz, stdin))
97 return 1;
98
99 for (p = buf; *p && !isgraph(*p); p++); /* get first non-blank */
100
101 if (p > buf)
102 memmove(buf, p, p - buf); /* remove blank space */
103 sz = strlen(buf);
104 if (sz && *(buf + sz - 1) == '\n')
105 *(buf + sz - 1) = '\0';
106
107 DBG(ASK, ul_debug("user's reply: >>>%s<<<", buf));
108 return 0;
109}
110
9c1f9dd3
KZ
111static int ask_callback(struct fdisk_context *cxt, struct fdisk_ask *ask,
112 void *data __attribute__((__unused__)))
113{
e8813494
KZ
114 int rc = 0;
115
9c1f9dd3
KZ
116 assert(cxt);
117 assert(ask);
118
119 switch(fdisk_ask_get_type(ask)) {
120 case FDISK_ASKTYPE_INFO:
121 fputs(fdisk_ask_print_get_mesg(ask), stdout);
122 fputc('\n', stdout);
123 break;
124 case FDISK_ASKTYPE_WARNX:
125 color_scheme_fenable("warn", UL_COLOR_RED, stderr);
126 fputs(fdisk_ask_print_get_mesg(ask), stderr);
127 color_fdisable(stderr);
128 fputc('\n', stderr);
129 break;
130 case FDISK_ASKTYPE_WARN:
131 color_scheme_fenable("warn", UL_COLOR_RED, stderr);
132 fputs(fdisk_ask_print_get_mesg(ask), stderr);
133 errno = fdisk_ask_print_get_errno(ask);
134 fprintf(stderr, ": %m\n");
135 color_fdisable(stderr);
136 break;
e8813494
KZ
137 case FDISK_ASKTYPE_YESNO:
138 {
139 char buf[BUFSIZ];
140 fputc('\n', stdout);
141 do {
142 int x;
143 fputs(fdisk_ask_get_query(ask), stdout);
144 rc = get_user_reply(_(" [Y]es/[N]o: "), buf, sizeof(buf));
145 if (rc)
146 break;
147 x = rpmatch(buf);
148 if (x == 1 || x == 0) {
149 fdisk_ask_yesno_set_result(ask, x);
150 break;
151 }
152 } while(1);
153 DBG(ASK, ul_debug("yes-no ask: reply '%s' [rc=%d]", buf, rc));
154 break;
155 }
9c1f9dd3
KZ
156 default:
157 break;
158 }
e8813494 159 return rc;
9c1f9dd3
KZ
160}
161
162static void sfdisk_init(struct sfdisk *sf)
163{
164 fdisk_init_debug(0);
165 sfdiskprog_init_debug();
166
167 colors_init(UL_COLORMODE_UNDEF, "sfdisk");
168
169 sf->cxt = fdisk_new_context();
170 if (!sf->cxt)
171 err(EXIT_FAILURE, _("failed to allocate libfdisk context"));
172 fdisk_set_ask(sf->cxt, ask_callback, NULL);
173}
174
175static int sfdisk_deinit(struct sfdisk *sf)
176{
177 int rc;
178
179 assert(sf);
180 assert(sf->cxt);
181
9c1f9dd3
KZ
182 fdisk_unref_context(sf->cxt);
183 memset(sf, 0, sizeof(*sf));
184
185 return rc;
186}
187
148f6e6d
KZ
188/*
189 * sfdisk --list [<device ..]
190 */
9c1f9dd3
KZ
191static int command_list_partitions(struct sfdisk *sf, int argc, char **argv)
192{
9c1f9dd3
KZ
193 fdisk_enable_listonly(sf->cxt, 1);
194
207de32a 195 if (argc) {
d2eb1457 196 int i, ct = 0;
8a8d204c
KZ
197
198 for (i = 0; i < argc; i++) {
199 if (ct)
200 fputs("\n\n", stdout);
201 if (print_device_pt(sf->cxt, argv[i], 0) == 0)
202 ct++;
203 }
9c1f9dd3
KZ
204 } else
205 print_all_devices_pt(sf->cxt);
206
207 return 0;
208}
209
148f6e6d 210static int get_size(const char *dev, int silent, uintmax_t *sz)
d2eb1457 211{
148f6e6d
KZ
212 int fd, rc = 0;
213
214 fd = open(dev, O_RDONLY);
d2eb1457
KZ
215 if (fd < 0) {
216 if (!silent)
217 warn(_("cannot open: %s"), dev);
218 return -errno;
219 }
d2eb1457
KZ
220
221 if (blkdev_get_sectors(fd, (unsigned long long *) sz) == -1) {
222 if (!silent)
223 warn(_("Cannot get size of %s"), dev);
224 rc = -errno;
225 }
226
227 close(fd);
228 return rc;
229}
230
148f6e6d
KZ
231/*
232 * sfdisk --show-size [<device ..]
233 *
234 * (silly, but just for backward compatibility)
235 */
d2eb1457
KZ
236static int command_show_size(struct sfdisk *sf __attribute__((__unused__)),
237 int argc, char **argv)
238{
239 uintmax_t sz;
240
241 if (argc) {
242 int i;
243 for (i = 0; i < argc; i++) {
244 if (get_size(argv[i], 0, &sz) == 0)
245 printf("%ju\n", sz / 2);
246 }
247 } else {
248 FILE *f = NULL;
249 uintmax_t total = 0;
250 char *dev;
251
252 while ((dev = next_proc_partition(&f))) {
253 if (get_size(dev, 1, &sz) == 0) {
254 printf("%s: %9ju\n", dev, sz / 2);
255 total += sz / 2;
256 }
257 free(dev);
258 }
259 if (total)
260 printf(_("total: %ju blocks\n"), total);
261 }
262
263 return 0;
264}
265
254b1dfc
KZ
266/*
267 * sfdisk --activate <device> [<partno> ...]
268 */
54b13b0c
KZ
269static int command_activate(struct sfdisk *sf, int argc, char **argv)
270{
271 int rc, nparts, i;
272 struct fdisk_partition *pa = NULL;
273 const char *devname = NULL;
274
275 if (argc)
276 devname = argv[0];
277 else
278 errx(EXIT_FAILURE, _("no disk device specified"));
279 if (argc > 2)
280 errx(EXIT_FAILURE, _("uneexpected arguments"));
281
282 rc = fdisk_assign_device(sf->cxt, devname, 0);
283 if (rc)
284 err(EXIT_FAILURE, _("cannot open %s"), devname);
285
286 if (!fdisk_is_label(sf->cxt, DOS))
287 errx(EXIT_FAILURE, _("toggle boot flags is supported for MBR only"));
288
289 nparts = fdisk_get_npartitions(sf->cxt);
290 for (i = 0; i < nparts; i++) {
291 char *data = NULL;
292
293 /* note that fdisk_get_partition() reuses the @pa pointer, you
294 * don't have to (re)allocate it */
295 if (fdisk_get_partition(sf->cxt, i, &pa) != 0)
296 continue;
297
298 /* sfdisk --activate list bootable partitions */
299 if (argc == 1) {
300 if (!fdisk_partition_is_bootable(pa))
301 continue;
302 if (fdisk_partition_to_string(pa, sf->cxt,
303 FDISK_FIELD_DEVICE, &data) == 0) {
304 printf("%s\n", data);
305 free(data);
306 }
307
308 /* deactivate all active partitions */
309 } else if (fdisk_partition_is_bootable(pa))
310 fdisk_partition_toggle_flag(sf->cxt, i, DOS_FLAG_ACTIVE);
311 }
312
313 /* sfdisk --activate <partno> [..] */
314 for (i = 1; i < argc; i++) {
315 int n = strtou32_or_err(argv[i], _("failed to parse partition number"));
316
254b1dfc
KZ
317 rc = fdisk_partition_toggle_flag(sf->cxt, n - 1, DOS_FLAG_ACTIVE);
318 if (rc)
319 errx(EXIT_FAILURE,
320 _("%s: #%d: failed to toggle bootable flag"),
321 devname, i + 1);
54b13b0c
KZ
322 }
323
324 fdisk_unref_partition(pa);
325 rc = fdisk_write_disklabel(sf->cxt);
326 if (!rc)
327 rc = fdisk_deassign_device(sf->cxt, 1);
328 return rc;
329}
330
148f6e6d
KZ
331/*
332 * sfdisk --dump <device>
333 */
8a8d204c
KZ
334static int command_dump(struct sfdisk *sf, int argc, char **argv)
335{
336 const char *devname = NULL;
337 struct fdisk_script *dp;
338 int rc;
339
340 if (argc)
341 devname = argv[0];
342 if (!devname)
343 errx(EXIT_FAILURE, _("no disk device specified"));
344
345 rc = fdisk_assign_device(sf->cxt, devname, 1);
346 if (rc)
347 err(EXIT_FAILURE, _("cannot open %s"), devname);
348
349 dp = fdisk_new_script(sf->cxt);
350 if (!dp)
351 err(EXIT_FAILURE, _("failed to allocate dump struct"));
352
353 rc = fdisk_script_read_context(dp, NULL);
354 if (rc)
355 err(EXIT_FAILURE, _("failed to dump partition table"));
356
357 fdisk_script_write_file(dp, stdout);
358
359 fdisk_unref_script(dp);
360 return 0;
361}
362
7324f1bf
KZ
363
364static void sfdisk_print_partition(struct sfdisk *sf, int n)
365{
c3bc7483 366 struct fdisk_partition *pa = NULL;
7324f1bf
KZ
367 char *data;
368
369 assert(sf);
370
371 if (fdisk_get_partition(sf->cxt, n, &pa) != 0)
372 return;
373
374 fdisk_partition_to_string(pa, sf->cxt, FDISK_FIELD_DEVICE, &data);
375 printf("%12s : ", data);
376
377 fdisk_partition_to_string(pa, sf->cxt, FDISK_FIELD_START, &data);
378 printf("%12s ", data);
379
380 fdisk_partition_to_string(pa, sf->cxt, FDISK_FIELD_END, &data);
381 printf("%12s ", data);
382
383 fdisk_partition_to_string(pa, sf->cxt, FDISK_FIELD_SIZE, &data);
384 printf("(%s) ", data);
385
386 fdisk_partition_to_string(pa, sf->cxt, FDISK_FIELD_TYPE, &data);
387 printf("%s\n", data);
388
389 fdisk_unref_partition(pa);
390}
391
3186f4a9
KZ
392static void command_fdisk_help(void)
393{
394 fputs(_("\nHelp:\n"), stdout);
395
396 fputc('\n', stdout);
397 color_scheme_enable("help-title", UL_COLOR_BOLD);
398 fputs(_(" Commands:\n"), stdout);
399 color_disable();
e8813494
KZ
400 fputs(_(" write write table to disk and exit\n"), stdout);
401 fputs(_(" quit show new situation and wait for user's feedbadk before write\n"), stdout);
402 fputs(_(" abort exit sfdisk shell\n"), stdout);
3186f4a9
KZ
403 fputs(_(" print print partition table.\n"), stdout);
404 fputs(_(" help this help.\n"), stdout);
405
406 fputc('\n', stdout);
407 color_scheme_enable("help-title", UL_COLOR_BOLD);
408 fputs(_(" Input format:\n"), stdout);
409 color_disable();
410 fputs(_(" <start> <size> <typy> <bootable>\n"), stdout);
411
412 fputc('\n', stdout);
413 fputs(_(" <start> begin of the partition in sectors. The default is the first\n"
414 " free space.\n"), stdout);
415
416 fputc('\n', stdout);
417 fputs(_(" <size> size of the partition in sectors if specified in format\n"
418 " <number>{K,M,G,T,P,E,Z,Y} then it's interpreted as size\n"
419 " in bytes. The default is all available space.\n"), stdout);
420
421 fputc('\n', stdout);
422 fputs(_(" <type> partition type. The default is Linux data partition.\n"), stdout);
423 fputs(_(" MBR: hex or L,S,E,X shortcuts.\n"), stdout);
424 fputs(_(" GPT: uuid or L,S,H shortcuts.\n"), stdout);
425
426 fputc('\n', stdout);
427 fputs(_(" <bootable> '*' to mark MBR partition as bootable. \n"), stdout);
428
429 fputc('\n', stdout);
430 color_scheme_enable("help-title", UL_COLOR_BOLD);
431 fputs(_(" Example:\n"), stdout);
432 color_disable();
433 fputs(_(" , 4G creates 4GiB partition on default start offset.\n"), stdout);
434 fputc('\n', stdout);
435}
436
e8813494
KZ
437enum {
438 SFDISK_DONE_NONE = 0,
439 SFDISK_DONE_EOF,
440 SFDISK_DONE_ABORT,
441 SFDISK_DONE_WRITE,
442 SFDISK_DONE_ASK
443};
444
445/* returns: 0 on success, <0 on error, 1 successfully stop sfdisk */
446static int loop_control_commands(struct sfdisk *sf,
447 struct fdisk_script *dp,
448 char *buf)
449{
450 const char *p = skip_blank(buf);
451 int rc = SFDISK_DONE_NONE;
452
453 if (strcmp(p, "print") == 0)
454 list_disklabel(sf->cxt);
455 else if (strcmp(p, "help") == 0)
456 command_fdisk_help();
457 else if (strcmp(p, "quit") == 0)
458 rc = SFDISK_DONE_ASK;
459 else if (strcmp(p, "write") == 0)
460 rc = SFDISK_DONE_WRITE;
461 else if (strcmp(p, "abort") == 0)
462 rc = SFDISK_DONE_ABORT;
463 else {
464 if (isatty(STDIN_FILENO))
465 fdisk_warnx(sf->cxt, _("unsupported command"));
466 else {
467 fdisk_warnx(sf->cxt, _("line %d: unsupported command"),
468 fdisk_script_get_nlines(dp));
469 rc = -EINVAL;
470 }
471 }
472 return rc;
473}
474
3186f4a9 475
254b1dfc
KZ
476/*
477 * sfdisk <device> [[-N] <partno>]
478 *
479 * Note that the option -N is there for backward compatibility only.
480 */
7324f1bf 481static int command_fdisk(struct sfdisk *sf, int argc, char **argv)
9c1f9dd3 482{
7324f1bf
KZ
483 int rc = 0, partno = sf->partno, created = 0;
484 struct fdisk_script *dp;
485 struct fdisk_table *tb = NULL;
486 const char *devname = NULL, *label;
487 char buf[BUFSIZ];
c3bc7483 488 size_t next_partno = (size_t) -1;
9c1f9dd3 489
8a8d204c
KZ
490 if (argc)
491 devname = argv[0];
254b1dfc 492 if (partno < 0 && argc > 1)
54b13b0c 493 partno = strtou32_or_err(argv[1],
9c1f9dd3 494 _("failed to parse partition number"));
8a8d204c 495 if (!devname)
9c1f9dd3
KZ
496 errx(EXIT_FAILURE, _("no disk device specified"));
497
7324f1bf
KZ
498 dp = fdisk_new_script(sf->cxt);
499 if (!dp)
500 err(EXIT_FAILURE, _("failed to allocate script handler"));
501
8a8d204c
KZ
502 rc = fdisk_assign_device(sf->cxt, devname, 0);
503 if (rc)
504 err(EXIT_FAILURE, _("cannot open %s"), devname);
9c1f9dd3 505
3186f4a9
KZ
506 if (isatty(STDIN_FILENO)) {
507 color_scheme_enable("welcome", UL_COLOR_GREEN);
508 fdisk_info(sf->cxt, _("\nWelcome to sfdisk (%s)."), PACKAGE_STRING);
509 color_disable();
510 fdisk_info(sf->cxt, _("Changes will remain in memory only, until you decide to write them.\n"
511 "Be careful before using the write command.\n"));
512 }
513
7324f1bf 514 list_disk_geometry(sf->cxt);
3186f4a9
KZ
515 if (fdisk_has_label(sf->cxt)) {
516 fdisk_info(sf->cxt, _("\nOld situation:"));
517 list_disklabel(sf->cxt);
518 }
7324f1bf
KZ
519
520 if (sf->label)
521 label = sf->label;
522 else if (fdisk_has_label(sf->cxt))
523 label = fdisk_label_get_name(fdisk_get_label(sf->cxt, NULL));
524 else
525 label = "dos"; /* just for backward compatibility */
526
527 fdisk_script_set_header(dp, "label", label);
528
3186f4a9
KZ
529 if (isatty(STDIN_FILENO)) {
530 if (!fdisk_has_label(sf->cxt) && !sf->label)
531 fdisk_info(sf->cxt,
532 _("\nsfdisk is going to create a new '%s' disk label.\n"
533 "Use 'label: <name>' before you define a first partition\n"
534 "to override the default."), label);
535 fdisk_info(sf->cxt, _("\nType 'help' to get more information.\n"));
536 } else
537 fputc('\n', stdout);
7324f1bf
KZ
538
539 tb = fdisk_script_get_table(dp);
c3bc7483 540 assert(tb);
7324f1bf
KZ
541
542 do {
c3bc7483 543 size_t nparts;
7324f1bf 544
c3bc7483
KZ
545 DBG(PARSE, ul_debug("<---next-line--->"));
546 if (next_partno == (size_t) -1)
547 next_partno = fdisk_table_get_nents(tb);
548
3186f4a9
KZ
549 if (created) {
550 char *partname = fdisk_partname(devname, next_partno + 1);
551 if (!partname)
552 err(EXIT_FAILURE, _("failed to allocate partition name"));
553 printf("%s: ", partname);
554 free(partname);
555 } else
556 printf(">>> ");
7324f1bf
KZ
557
558 rc = fdisk_script_read_line(dp, stdin, buf, sizeof(buf));
e8813494 559 if (rc < 0) {
c3bc7483 560 DBG(PARSE, ul_debug("script parsing failed, trying sfdisk specific commands"));
7324f1bf 561 buf[sizeof(buf) - 1] = '\0';
e8813494
KZ
562 rc = loop_control_commands(sf, dp, buf);
563 if (rc)
7324f1bf 564 break;
7324f1bf 565 continue;
e8813494
KZ
566 } else if (rc == 1) {
567 rc = SFDISK_DONE_EOF;
568 break;
7324f1bf
KZ
569 }
570
571 nparts = fdisk_table_get_nents(tb);
572 if (nparts) {
c3bc7483 573 size_t cur_partno;
7324f1bf
KZ
574 struct fdisk_partition *pa = fdisk_table_get_partition(tb, nparts - 1);
575
c3bc7483 576 assert(pa);
3186f4a9
KZ
577
578 if (!fdisk_partition_get_start(pa) &&
579 !fdisk_partition_start_is_default(pa)) {
580 fdisk_info(sf->cxt, _("Ignore partition %zu"), next_partno + 1);
581 continue;
582 }
7324f1bf
KZ
583 if (!created) { /* create a disklabel */
584 rc = fdisk_apply_script_headers(sf->cxt, dp);
585 created = !rc;
586 }
587 if (!rc) /* cretate partition */
c3bc7483 588 rc = fdisk_add_partition(sf->cxt, pa, &cur_partno);
7324f1bf 589
c3bc7483
KZ
590 if (!rc) { /* success, print reult */
591 sfdisk_print_partition(sf, cur_partno);
592 next_partno = cur_partno + 1;
593 } else if (pa) /* error, drop partition from script */
7324f1bf
KZ
594 fdisk_table_remove_partition(tb, pa);
595 } else
3186f4a9 596 fdisk_info(sf->cxt, _("Script header accepted."));
7324f1bf 597 } while (1);
254b1dfc 598
e8813494 599 if (rc != SFDISK_DONE_ABORT) {
3186f4a9 600 fdisk_info(sf->cxt, _("\nNew situation:"));
7324f1bf
KZ
601 list_disklabel(sf->cxt);
602 }
e8813494
KZ
603
604 switch (rc) {
605 case SFDISK_DONE_ASK:
606 if (isatty(STDIN_FILENO)) {
607 int yes = 0;
608 fdisk_ask_yesno(sf->cxt, _("Do you want to write this to disk?"), &yes);
609 if (!yes) {
610 printf(_("Leaving.\n"));
611 rc = 0;
612 break;
613 }
614 }
615 case SFDISK_DONE_EOF:
616 case SFDISK_DONE_WRITE:
254b1dfc 617 rc = fdisk_write_disklabel(sf->cxt);
e8813494
KZ
618 if (!rc) {
619 fdisk_info(sf->cxt, _("\nThe partition table has been altered."));
620 fdisk_reread_partition_table(sf->cxt);
621 rc = fdisk_deassign_device(sf->cxt, 0);
622 }
623 break;
624 case SFDISK_DONE_ABORT:
625 printf(_("Leaving.\n"));
626 break;
3186f4a9 627 }
e8813494 628
7324f1bf 629 fdisk_unref_script(dp);
9c1f9dd3
KZ
630 return rc;
631}
632
1881390d
KZ
633static void __attribute__ ((__noreturn__)) usage(FILE *out)
634{
635 fputs(USAGE_HEADER, out);
fd6b7a7f 636
1881390d 637 fprintf(out,
54b13b0c
KZ
638 _(" %1$s [options] --dump <device>\n"
639 " %1$s [options] --list [<device> ...]\n"
640 " %1$s [options] --activate <device> [<partno> ...]\n"),
e3bb13d9 641 program_invocation_short_name);
fd6b7a7f 642
1881390d 643 fputs(USAGE_OPTIONS, out);
54b13b0c 644 fputs(_(" -a, --activate mark MBR partitions as bootable\n"), out);
e3bb13d9
KZ
645 fputs(_(" -d, --dump dump partition table (suitable for later input)\n"), out);
646 fputs(_(" -l, --list list partitions of each device\n"), out);
8a8d204c 647
1881390d
KZ
648 fputs(USAGE_SEPARATOR, out);
649 fputs(USAGE_HELP, out);
650 fputs(USAGE_VERSION, out);
fd6b7a7f 651
1881390d
KZ
652 fprintf(out, USAGE_MAN_TAIL("sfdisk(8)"));
653 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
fd6b7a7f
KZ
654}
655
9c1f9dd3
KZ
656
657
1881390d
KZ
658int main(int argc, char *argv[])
659{
7324f1bf
KZ
660 int rc = -EINVAL, c;
661 struct sfdisk _sf = {
662 .act = 0,
663 .partno = -1
664 }, *sf = &_sf;
1881390d
KZ
665
666 static const struct option longopts[] = {
54b13b0c 667 { "activate",no_argument, NULL, 'a' },
9c1f9dd3 668 { "list", no_argument, NULL, 'l' },
8a8d204c 669 { "dump", no_argument, NULL, 'd' },
1881390d 670 { "help", no_argument, NULL, 'h' },
d2eb1457 671 { "show-size", no_argument, NULL, 's' },
254b1dfc 672 { "partno", required_argument, NULL, 'N' },
7324f1bf 673 { "label", required_argument, NULL, 'X' },
1881390d
KZ
674 { "version", no_argument, NULL, 'v' },
675 { NULL, 0, 0, 0 },
676 };
677
678 setlocale(LC_ALL, "");
679 bindtextdomain(PACKAGE, LOCALEDIR);
680 textdomain(PACKAGE);
681 atexit(close_stdout);
682
7324f1bf 683 while ((c = getopt_long(argc, argv, "adhlN:svX:", longopts, NULL)) != -1) {
1881390d 684 switch(c) {
54b13b0c
KZ
685 case 'a':
686 sf->act = ACT_ACTIVATE;
687 break;
1881390d
KZ
688 case 'h':
689 usage(stdout);
690 break;
9c1f9dd3
KZ
691 case 'l':
692 sf->act = ACT_LIST;
693 break;
8a8d204c
KZ
694 case 'd':
695 sf->act = ACT_DUMP;
696 break;
254b1dfc 697 case 'N':
7324f1bf
KZ
698 sf->partno = strtou32_or_err(optarg, _("failed to parse partition number"));
699 break;
700 case 'X':
701 sf->label = optarg;
254b1dfc 702 break;
d2eb1457
KZ
703 case 's':
704 sf->act = ACT_SHOW_SIZE;
705 break;
1881390d
KZ
706 case 'v':
707 printf(_("%s from %s\n"), program_invocation_short_name,
708 PACKAGE_STRING);
709 return EXIT_SUCCESS;
7324f1bf
KZ
710 default:
711 usage(stderr);
37b94458 712 }
37b94458 713 }
fd6b7a7f 714
9c1f9dd3 715 sfdisk_init(sf);
22853e4a 716
9c1f9dd3 717 switch (sf->act) {
54b13b0c
KZ
718 case ACT_ACTIVATE:
719 rc = command_activate(sf, argc - optind, argv + optind);
720 break;
721
9c1f9dd3
KZ
722 case ACT_LIST:
723 rc = command_list_partitions(sf, argc - optind, argv + optind);
724 break;
fd6b7a7f 725
9c1f9dd3 726 case ACT_FDISK:
7324f1bf 727 rc = command_fdisk(sf, argc - optind, argv + optind);
9c1f9dd3 728 break;
8a8d204c
KZ
729
730 case ACT_DUMP:
731 rc = command_dump(sf, argc - optind, argv + optind);
732 break;
d2eb1457
KZ
733
734 case ACT_SHOW_SIZE:
735 rc = command_show_size(sf, argc - optind, argv + optind);
736 break;
9c1f9dd3 737 }
fd6b7a7f 738
9c1f9dd3 739 sfdisk_deinit(sf);
fd6b7a7f 740
1881390d
KZ
741 DBG(MISC, ul_debug("bye! [rc=%d]", rc));
742 return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
4b1cc035
KZ
743}
744