2 * Copyright (C) 1995 Andries E. Brouwer (aeb@cwi.nl)
3 * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
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.
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.
20 * Karel Zak wrote new sfdisk based on libfdisk from util-linux
34 #include <libsmartcols.h>
35 #ifdef HAVE_LIBREADLINE
36 # define _FUNCTION_DEF
37 # include <readline/readline.h>
47 #include "closestream.h"
56 #include "fdisk-list.h"
59 * sfdisk debug stuff (see fdisk.h and include/debug.h)
61 static UL_DEBUG_DEFINE_MASK(sfdisk
);
62 UL_DEBUG_DEFINE_MASKNAMES(sfdisk
) = UL_DEBUG_EMPTY_MASKNAMES
;
64 #define SFDISKPROG_DEBUG_INIT (1 << 1)
65 #define SFDISKPROG_DEBUG_PARSE (1 << 2)
66 #define SFDISKPROG_DEBUG_MISC (1 << 3)
67 #define SFDISKPROG_DEBUG_ASK (1 << 4)
68 #define SFDISKPROG_DEBUG_ALL 0xFFFF
70 #define DBG(m, x) __UL_DBG(sfdisk, SFDISKPROG_DEBUG_, m, x)
71 #define ON_DBG(m, x) __UL_DBG_CALL(sfdisk, SFDISKPROG_DEBUG_, m, x)
98 int partno
; /* -N <partno>, default -1 */
99 int wipemode
; /* remove foreign signatures from disk */
100 int pwipemode
; /* remove foreign signatures from partitions */
101 const char *lockmode
; /* as specified by --lock */
102 const char *label
; /* --label <label> */
103 const char *label_nested
; /* --label-nested <label> */
104 const char *backup_file
; /* -O <path> */
105 const char *move_typescript
; /* --movedata <typescript> */
108 struct fdisk_context
*cxt
; /* libfdisk context */
109 struct fdisk_partition
*orig_pa
; /* -N <partno> before the change */
111 unsigned int verify
: 1, /* call fdisk_verify_disklabel() */
112 quiet
: 1, /* suppress extra messages */
113 interactive
: 1, /* running on tty */
114 noreread
: 1, /* don't check device is in use */
115 force
: 1, /* do also stupid things */
116 backup
: 1, /* backup sectors before write PT */
117 container
: 1, /* PT contains container (MBR extended) partitions */
118 unused
: 1, /* PT contains unused partition */
119 append
: 1, /* don't create new PT, append partitions only */
120 json
: 1, /* JSON dump */
121 movedata
: 1, /* move data after resize */
122 movefsync
: 1, /* use fsync() after each write() */
123 notell
: 1, /* don't tell kernel about new PT */
124 noact
: 1; /* do not write to device */
127 #define SFDISK_PROMPT ">>> "
129 static void sfdiskprog_init_debug(void)
131 __UL_INIT_DEBUG_FROM_ENV(sfdisk
, SFDISKPROG_DEBUG_
, 0, SFDISK_DEBUG
);
135 static int get_user_reply(const char *prompt
, char *buf
, size_t bufsz
)
140 #ifdef HAVE_LIBREADLINE
141 if (isatty(STDIN_FILENO
)) {
142 p
= readline(prompt
);
145 xstrncpy(buf
, p
, bufsz
);
150 fputs(prompt
, stdout
);
153 if (!fgets(buf
, bufsz
, stdin
))
157 for (p
= buf
; *p
&& !isgraph(*p
); p
++); /* get first non-blank */
160 memmove(buf
, p
, p
- buf
); /* remove blank space */
162 if (sz
&& *(buf
+ sz
- 1) == '\n')
163 *(buf
+ sz
- 1) = '\0';
165 DBG(ASK
, ul_debug("user's reply: >>>%s<<<", buf
));
169 static int ask_callback(struct fdisk_context
*cxt
__attribute__((__unused__
)),
170 struct fdisk_ask
*ask
,
173 struct sfdisk
*sf
= (struct sfdisk
*) data
;
178 switch(fdisk_ask_get_type(ask
)) {
179 case FDISK_ASKTYPE_INFO
:
182 fputs(fdisk_ask_print_get_mesg(ask
), stdout
);
185 case FDISK_ASKTYPE_WARNX
:
187 color_scheme_fenable("warn", UL_COLOR_RED
, stderr
);
188 fputs(fdisk_ask_print_get_mesg(ask
), stderr
);
189 color_fdisable(stderr
);
192 case FDISK_ASKTYPE_WARN
:
194 color_scheme_fenable("warn", UL_COLOR_RED
, stderr
);
195 fputs(fdisk_ask_print_get_mesg(ask
), stderr
);
196 errno
= fdisk_ask_print_get_errno(ask
);
197 fprintf(stderr
, ": %m\n");
198 color_fdisable(stderr
);
200 case FDISK_ASKTYPE_YESNO
:
202 char buf
[BUFSIZ
] = { '\0' };
206 fputs(fdisk_ask_get_query(ask
), stdout
);
207 rc
= get_user_reply(_(" [Y]es/[N]o: "), buf
, sizeof(buf
));
211 if (x
== RPMATCH_YES
|| x
== RPMATCH_NO
) {
212 fdisk_ask_yesno_set_result(ask
, x
);
216 DBG(ASK
, ul_debug("yes-no ask: reply '%s' [rc=%d]", buf
, rc
));
225 static void sfdisk_init(struct sfdisk
*sf
)
229 sfdiskprog_init_debug();
231 sf
->cxt
= fdisk_new_context();
233 err(EXIT_FAILURE
, _("failed to allocate libfdisk context"));
234 fdisk_set_ask(sf
->cxt
, ask_callback
, (void *) sf
);
236 if (sf
->wipemode
!= WIPEMODE_ALWAYS
)
237 fdisk_enable_bootbits_protection(sf
->cxt
, 1);
239 if (sf
->label_nested
) {
240 struct fdisk_context
*x
= fdisk_new_nested_context(sf
->cxt
,
243 err(EXIT_FAILURE
, _("failed to allocate nested libfdisk context"));
244 /* the original context is available by fdisk_get_parent() */
249 static int sfdisk_deinit(struct sfdisk
*sf
)
251 struct fdisk_context
*parent
;
256 parent
= fdisk_get_parent(sf
->cxt
);
258 fdisk_unref_context(sf
->cxt
);
262 fdisk_unref_context(sf
->cxt
);
265 memset(sf
, 0, sizeof(*sf
));
269 static struct fdisk_partition
*get_partition(struct fdisk_context
*cxt
, size_t partno
)
271 struct fdisk_table
*tb
= NULL
;
272 struct fdisk_partition
*pa
;
274 if (fdisk_get_partitions(cxt
, &tb
) != 0)
277 pa
= fdisk_table_get_partition_by_partno(tb
, partno
);
279 fdisk_ref_partition(pa
);
280 fdisk_unref_table(tb
);
284 static void backup_sectors(struct sfdisk
*sf
,
288 uint64_t offset
, size_t size
)
293 devfd
= fdisk_get_devfd(sf
->cxt
);
296 xasprintf(&fname
, "%s0x%08"PRIx64
".bak", tpl
, offset
);
298 fd
= open(fname
, O_CREAT
| O_WRONLY
, S_IRUSR
| S_IWUSR
);
302 if (lseek(devfd
, (off_t
) offset
, SEEK_SET
) == (off_t
) -1) {
303 fdisk_warn(sf
->cxt
, _("cannot seek %s"), devname
);
306 unsigned char *buf
= xmalloc(size
);
308 if (read_all(devfd
, (char *) buf
, size
) != (ssize_t
) size
) {
309 fdisk_warn(sf
->cxt
, _("cannot read %s"), devname
);
313 if (write_all(fd
, buf
, size
) != 0) {
314 fdisk_warn(sf
->cxt
, _("cannot write %s"), fname
);
321 fdisk_info(sf
->cxt
, _("%12s (offset %5ju, size %5ju): %s"),
322 name
, (uintmax_t) offset
, (uintmax_t) size
, fname
);
327 errx(EXIT_FAILURE
, _("%s: failed to create a backup"), devname
);
330 static char *mk_backup_filename_tpl(const char *filename
, const char *devname
, const char *suffix
)
333 char *name
, *buf
= xstrdup(devname
);
335 name
= basename(buf
);
337 if (!filename
|| strcmp(filename
, "@default") == 0) {
338 const char *home
= getenv ("HOME");
340 errx(EXIT_FAILURE
, _("failed to create a backup file, $HOME undefined"));
341 xasprintf(&tpl
, "%s/sfdisk-%s%s", home
, name
, suffix
);
343 xasprintf(&tpl
, "%s-%s%s", filename
, name
, suffix
);
350 static void backup_partition_table(struct sfdisk
*sf
, const char *devname
)
360 if (!fdisk_has_label(sf
->cxt
))
363 tpl
= mk_backup_filename_tpl(sf
->backup_file
, devname
, "-");
365 color_scheme_enable("header", UL_COLOR_BOLD
);
366 fdisk_info(sf
->cxt
, _("Backup files:"));
369 while (fdisk_locate_disklabel(sf
->cxt
, i
++, &name
, &offset
, &size
) == 0 && size
)
370 backup_sectors(sf
, tpl
, name
, devname
, offset
, size
);
377 static int assign_device(struct sfdisk
*sf
, const char *devname
, int rdonly
)
379 struct fdisk_context
*cxt
= sf
->cxt
;
381 if (fdisk_assign_device(cxt
, devname
, rdonly
) != 0)
382 err(EXIT_FAILURE
, _("cannot open %s"), devname
);
384 if (!fdisk_is_readonly(cxt
)) {
385 if (blkdev_lock(fdisk_get_devfd(cxt
), devname
, sf
->lockmode
) != 0) {
386 fdisk_deassign_device(cxt
, 1);
390 backup_partition_table(sf
, devname
);
396 static int move_partition_data(struct sfdisk
*sf
, size_t partno
, struct fdisk_partition
*orig_pa
)
398 struct fdisk_partition
*pa
= get_partition(sf
->cxt
, partno
);
399 char *devname
= NULL
, *typescript
= NULL
, *buf
= NULL
;
401 int ok
= 0, fd
, backward
= 0;
402 fdisk_sector_t nsectors
, from
, to
, step
, i
, prev
;
403 size_t io
, ss
, step_bytes
, cc
, ioerr
= 0;
404 uintmax_t src
, dst
, nbytes
;
405 int progress
= 0, rc
= 0;
406 struct timeval prev_time
;
407 uint64_t bytes_per_sec
= 0;
409 assert(sf
->movedata
);
412 warnx(_("failed to read new partition from device; ignoring --move-data"));
413 else if (!fdisk_partition_has_size(pa
))
414 warnx(_("failed to get size of the new partition; ignoring --move-data"));
415 else if (!fdisk_partition_has_start(pa
))
416 warnx(_("failed to get start of the new partition; ignoring --move-data"));
417 else if (!fdisk_partition_has_size(orig_pa
))
418 warnx(_("failed to get size of the old partition; ignoring --move-data"));
419 else if (!fdisk_partition_has_start(orig_pa
))
420 warnx(_("failed to get start of the old partition; ignoring --move-data"));
421 else if (fdisk_partition_get_start(pa
) == fdisk_partition_get_start(orig_pa
))
422 warnx(_("start of the partition has not been moved; ignoring --move-data"));
423 else if (fdisk_partition_get_size(orig_pa
) > fdisk_partition_get_size(pa
))
424 warnx(_("new partition is smaller than original; ignoring --move-data"));
430 DBG(MISC
, ul_debug("moving data"));
432 fd
= fdisk_get_devfd(sf
->cxt
);
434 /* set move direction and overlay */
435 nsectors
= fdisk_partition_get_size(orig_pa
);
436 from
= fdisk_partition_get_start(orig_pa
);
437 to
= fdisk_partition_get_start(pa
);
439 if ((to
>= from
&& from
+ nsectors
>= to
) ||
440 (from
>= to
&& to
+ nsectors
>= from
)) {
441 /* source and target overlay, check if we need to copy
442 * backwardly from end of the source */
443 DBG(MISC
, ul_debug("overlay between source and target"));
444 backward
= from
< to
;
445 DBG(MISC
, ul_debug(" copy order: %s", backward
? "backward" : "forward"));
448 /* set optimal step size -- nearest to 1MiB aligned to optimal I/O */
449 io
= fdisk_get_optimal_iosize(sf
->cxt
);
450 ss
= fdisk_get_sector_size(sf
->cxt
);
453 if (io
< 1024 * 1024)
454 step_bytes
= ((1024 * 1024) + io
/2) / io
* io
;
458 step
= step_bytes
/ ss
;
459 nbytes
= nsectors
* ss
;
461 DBG(MISC
, ul_debug(" step: %ju (%zu bytes)", (uintmax_t)step
, step_bytes
));
463 #if defined(POSIX_FADV_SEQUENTIAL) && defined(HAVE_POSIX_FADVISE)
465 ignore_result( posix_fadvise(fd
, from
* ss
,
466 nsectors
* ss
, POSIX_FADV_SEQUENTIAL
) );
468 devname
= fdisk_partname(fdisk_get_devname(sf
->cxt
), partno
+1);
469 if (sf
->move_typescript
)
470 typescript
= mk_backup_filename_tpl(sf
->move_typescript
, devname
, ".move");
473 fdisk_info(sf
->cxt
, "%s", "");
474 color_scheme_enable("header", UL_COLOR_BOLD
);
475 fdisk_info(sf
->cxt
, sf
->noact
? _("Data move: (--no-act)") : _("Data move:"));
478 fdisk_info(sf
->cxt
, _(" typescript file: %s"), typescript
);
479 printf(_(" start sector: (from/to) %ju / %ju\n"), (uintmax_t) from
, (uintmax_t) to
);
480 printf(_(" sectors: %ju\n"), (uintmax_t) nsectors
);
481 printf(_(" step size: %zu bytes\n"), step_bytes
);
485 if (isatty(fileno(stdout
)))
489 if (sf
->interactive
) {
491 fdisk_ask_yesno(sf
->cxt
, _("Do you want to move partition data?"), &yes
);
493 fdisk_info(sf
->cxt
, _("Leaving."));
500 f
= fopen(typescript
, "w");
503 fdisk_warn(sf
->cxt
, _("cannot open %s"), typescript
);
507 /* don't translate */
508 fprintf(f
, "# sfdisk: " PACKAGE_STRING
"\n");
509 fprintf(f
, "# Disk: %s\n", devname
);
510 fprintf(f
, "# Partition: %zu\n", partno
+ 1);
511 fprintf(f
, "# Operation: move data\n");
512 fprintf(f
, "# Sector size: %zu\n", ss
);
513 fprintf(f
, "# Original start offset (sectors/bytes): %ju/%ju\n",
514 (uintmax_t)from
, (uintmax_t)from
* ss
);
515 fprintf(f
, "# New start offset (sectors/bytes): %ju/%ju\n",
516 (uintmax_t)to
, (uintmax_t)to
* ss
);
517 fprintf(f
, "# Area size (sectors/bytes): %ju/%ju\n",
518 (uintmax_t)nsectors
, (uintmax_t)nsectors
* ss
);
519 fprintf(f
, "# Step size (sectors/bytes): %" PRIu64
"/%zu\n", step
, step_bytes
);
520 fprintf(f
, "# Steps: %ju\n", ((uintmax_t) nsectors
/ step
) + 1);
522 fprintf(f
, "# <step>: <from> <to> (step offsets in bytes)\n");
525 src
= (backward
? from
+ nsectors
: from
) * ss
;
526 dst
= (backward
? to
+ nsectors
: to
) * ss
;
527 buf
= xmalloc(step_bytes
);
529 DBG(MISC
, ul_debug(" initial: src=%ju dst=%ju", src
, dst
));
531 gettimeofday(&prev_time
, NULL
);
534 for (cc
= 1, i
= 0; i
< nsectors
&& nbytes
> 0; i
+= step
, cc
++) {
536 if (nbytes
< step_bytes
) {
537 DBG(MISC
, ul_debug("aligning step #%05zu from %zu to %ju",
538 cc
, step_bytes
, nbytes
));
541 nbytes
-= step_bytes
;
544 src
-= step_bytes
, dst
-= step_bytes
;
546 DBG(MISC
, ul_debug("#%05zu: src=%ju dst=%ju", cc
, src
, dst
));
550 if (lseek(fd
, src
, SEEK_SET
) == (off_t
) -1 ||
551 read_all(fd
, buf
, step_bytes
) != (ssize_t
) step_bytes
) {
553 fprintf(f
, "%05zu: read error %12ju %12ju\n", cc
, src
, dst
);
555 _("cannot read at offset: %ju; continue"), src
);
561 if (lseek(fd
, dst
, SEEK_SET
) == (off_t
) -1 ||
562 write_all(fd
, buf
, step_bytes
) != 0) {
564 fprintf(f
, "%05zu: write error %12ju %12ju\n", cc
, src
, dst
);
566 _("cannot write at offset: %ju; continue"), dst
);
570 if (sf
->movefsync
&& fsync(fd
) != 0)
572 _("cannot fsync at offset: %ju; continue"), dst
);
577 fprintf(f
, "%05zu: %12ju %12ju\n", cc
, src
, dst
);
579 if (progress
&& i
% 10 == 0) {
580 unsigned int elapsed
= 0; /* usec */
581 struct timeval cur_time
;
583 gettimeofday(&cur_time
, NULL
);
584 if (cur_time
.tv_sec
- prev_time
.tv_sec
> 1) {
585 elapsed
= ((cur_time
.tv_sec
- prev_time
.tv_sec
) * 1000000) +
586 (cur_time
.tv_usec
- prev_time
.tv_usec
);
588 bytes_per_sec
= ((i
- prev
) * ss
) / elapsed
; /* per usec */
589 bytes_per_sec
*= 1000000; /* per sec */
591 prev_time
= cur_time
;
596 fprintf(stdout
, _("Moved %ju from %ju sectors (%.3f%%, %.1f MiB/s)."),
598 100.0 / ((double) nsectors
/(i
+1)),
599 (double) (bytes_per_sec
/ (1024 * 1024)));
601 fprintf(stdout
, _("Moved %ju from %ju sectors (%.3f%%)."),
603 100.0 / ((double) nsectors
/(i
+1)));
610 src
+= step_bytes
, dst
+= step_bytes
;
613 if (progress
&& nsectors
) {
614 int x
= get_terminal_width(80);
621 /* see for() above; @i has to be greater than @nsectors
622 * on success due to i += step */
625 fprintf(stdout
, _("Moved %ju from %ju sectors (%.0f%%)."),
627 100.0 / ((double) nsectors
/(i
+1)));
638 fdisk_info(sf
->cxt
, _("Your data has not been moved (--no-act)."));
640 fdisk_info(sf
->cxt
, _("%zu I/O errors detected!"), ioerr
);
643 warn(_("%s: failed to move data"), devname
);
650 static int write_changes(struct sfdisk
*sf
)
655 fdisk_info(sf
->cxt
, _("The partition table is unchanged (--no-act)."));
657 rc
= fdisk_write_disklabel(sf
->cxt
);
659 if (rc
== 0 && sf
->movedata
&& sf
->orig_pa
)
660 rc
= move_partition_data(sf
, sf
->partno
, sf
->orig_pa
);
662 if (!sf
->noact
&& !rc
) {
663 fdisk_info(sf
->cxt
, _("\nThe partition table has been altered."));
665 /* Let's wait a little bit. It's possible that our
666 * system is still busy with a previous re-read
667 * ioctl (on sfdisk start) or with another task
668 * related to the write to the device.
671 fdisk_reread_partition_table(sf
->cxt
);
676 rc
= fdisk_deassign_device(sf
->cxt
,
677 sf
->noact
|| sf
->notell
); /* no-sync */
682 * sfdisk --list [<device ..]
684 static int command_list_partitions(struct sfdisk
*sf
, int argc
, char **argv
)
687 fdisk_enable_listonly(sf
->cxt
, 1);
692 for (i
= 0; i
< argc
; i
++)
693 if (print_device_pt(sf
->cxt
, argv
[i
], 1, sf
->verify
, i
) != 0)
696 print_all_devices_pt(sf
->cxt
, sf
->verify
);
702 * sfdisk --list-free [<device ..]
704 static int command_list_freespace(struct sfdisk
*sf
, int argc
, char **argv
)
707 fdisk_enable_listonly(sf
->cxt
, 1);
712 for (i
= 0; i
< argc
; i
++)
713 if (print_device_freespace(sf
->cxt
, argv
[i
], 1, i
) != 0)
716 print_all_devices_freespace(sf
->cxt
);
722 * sfdisk --list-types
724 static int command_list_types(struct sfdisk
*sf
)
726 const struct fdisk_parttype
*t
;
727 struct fdisk_label
*lb
;
735 name
= sf
->label
? sf
->label
: "dos";
736 lb
= fdisk_get_label(sf
->cxt
, name
);
738 errx(EXIT_FAILURE
, _("unsupported label '%s'"), name
);
740 codes
= fdisk_label_has_code_parttypes(lb
);
741 fputs(_("Id Name\n\n"), stdout
);
743 while ((t
= fdisk_label_get_parttype(lb
, i
++))) {
745 printf("%2x %s\n", fdisk_parttype_get_code(t
),
746 fdisk_parttype_get_name(t
));
748 printf("%s %s\n", fdisk_parttype_get_string(t
),
749 fdisk_parttype_get_name(t
));
755 static int verify_device(struct sfdisk
*sf
, const char *devname
)
759 fdisk_enable_listonly(sf
->cxt
, 1);
761 assign_device(sf
, devname
, 1);
763 color_scheme_enable("header", UL_COLOR_BOLD
);
764 fdisk_info(sf
->cxt
, "%s:", devname
);
767 if (!fdisk_has_label(sf
->cxt
))
768 fdisk_info(sf
->cxt
, _("unrecognized partition table type"));
770 rc
= fdisk_verify_disklabel(sf
->cxt
);
772 fdisk_deassign_device(sf
->cxt
, 1);
777 * sfdisk --verify [<device ..]
779 static int command_verify(struct sfdisk
*sf
, int argc
, char **argv
)
781 int nfails
= 0, ct
= 0;
785 for (i
= 0; i
< argc
; i
++) {
787 fdisk_info(sf
->cxt
, " ");
788 if (verify_device(sf
, argv
[i
]) < 0)
795 while ((dev
= next_proc_partition(&f
))) {
797 fdisk_info(sf
->cxt
, " ");
798 if (verify_device(sf
, dev
) < 0)
808 static int get_size(const char *dev
, int silent
, uintmax_t *sz
)
812 fd
= open(dev
, O_RDONLY
);
815 warn(_("cannot open %s"), dev
);
819 if (blkdev_get_sectors(fd
, (unsigned long long *) sz
) == -1) {
821 warn(_("Cannot get size of %s"), dev
);
830 * sfdisk --show-size [<device ..]
832 * (silly, but just for backward compatibility)
834 static int command_show_size(struct sfdisk
*sf
__attribute__((__unused__
)),
835 int argc
, char **argv
)
841 for (i
= 0; i
< argc
; i
++) {
842 if (get_size(argv
[i
], 0, &sz
) == 0)
843 printf("%ju\n", sz
/ 2);
850 while ((dev
= next_proc_partition(&f
))) {
851 if (get_size(dev
, 1, &sz
) == 0) {
852 printf("%s: %9ju\n", dev
, sz
/ 2);
858 printf(_("total: %ju blocks\n"), total
);
864 static int print_geom(struct sfdisk
*sf
, const char *devname
)
866 fdisk_enable_listonly(sf
->cxt
, 1);
868 assign_device(sf
, devname
, 1);
870 fdisk_info(sf
->cxt
, "%s: %ju cylinders, %ju heads, %ju sectors/track",
872 (uintmax_t) fdisk_get_geom_cylinders(sf
->cxt
),
873 (uintmax_t) fdisk_get_geom_heads(sf
->cxt
),
874 (uintmax_t) fdisk_get_geom_sectors(sf
->cxt
));
876 fdisk_deassign_device(sf
->cxt
, 1);
881 * sfdisk --show-geometry [<device ..]
883 static int command_show_geometry(struct sfdisk
*sf
, int argc
, char **argv
)
889 for (i
= 0; i
< argc
; i
++) {
890 if (print_geom(sf
, argv
[i
]) < 0)
897 while ((dev
= next_proc_partition(&f
))) {
898 if (print_geom(sf
, dev
) < 0)
908 * sfdisk --activate <device> [<partno> ...]
910 static int command_activate(struct sfdisk
*sf
, int argc
, char **argv
)
912 int rc
, nparts
, i
, listonly
;
913 struct fdisk_partition
*pa
= NULL
;
914 const char *devname
= NULL
;
917 errx(EXIT_FAILURE
, _("no disk device specified"));
920 /* --activate <device> */
921 listonly
= argc
== 1;
923 assign_device(sf
, devname
, listonly
);
925 if (fdisk_is_label(sf
->cxt
, GPT
)) {
926 if (fdisk_gpt_is_hybrid(sf
->cxt
))
927 errx(EXIT_FAILURE
, _("toggle boot flags is unsupported for Hybrid GPT/MBR"));
929 /* Switch from GPT to PMBR */
930 sf
->cxt
= fdisk_new_nested_context(sf
->cxt
, "dos");
932 err(EXIT_FAILURE
, _("cannot switch to PMBR"));
933 fdisk_info(sf
->cxt
, _("Activation is unsupported for GPT -- entering nested PMBR."));
935 } else if (!fdisk_is_label(sf
->cxt
, DOS
))
936 errx(EXIT_FAILURE
, _("toggle boot flags is supported for MBR or PMBR only"));
938 nparts
= fdisk_get_npartitions(sf
->cxt
);
939 for (i
= 0; i
< nparts
; i
++) {
942 /* note that fdisk_get_partition() reuses the @pa pointer, you
943 * don't have to (re)allocate it */
944 if (fdisk_get_partition(sf
->cxt
, i
, &pa
) != 0)
947 /* sfdisk --activate list bootable partitions */
949 if (!fdisk_partition_is_bootable(pa
))
951 if (fdisk_partition_to_string(pa
, sf
->cxt
,
952 FDISK_FIELD_DEVICE
, &data
) == 0) {
953 printf("%s\n", data
);
957 /* deactivate all active partitions */
958 } else if (fdisk_partition_is_bootable(pa
))
959 fdisk_toggle_partition_flag(sf
->cxt
, i
, DOS_FLAG_ACTIVE
);
962 /* sfdisk --activate <partno> [..] */
963 for (i
= 1; i
< argc
; i
++) {
966 if (i
== 1 && strcmp(argv
[1], "-") == 0)
968 n
= strtou32_or_err(argv
[i
], _("failed to parse partition number"));
970 rc
= fdisk_toggle_partition_flag(sf
->cxt
, n
- 1, DOS_FLAG_ACTIVE
);
973 _("%s: partition %d: failed to toggle bootable flag"),
977 fdisk_unref_partition(pa
);
980 rc
= fdisk_deassign_device(sf
->cxt
, 1);
982 rc
= write_changes(sf
);
987 * sfdisk --delete <device> [<partno> ...]
989 static int command_delete(struct sfdisk
*sf
, int argc
, char **argv
)
992 const char *devname
= NULL
;
995 errx(EXIT_FAILURE
, _("no disk device specified"));
998 assign_device(sf
, devname
, 0);
1002 size_t nparts
= fdisk_get_npartitions(sf
->cxt
);
1003 for (i
= 0; i
< nparts
; i
++) {
1004 if (fdisk_is_partition_used(sf
->cxt
, i
) &&
1005 fdisk_delete_partition(sf
->cxt
, i
) != 0)
1006 errx(EXIT_FAILURE
, _("%s: partition %zu: failed to delete"), devname
, i
+ 1);
1008 /* delete specified */
1010 for (i
= 1; i
< (size_t) argc
; i
++) {
1011 size_t n
= strtou32_or_err(argv
[i
], _("failed to parse partition number"));
1014 errx(EXIT_FAILURE
, _("partition number must be a positive number"));
1015 if (fdisk_delete_partition(sf
->cxt
, n
- 1) != 0)
1016 errx(EXIT_FAILURE
, _("%s: partition %zu: failed to delete"), devname
, n
);
1020 return write_changes(sf
);
1024 * sfdisk --reorder <device>
1026 static int command_reorder(struct sfdisk
*sf
, int argc
, char **argv
)
1028 const char *devname
= NULL
;
1034 errx(EXIT_FAILURE
, _("no disk device specified"));
1036 assign_device(sf
, devname
, 0); /* read-write */
1038 if (fdisk_reorder_partitions(sf
->cxt
) == 1) /* unchanged */
1039 rc
= fdisk_deassign_device(sf
->cxt
, 1);
1041 rc
= write_changes(sf
);
1048 * sfdisk --dump <device>
1050 static int command_dump(struct sfdisk
*sf
, int argc
, char **argv
)
1052 const char *devname
= NULL
;
1053 struct fdisk_script
*dp
;
1059 errx(EXIT_FAILURE
, _("no disk device specified"));
1061 assign_device(sf
, devname
, 1); /* read-only */
1063 if (!fdisk_has_label(sf
->cxt
))
1064 errx(EXIT_FAILURE
, _("%s: does not contain a recognized partition table"), devname
);
1066 dp
= fdisk_new_script(sf
->cxt
);
1068 err(EXIT_FAILURE
, _("failed to allocate dump struct"));
1070 rc
= fdisk_script_read_context(dp
, NULL
);
1072 errx(EXIT_FAILURE
, _("%s: failed to dump partition table"), devname
);
1075 fdisk_script_enable_json(dp
, 1);
1076 fdisk_script_write_file(dp
, stdout
);
1078 fdisk_unref_script(dp
);
1079 fdisk_deassign_device(sf
->cxt
, 1); /* no-sync() */
1084 * sfdisk --backup-pt-sectors <device>
1086 static int command_backup_sectors(struct sfdisk
*sf
, int argc
, char **argv
)
1088 const char *devname
= NULL
;
1093 errx(EXIT_FAILURE
, _("no disk device specified"));
1095 assign_device(sf
, devname
, 1); /* read-only */
1097 if (!fdisk_has_label(sf
->cxt
))
1098 errx(EXIT_FAILURE
, _("%s: does not contain a recognized partition table"), devname
);
1100 backup_partition_table(sf
, devname
);
1102 fdisk_deassign_device(sf
->cxt
, 1); /* no-sync() */
1106 static void assign_device_partition(struct sfdisk
*sf
,
1107 const char *devname
,
1113 struct fdisk_label
*lb
= NULL
;
1118 /* read-only when a new <type> undefined */
1119 rc
= fdisk_assign_device(sf
->cxt
, devname
, rdonly
);
1121 err(EXIT_FAILURE
, _("cannot open %s"), devname
);
1123 if (!fdisk_is_readonly(sf
->cxt
)
1124 && blkdev_lock(fdisk_get_devfd(sf
->cxt
), devname
, sf
->lockmode
) != 0) {
1125 fdisk_deassign_device(sf
->cxt
, 1);
1128 lb
= fdisk_get_label(sf
->cxt
, NULL
);
1130 errx(EXIT_FAILURE
, _("%s: no partition table found"), devname
);
1132 n
= fdisk_get_npartitions(sf
->cxt
);
1134 errx(EXIT_FAILURE
, _("%s: partition %zu: partition table contains "
1135 "only %zu partitions"), devname
, partno
, n
);
1136 if (!fdisk_is_partition_used(sf
->cxt
, partno
- 1))
1137 errx(EXIT_FAILURE
, _("%s: partition %zu: partition is unused"),
1142 * sfdisk --part-type <device> <partno> [<type>]
1144 static int command_parttype(struct sfdisk
*sf
, int argc
, char **argv
)
1147 struct fdisk_parttype
*type
= NULL
;
1148 struct fdisk_label
*lb
;
1149 const char *devname
= NULL
, *typestr
= NULL
;
1152 errx(EXIT_FAILURE
, _("no disk device specified"));
1156 errx(EXIT_FAILURE
, _("no partition number specified"));
1157 partno
= strtou32_or_err(argv
[1], _("failed to parse partition number"));
1162 errx(EXIT_FAILURE
, _("unexpected arguments"));
1164 /* read-only when a new <type> undefined */
1165 assign_device_partition(sf
, devname
, partno
, !typestr
);
1167 lb
= fdisk_get_label(sf
->cxt
, NULL
);
1169 /* print partition type */
1171 const struct fdisk_parttype
*t
= NULL
;
1172 struct fdisk_partition
*pa
= NULL
;
1174 if (fdisk_get_partition(sf
->cxt
, partno
- 1, &pa
) == 0)
1175 t
= fdisk_partition_get_type(pa
);
1177 errx(EXIT_FAILURE
, _("%s: partition %zu: failed to get partition type"),
1180 if (fdisk_label_has_code_parttypes(lb
))
1181 printf("%2x\n", fdisk_parttype_get_code(t
));
1183 printf("%s\n", fdisk_parttype_get_string(t
));
1185 fdisk_unref_partition(pa
);
1186 fdisk_deassign_device(sf
->cxt
, 1);
1191 backup_partition_table(sf
, devname
);
1193 /* parse <type> and apply to PT */
1194 type
= fdisk_label_advparse_parttype(lb
, typestr
,
1195 FDISK_PARTTYPE_PARSE_DATA
1196 | FDISK_PARTTYPE_PARSE_ALIAS
1197 | FDISK_PARTTYPE_PARSE_NAME
1198 | FDISK_PARTTYPE_PARSE_SHORTCUT
);
1200 errx(EXIT_FAILURE
, _("failed to parse %s partition type '%s'"),
1201 fdisk_label_get_name(lb
), typestr
);
1203 else if (fdisk_set_partition_type(sf
->cxt
, partno
- 1, type
) != 0)
1204 errx(EXIT_FAILURE
, _("%s: partition %zu: failed to set partition type"),
1206 fdisk_unref_parttype(type
);
1207 return write_changes(sf
);
1211 * sfdisk --part-uuid <device> <partno> [<uuid>]
1213 static int command_partuuid(struct sfdisk
*sf
, int argc
, char **argv
)
1216 struct fdisk_partition
*pa
= NULL
;
1217 const char *devname
= NULL
, *uuid
= NULL
;
1220 errx(EXIT_FAILURE
, _("no disk device specified"));
1224 errx(EXIT_FAILURE
, _("no partition number specified"));
1225 partno
= strtou32_or_err(argv
[1], _("failed to parse partition number"));
1230 errx(EXIT_FAILURE
, _("unexpected arguments"));
1232 /* read-only if uuid not given */
1233 assign_device_partition(sf
, devname
, partno
, !uuid
);
1235 /* print partition uuid */
1237 const char *str
= NULL
;
1239 if (fdisk_get_partition(sf
->cxt
, partno
- 1, &pa
) == 0)
1240 str
= fdisk_partition_get_uuid(pa
);
1242 errx(EXIT_FAILURE
, _("%s: partition %zu: failed to get partition UUID"),
1244 printf("%s\n", str
);
1245 fdisk_unref_partition(pa
);
1246 fdisk_deassign_device(sf
->cxt
, 1);
1251 backup_partition_table(sf
, devname
);
1253 pa
= fdisk_new_partition();
1255 err(EXIT_FAILURE
, _("failed to allocate partition object"));
1257 if (fdisk_partition_set_uuid(pa
, uuid
) != 0 ||
1258 fdisk_set_partition(sf
->cxt
, partno
- 1, pa
) != 0)
1259 errx(EXIT_FAILURE
, _("%s: partition %zu: failed to set partition UUID"),
1261 fdisk_unref_partition(pa
);
1262 return write_changes(sf
);
1266 * sfdisk --part-label <device> <partno> [<label>]
1268 static int command_partlabel(struct sfdisk
*sf
, int argc
, char **argv
)
1271 struct fdisk_partition
*pa
= NULL
;
1272 const char *devname
= NULL
, *name
= NULL
;
1275 errx(EXIT_FAILURE
, _("no disk device specified"));
1279 errx(EXIT_FAILURE
, _("no partition number specified"));
1280 partno
= strtou32_or_err(argv
[1], _("failed to parse partition number"));
1285 errx(EXIT_FAILURE
, _("unexpected arguments"));
1287 /* read-only if name not given */
1288 assign_device_partition(sf
, devname
, partno
, !name
);
1290 /* print partition name */
1292 const char *str
= NULL
;
1294 if (fdisk_get_partition(sf
->cxt
, partno
- 1, &pa
) == 0)
1295 str
= fdisk_partition_get_name(pa
);
1297 errx(EXIT_FAILURE
, _("%s: partition %zu: failed to get partition name"),
1299 printf("%s\n", str
);
1300 fdisk_unref_partition(pa
);
1301 fdisk_deassign_device(sf
->cxt
, 1);
1306 backup_partition_table(sf
, devname
);
1308 pa
= fdisk_new_partition();
1310 err(EXIT_FAILURE
, _("failed to allocate partition object"));
1312 if (fdisk_partition_set_name(pa
, name
) != 0 ||
1313 fdisk_set_partition(sf
->cxt
, partno
- 1, pa
) != 0)
1314 errx(EXIT_FAILURE
, _("%s: partition %zu: failed to set partition name"),
1317 fdisk_unref_partition(pa
);
1318 return write_changes(sf
);
1322 * sfdisk --part-attrs <device> <partno> [<attrs>]
1324 static int command_partattrs(struct sfdisk
*sf
, int argc
, char **argv
)
1327 struct fdisk_partition
*pa
= NULL
;
1328 const char *devname
= NULL
, *attrs
= NULL
;
1331 errx(EXIT_FAILURE
, _("no disk device specified"));
1335 errx(EXIT_FAILURE
, _("no partition number specified"));
1336 partno
= strtou32_or_err(argv
[1], _("failed to parse partition number"));
1341 errx(EXIT_FAILURE
, _("unexpected arguments"));
1343 /* read-only if name not given */
1344 assign_device_partition(sf
, devname
, partno
, !attrs
);
1346 /* print partition name */
1348 const char *str
= NULL
;
1350 if (fdisk_get_partition(sf
->cxt
, partno
- 1, &pa
) == 0)
1351 str
= fdisk_partition_get_attrs(pa
);
1353 printf("%s\n", str
);
1354 fdisk_unref_partition(pa
);
1355 fdisk_deassign_device(sf
->cxt
, 1);
1360 backup_partition_table(sf
, devname
);
1362 pa
= fdisk_new_partition();
1364 err(EXIT_FAILURE
, _("failed to allocate partition object"));
1366 if (fdisk_partition_set_attrs(pa
, attrs
) != 0 ||
1367 fdisk_set_partition(sf
->cxt
, partno
- 1, pa
) != 0)
1368 errx(EXIT_FAILURE
, _("%s: partition %zu: failed to set partition attributes"),
1371 fdisk_unref_partition(pa
);
1372 return write_changes(sf
);
1377 * sfdisk --discard-free <device>
1379 static int command_discard_free(struct sfdisk
*sf
, int argc
, char **argv
)
1381 struct fdisk_table
*tb
= NULL
;
1382 struct fdisk_iter
*itr
= NULL
;
1383 struct fdisk_partition
*pa
= NULL
;
1384 const char *devname
= NULL
;
1389 errx(EXIT_FAILURE
, _("no disk device specified"));
1392 errx(EXIT_FAILURE
, _("unexpected arguments"));
1394 itr
= fdisk_new_iter(FDISK_ITER_FORWARD
);
1396 err(EXIT_FAILURE
, _("failed to allocate iterator"));
1398 assign_device(sf
, devname
, 0);
1400 ss
= fdisk_get_sector_size(sf
->cxt
);
1402 rc
= fdisk_get_freespaces(sf
->cxt
, &tb
);
1404 fdisk_warn(sf
->cxt
, _("failed to gather unpartitioned space"));
1408 while (fdisk_table_next_partition(tb
, itr
, &pa
) == 0) {
1411 if (!fdisk_partition_has_size(pa
) ||
1412 !fdisk_partition_has_start(pa
))
1415 range
[0] = (uint64_t) fdisk_partition_get_start(pa
);
1416 range
[1] = (uint64_t) fdisk_partition_get_size(pa
);
1418 fdisk_info(sf
->cxt
, _("Discarding region %"PRIu64
1420 range
[0], range
[0] + range
[1] - 1);
1426 if (ioctl(fdisk_get_devfd(sf
->cxt
), BLKDISCARD
, &range
)) {
1428 fdisk_warn(sf
->cxt
, _("BLKDISCARD ioctl failed"));
1434 fdisk_free_iter(itr
);
1435 fdisk_unref_table(tb
);
1438 #else /* BLKDISCARD */
1439 static int command_discard_free(struct sfdisk
*sf
, int argc
, char **argv
)
1441 fdisk_warnx(sf
->cxt
, _("Discard unsupported on your system."));
1443 #endif /* BLKDISCARD */
1446 * sfdisk --disk-id <device> [<str>]
1448 static int command_diskid(struct sfdisk
*sf
, int argc
, char **argv
)
1450 const char *devname
= NULL
;
1454 errx(EXIT_FAILURE
, _("no disk device specified"));
1460 errx(EXIT_FAILURE
, _("unexpected arguments"));
1462 assign_device(sf
, devname
, !str
);
1466 fdisk_get_disklabel_id(sf
->cxt
, &str
);
1468 printf("%s\n", str
);
1470 fdisk_deassign_device(sf
->cxt
, 1);
1474 if (fdisk_set_disklabel_id_from_string(sf
->cxt
, str
) != 0)
1475 errx(EXIT_FAILURE
, _("%s: failed to set disklabel ID"), devname
);
1477 return write_changes(sf
);
1481 * sfdisk --relocate <mode> <device>
1483 static int command_relocate(struct sfdisk
*sf
, int argc
, char **argv
)
1485 const char *devname
= NULL
;
1486 const char *oper
= NULL
;
1487 struct fdisk_label
*lb
;
1490 errx(EXIT_FAILURE
, _("no relocate operation specified"));
1492 errx(EXIT_FAILURE
, _("no disk device specified"));
1494 errx(EXIT_FAILURE
, _("unexpected arguments"));
1498 lb
= fdisk_get_label(sf
->cxt
, "gpt");
1500 if (strcmp(oper
, "gpt-bak-mini") == 0)
1501 fdisk_gpt_enable_minimize(lb
, 1);
1503 else if (strcmp(oper
, "gpt-bak-std") != 0)
1504 errx(EXIT_FAILURE
, _("unsupported relocation operation"));
1506 assign_device(sf
, devname
, 0);
1508 fdisk_label_set_changed(lb
, 1);
1510 return write_changes(sf
);
1513 static void sfdisk_print_partition(struct sfdisk
*sf
, size_t n
)
1515 struct fdisk_partition
*pa
= NULL
;
1522 if (fdisk_get_partition(sf
->cxt
, n
, &pa
) != 0)
1525 fdisk_partition_to_string(pa
, sf
->cxt
, FDISK_FIELD_DEVICE
, &data
);
1526 printf("%12s : ", data
);
1528 fdisk_partition_to_string(pa
, sf
->cxt
, FDISK_FIELD_START
, &data
);
1529 printf("%12s ", data
);
1531 fdisk_partition_to_string(pa
, sf
->cxt
, FDISK_FIELD_END
, &data
);
1532 printf("%12s ", data
);
1534 fdisk_partition_to_string(pa
, sf
->cxt
, FDISK_FIELD_SIZE
, &data
);
1535 printf("(%s) ", data
);
1537 fdisk_partition_to_string(pa
, sf
->cxt
, FDISK_FIELD_TYPE
, &data
);
1538 printf("%s\n", data
);
1540 fdisk_unref_partition(pa
);
1543 static void command_fdisk_help(void)
1545 fputs(_("\nHelp:\n"), stdout
);
1547 fputc('\n', stdout
);
1548 color_scheme_enable("help-title", UL_COLOR_BOLD
);
1549 fputs(_(" Commands:\n"), stdout
);
1551 fputs(_(" write write table to disk and exit\n"), stdout
);
1552 fputs(_(" quit show new situation and wait for user's feedback before write\n"), stdout
);
1553 fputs(_(" abort exit sfdisk shell\n"), stdout
);
1554 fputs(_(" print display the partition table\n"), stdout
);
1555 fputs(_(" help show this help text\n"), stdout
);
1556 fputc('\n', stdout
);
1557 fputs(_(" Ctrl-D the same as 'quit'\n"), stdout
);
1559 fputc('\n', stdout
);
1560 color_scheme_enable("help-title", UL_COLOR_BOLD
);
1561 fputs(_(" Input format:\n"), stdout
);
1563 fputs(_(" <start>, <size>, <type>, <bootable>\n"), stdout
);
1565 fputc('\n', stdout
);
1566 fputs(_(" <start> Beginning of the partition in sectors, or bytes if\n"
1567 " specified in the format <number>{K,M,G,T,P,E,Z,Y}.\n"
1568 " The default is the first free space.\n"), stdout
);
1570 fputc('\n', stdout
);
1571 fputs(_(" <size> Size of the partition in sectors, or bytes if\n"
1572 " specified in the format <number>{K,M,G,T,P,E,Z,Y}.\n"
1573 " The default is all available space.\n"), stdout
);
1575 fputc('\n', stdout
);
1576 fputs(_(" <type> The partition type. Default is a Linux data partition.\n"), stdout
);
1577 fputs(_(" MBR: hex or L,S,Ex,X,U,R,V shortcuts.\n"), stdout
);
1578 fputs(_(" GPT: UUID or L,S,H,U,R,V shortcuts.\n"), stdout
);
1580 fputc('\n', stdout
);
1581 fputs(_(" <bootable> Use '*' to mark an MBR partition as bootable.\n"), stdout
);
1583 fputc('\n', stdout
);
1584 color_scheme_enable("help-title", UL_COLOR_BOLD
);
1585 fputs(_(" Example:\n"), stdout
);
1587 fputs(_(" , 4G Creates a 4GiB partition at default start offset.\n"), stdout
);
1588 fputc('\n', stdout
);
1592 SFDISK_DONE_NONE
= 0,
1599 /* returns: 0 on success, <0 on error, 1 successfully stop sfdisk */
1600 static int loop_control_commands(struct sfdisk
*sf
,
1601 struct fdisk_script
*dp
,
1604 const char *p
= skip_blank(buf
);
1605 int rc
= SFDISK_DONE_NONE
;
1607 if (strcmp(p
, "print") == 0)
1608 list_disklabel(sf
->cxt
);
1609 else if (strcmp(p
, "help") == 0)
1610 command_fdisk_help();
1611 else if (strcmp(p
, "quit") == 0)
1612 rc
= SFDISK_DONE_ASK
;
1613 else if (strcmp(p
, "write") == 0)
1614 rc
= SFDISK_DONE_WRITE
;
1615 else if (strcmp(p
, "abort") == 0)
1616 rc
= SFDISK_DONE_ABORT
;
1618 if (sf
->interactive
)
1619 fdisk_warnx(sf
->cxt
, _("unsupported command"));
1621 fdisk_warnx(sf
->cxt
, _("line %d: unsupported command"),
1622 fdisk_script_get_nlines(dp
));
1629 static int has_container_or_unused(struct sfdisk
*sf
)
1632 struct fdisk_partition
*pa
= NULL
;
1634 if (sf
->container
|| sf
->unused
)
1637 nparts
= fdisk_get_npartitions(sf
->cxt
);
1638 for (i
= 0; i
< nparts
; i
++) {
1640 if (!fdisk_is_partition_used(sf
->cxt
, i
)) {
1644 if (fdisk_get_partition(sf
->cxt
, i
, &pa
) != 0)
1646 if (fdisk_partition_is_container(pa
))
1650 fdisk_unref_partition(pa
);
1651 return sf
->container
|| sf
->unused
;
1654 static size_t last_pt_partno(struct sfdisk
*sf
)
1656 size_t i
, nparts
, partno
= 0;
1657 struct fdisk_partition
*pa
= NULL
;
1660 nparts
= fdisk_get_npartitions(sf
->cxt
);
1661 for (i
= 0; i
< nparts
; i
++) {
1664 if (fdisk_get_partition(sf
->cxt
, i
, &pa
) != 0 ||
1665 !fdisk_partition_is_used(pa
))
1667 x
= fdisk_partition_get_partno(pa
);
1672 fdisk_unref_partition(pa
);
1676 #ifdef HAVE_LIBREADLINE
1677 static char *sfdisk_fgets(struct fdisk_script
*dp
,
1678 char *buf
, size_t bufsz
, FILE *f
)
1680 struct sfdisk
*sf
= (struct sfdisk
*) fdisk_script_get_userdata(dp
);
1686 if (sf
->interactive
) {
1687 char *p
= readline(sf
->prompt
);
1693 if (len
> bufsz
- 2)
1696 memcpy(buf
, p
, len
);
1697 buf
[len
] = '\n'; /* append \n to be compatible with libc fgetc() */
1698 buf
[len
+ 1] = '\0';
1703 return fgets(buf
, bufsz
, f
);
1707 static int ignore_partition(struct fdisk_partition
*pa
)
1709 /* incomplete partition setting */
1710 if (!fdisk_partition_has_start(pa
) && !fdisk_partition_start_is_default(pa
))
1712 if (!fdisk_partition_has_size(pa
) && !fdisk_partition_end_is_default(pa
))
1715 /* probably dump from old sfdisk with start=0 size=0 */
1716 if (fdisk_partition_has_start(pa
) && fdisk_partition_get_start(pa
) == 0 &&
1717 fdisk_partition_has_size(pa
) && fdisk_partition_get_size(pa
) == 0)
1723 static void follow_wipe_mode(struct sfdisk
*sf
)
1725 int dowipe
= sf
->wipemode
== WIPEMODE_ALWAYS
? 1 : 0;
1727 if (sf
->interactive
&& sf
->wipemode
== WIPEMODE_AUTO
)
1728 dowipe
= 1; /* do it in interactive mode */
1730 if (fdisk_is_ptcollision(sf
->cxt
) && sf
->wipemode
!= WIPEMODE_NEVER
)
1731 dowipe
= 1; /* always wipe old PT */
1733 fdisk_enable_wipe(sf
->cxt
, dowipe
);
1738 if (!fdisk_is_ptcollision(sf
->cxt
)) {
1739 fdisk_warnx(sf
->cxt
, _(
1740 "The device contains '%s' signature and it may be removed by a write command. "
1741 "See sfdisk(8) man page and --wipe option for more details."),
1742 fdisk_get_collision(sf
->cxt
));
1743 fputc('\n', stdout
);
1746 fdisk_warnx(sf
->cxt
, _(
1747 "The device contains '%s' signature and it may remain on the device. "
1748 "It is recommended to wipe the device with wipefs(8) or "
1749 "sfdisk --wipe, in order to avoid possible collisions."),
1750 fdisk_get_collision(sf
->cxt
));
1751 fputc('\n', stderr
);
1755 static int wipe_partition(struct sfdisk
*sf
, size_t partno
)
1758 char *fstype
= NULL
;
1759 struct fdisk_partition
*tmp
= NULL
;
1761 DBG(MISC
, ul_debug("checking for signature"));
1763 rc
= fdisk_get_partition(sf
->cxt
, partno
, &tmp
);
1767 rc
= fdisk_partition_to_string(tmp
, sf
->cxt
, FDISK_FIELD_FSTYPE
, &fstype
);
1768 if (rc
|| fstype
== NULL
)
1771 fdisk_warnx(sf
->cxt
, _("Partition #%zu contains a %s signature."), partno
+ 1, fstype
);
1773 if (sf
->pwipemode
== WIPEMODE_AUTO
&& isatty(STDIN_FILENO
))
1774 fdisk_ask_yesno(sf
->cxt
, _("Do you want to remove the signature?"), &yes
);
1775 else if (sf
->pwipemode
== WIPEMODE_ALWAYS
)
1779 fdisk_info(sf
->cxt
, _("The signature will be removed by a write command."));
1780 rc
= fdisk_wipe_partition(sf
->cxt
, partno
, TRUE
);
1783 fdisk_unref_partition(tmp
);
1785 DBG(MISC
, ul_debug("partition wipe check end [rc=%d]", rc
));
1789 static void refresh_prompt_buffer(struct sfdisk
*sf
, const char *devname
,
1790 size_t next_partno
, int created
)
1793 char *partname
= fdisk_partname(devname
, next_partno
+ 1);
1795 err(EXIT_FAILURE
, _("failed to allocate partition name"));
1797 if (!sf
->prompt
|| !ul_startswith(sf
->prompt
, partname
)) {
1799 xasprintf(&sf
->prompt
,"%s: ", partname
);
1802 } else if (!sf
->prompt
|| !ul_startswith(sf
->prompt
, SFDISK_PROMPT
)) {
1804 sf
->prompt
= xstrdup(SFDISK_PROMPT
);
1809 * sfdisk <device> [[-N] <partno>]
1811 * Note that the option -N is there for backward compatibility only.
1813 static int command_fdisk(struct sfdisk
*sf
, int argc
, char **argv
)
1815 int rc
= 0, partno
= sf
->partno
, created
= 0, unused
= 0, ignored
= 0;
1816 struct fdisk_script
*dp
;
1817 struct fdisk_table
*tb
= NULL
;
1818 const char *devname
= NULL
, *label
;
1820 size_t next_partno
= (size_t) -1;
1824 if (partno
< 0 && argc
> 1)
1825 partno
= strtou32_or_err(argv
[1],
1826 _("failed to parse partition number"));
1828 errx(EXIT_FAILURE
, _("no disk device specified"));
1830 assign_device(sf
, devname
, 0);
1832 dp
= fdisk_new_script(sf
->cxt
);
1834 err(EXIT_FAILURE
, _("failed to allocate script handler"));
1835 fdisk_set_script(sf
->cxt
, dp
);
1836 #ifdef HAVE_LIBREADLINE
1837 fdisk_script_set_fgets(dp
, sfdisk_fgets
);
1839 fdisk_script_set_userdata(dp
, (void *) sf
);
1842 * Don't create a new disklabel when [-N] <partno> specified. In this
1843 * case reuse already specified disklabel. Let's check that the disk
1844 * really contains the partition.
1849 if (!fdisk_has_label(sf
->cxt
))
1850 errx(EXIT_FAILURE
, _("%s: cannot modify partition %d: "
1851 "no partition table was found"),
1852 devname
, partno
+ 1);
1853 n
= fdisk_get_npartitions(sf
->cxt
);
1854 if ((size_t) partno
> n
)
1855 errx(EXIT_FAILURE
, _("%s: cannot modify partition %d: "
1856 "partition table contains only %zu "
1858 devname
, partno
+ 1, n
);
1860 if (!fdisk_is_partition_used(sf
->cxt
, partno
)) {
1861 fdisk_warnx(sf
->cxt
, _("warning: %s: partition %d is not defined yet"),
1862 devname
, partno
+ 1);
1866 next_partno
= partno
;
1869 sf
->orig_pa
= get_partition(sf
->cxt
, partno
);
1874 next_partno
= last_pt_partno(sf
) + 1;
1877 if (!sf
->quiet
&& sf
->interactive
) {
1878 color_scheme_enable("welcome", UL_COLOR_GREEN
);
1879 fdisk_info(sf
->cxt
, _("\nWelcome to sfdisk (%s)."), PACKAGE_STRING
);
1881 fdisk_info(sf
->cxt
, _("Changes will remain in memory only, until you decide to write them.\n"
1882 "Be careful before using the write command.\n"));
1885 if (!sf
->noact
&& !sf
->noreread
) {
1887 fputs(_("Checking that no-one is using this disk right now ..."), stdout
);
1888 if (fdisk_device_is_used(sf
->cxt
)) {
1890 fputs(_(" FAILED\n\n"), stdout
);
1892 fdisk_warnx(sf
->cxt
, _(
1893 "This disk is currently in use - repartitioning is probably a bad idea.\n"
1894 "Umount all file systems, and swapoff all swap partitions on this disk.\n"
1895 "Use the --no-reread flag to suppress this check.\n"));
1898 errx(EXIT_FAILURE
, _("Use the --force flag to overrule all checks."));
1899 } else if (!sf
->quiet
)
1900 fputs(_(" OK\n\n"), stdout
);
1903 if (fdisk_get_collision(sf
->cxt
))
1904 follow_wipe_mode(sf
);
1907 list_disk_geometry(sf
->cxt
);
1908 if (fdisk_has_label(sf
->cxt
)) {
1909 fdisk_info(sf
->cxt
, _("\nOld situation:"));
1910 list_disklabel(sf
->cxt
);
1916 else if (fdisk_has_label(sf
->cxt
))
1917 label
= fdisk_label_get_name(fdisk_get_label(sf
->cxt
, NULL
));
1919 label
= "dos"; /* just for backward compatibility */
1921 if (fdisk_script_set_header(dp
, "label", label
) != 0)
1922 errx(EXIT_FAILURE
, _("failed to set script header"));
1924 if (!sf
->quiet
&& sf
->interactive
) {
1925 if (!fdisk_has_label(sf
->cxt
) && !sf
->label
)
1927 _("\nsfdisk is going to create a new '%s' disk label.\n"
1928 "Use 'label: <name>' before you define a first partition\n"
1929 "to override the default."), label
);
1930 fdisk_info(sf
->cxt
, _("\nType 'help' to get more information.\n"));
1931 } else if (!sf
->quiet
)
1932 fputc('\n', stdout
);
1934 tb
= fdisk_script_get_table(dp
);
1940 DBG(PARSE
, ul_debug("<---next-line--->"));
1941 if (next_partno
== (size_t) -1)
1942 next_partno
= fdisk_table_get_nents(tb
);
1946 && next_partno
== fdisk_get_npartitions(sf
->cxt
)
1947 && !has_container_or_unused(sf
)) {
1948 fdisk_info(sf
->cxt
, _("All partitions used."));
1949 rc
= SFDISK_DONE_ASK
;
1953 refresh_prompt_buffer(sf
, devname
, next_partno
, created
);
1956 if (sf
->prompt
&& (sf
->interactive
|| !sf
->quiet
)) {
1957 #ifndef HAVE_LIBREADLINE
1958 fputs(sf
->prompt
, stdout
);
1960 if (!sf
->interactive
)
1961 fputs(sf
->prompt
, stdout
);
1965 rc
= fdisk_script_read_line(dp
, stdin
, buf
, sizeof(buf
));
1966 if (rc
== -ENOTSUP
) {
1967 buf
[sizeof(buf
) - 1] = '\0';
1968 fdisk_warnx(sf
->cxt
, _("Unknown script header '%s' -- ignore."), buf
);
1973 DBG(PARSE
, ul_debug("script parsing failed, trying sfdisk specific commands"));
1974 buf
[sizeof(buf
) - 1] = '\0';
1975 rc
= loop_control_commands(sf
, dp
, buf
);
1982 rc
= SFDISK_DONE_EOF
;
1984 fputs(_("Done.\n"), stdout
);
1988 nparts
= fdisk_table_get_nents(tb
);
1990 size_t cur_partno
= (size_t) -1;
1991 struct fdisk_partition
*pa
= fdisk_table_get_partition(tb
, nparts
- 1);
1995 if (ignore_partition(pa
)) {
1996 fdisk_info(sf
->cxt
, _("Ignoring partition."));
2002 /* ignore "last-lba" and use default if --force specified */
2003 if (sf
->force
&& fdisk_script_get_header(dp
, "last-lba")) {
2004 fdisk_info(sf
->cxt
, _("Ignoring last-lba script header."));
2005 fdisk_script_set_header(dp
, "last-lba", NULL
);
2008 /* create a new disklabel */
2009 rc
= fdisk_apply_script_headers(sf
->cxt
, dp
);
2013 fdisk_warn(sf
->cxt
, _(
2014 "Failed to apply script headers, disk label not created"));
2016 if (rc
== 0 && fdisk_get_collision(sf
->cxt
))
2017 follow_wipe_mode(sf
);
2019 if (!rc
&& partno
>= 0) { /* -N <partno>, modify partition */
2020 rc
= fdisk_set_partition(sf
->cxt
, partno
, pa
);
2021 rc
= rc
== 0 ? SFDISK_DONE_ASK
: SFDISK_DONE_ABORT
;
2025 if (!rc
) { /* add partition */
2026 if (!sf
->interactive
&& !sf
->quiet
&&
2027 (!sf
->prompt
|| ul_startswith(sf
->prompt
, SFDISK_PROMPT
))) {
2028 refresh_prompt_buffer(sf
, devname
, next_partno
, created
);
2029 fputs(sf
->prompt
, stdout
);
2031 rc
= fdisk_add_partition(sf
->cxt
, pa
, &cur_partno
);
2034 fdisk_warn(sf
->cxt
, _("Failed to add #%zu partition"), next_partno
+ 1);
2038 /* wipe partition on success
2040 * Note that unused=1 means -N <partno> for unused,
2041 * otherwise we wipe only newly created partitions.
2043 if (rc
== 0 && (unused
|| partno
< 0)) {
2044 rc
= wipe_partition(sf
, unused
? (size_t) partno
: cur_partno
);
2050 /* success print result */
2051 if (sf
->interactive
)
2052 sfdisk_print_partition(sf
, cur_partno
);
2053 next_partno
= cur_partno
+ 1;
2054 } else if (pa
) /* error, drop partition from script */
2055 fdisk_table_remove_partition(tb
, pa
);
2057 fdisk_info(sf
->cxt
, _("Script header accepted."));
2059 if (rc
&& !sf
->interactive
) {
2060 rc
= SFDISK_DONE_ABORT
;
2065 /* create empty disk label if label, but no partition specified */
2066 if ((rc
== SFDISK_DONE_EOF
|| rc
== SFDISK_DONE_WRITE
) && created
== 0
2067 && fdisk_script_has_force_label(dp
) == 1
2068 && fdisk_table_get_nents(tb
) == (size_t) ignored
2069 && fdisk_script_get_header(dp
, "label")) {
2071 int xrc
= fdisk_apply_script_headers(sf
->cxt
, dp
);
2073 fdisk_warnx(sf
->cxt
, _(
2074 "Failed to apply script headers, "
2075 "disk label not created."));
2076 rc
= SFDISK_DONE_ABORT
;
2080 if (!sf
->quiet
&& rc
!= SFDISK_DONE_ABORT
) {
2081 fdisk_info(sf
->cxt
, _("\nNew situation:"));
2082 list_disk_identifier(sf
->cxt
);
2083 list_disklabel(sf
->cxt
);
2087 case SFDISK_DONE_ASK
:
2088 case SFDISK_DONE_EOF
:
2089 if (sf
->interactive
) {
2091 fdisk_ask_yesno(sf
->cxt
, _("Do you want to write this to disk?"), &yes
);
2093 fdisk_info(sf
->cxt
, _("Leaving."));
2099 case SFDISK_DONE_WRITE
:
2100 rc
= write_changes(sf
);
2102 case SFDISK_DONE_ABORT
:
2103 default: /* rc < 0 on error */
2104 fdisk_info(sf
->cxt
, _("Leaving.\n"));
2108 fdisk_set_script(sf
->cxt
, NULL
);
2109 fdisk_unref_script(dp
);
2113 static void __attribute__((__noreturn__
)) usage(void)
2116 fputs(USAGE_HEADER
, out
);
2119 _(" %1$s [options] <dev> [[-N] <part>]\n"
2120 " %1$s [options] <command>\n"), program_invocation_short_name
);
2122 fputs(USAGE_SEPARATOR
, out
);
2123 fputs(_("Display or manipulate a disk partition table.\n"), out
);
2125 fputs(USAGE_COMMANDS
, out
);
2126 fputs(_(" -A, --activate <dev> [<part> ...] list or set bootable (P)MBR partitions\n"), out
);
2127 fputs(_(" -d, --dump <dev> dump partition table (usable for later input)\n"), out
);
2128 fputs(_(" -J, --json <dev> dump partition table in JSON format\n"), out
);
2129 fputs(_(" -B, --backup-pt-sectors <dev> binary partition table backup (see -b and -O)\n"), out
);
2130 fputs(_(" -g, --show-geometry [<dev> ...] list geometry of all or specified devices\n"), out
);
2131 fputs(_(" -l, --list [<dev> ...] list partitions of each device\n"), out
);
2132 fputs(_(" -F, --list-free [<dev> ...] list unpartitioned free areas of each device\n"), out
);
2133 fputs(_(" -r, --reorder <dev> fix partitions order (by start offset)\n"), out
);
2134 fputs(_(" -s, --show-size [<dev> ...] list sizes of all or specified devices\n"), out
);
2135 fputs(_(" -T, --list-types print the recognized types (see -X)\n"), out
);
2136 fputs(_(" -V, --verify [<dev> ...] test whether partitions seem correct\n"), out
);
2137 fputs(_(" --delete <dev> [<part> ...] delete all or specified partitions\n"), out
);
2139 fputs(USAGE_SEPARATOR
, out
);
2140 fputs(_(" --part-label <dev> <part> [<str>] print or change partition label\n"), out
);
2141 fputs(_(" --part-type <dev> <part> [<type>] print or change partition type\n"), out
);
2142 fputs(_(" --part-uuid <dev> <part> [<uuid>] print or change partition uuid\n"), out
);
2143 fputs(_(" --part-attrs <dev> <part> [<str>] print or change partition attributes\n"), out
);
2145 fputs(USAGE_SEPARATOR
, out
);
2146 fputs(_(" --discard-free <dev> discard (trim) unpartitioned areas\n"), out
);
2147 fputs(_(" --disk-id <dev> [<str>] print or change disk label ID (UUID)\n"), out
);
2148 fputs(_(" --relocate <oper> <dev> move partition header\n"), out
);
2150 fputs(USAGE_ARGUMENTS
, out
);
2151 fputs(_(" <dev> device (usually disk) path\n"), out
);
2152 fputs(_(" <part> partition number\n"), out
);
2153 fputs(_(" <type> partition type, GUID for GPT, hex for MBR\n"), out
);
2155 fputs(USAGE_OPTIONS
, out
);
2156 fputs(_(" -a, --append append partitions to existing partition table\n"), out
);
2157 fputs(_(" -b, --backup backup partition table sectors (see -O)\n"), out
);
2158 fputs(_(" --bytes print SIZE in bytes rather than in human readable format\n"), out
);
2159 fputs(_(" --move-data[=<typescript>] move partition data after relocation (requires -N)\n"), out
);
2160 fputs(_(" --move-use-fsync use fsync after each write when move data\n"), out
);
2161 fputs(_(" -f, --force disable all consistency checking\n"), out
);
2164 _(" --color[=<when>] colorize output (%s, %s or %s)\n"), "auto", "always", "never");
2166 " %s\n", USAGE_COLORS_DEFAULT
);
2167 fputs(_(" --sector-size <size> physical and logical sector size\n"), out
);
2170 _(" --lock[=<mode>] use exclusive device lock (%s, %s or %s)\n"), "yes", "no", "nonblock");
2171 fputs(_(" -N, --partno <num> specify partition number\n"), out
);
2172 fputs(_(" -n, --no-act do everything except write to device\n"), out
);
2173 fputs(_(" --no-reread do not check whether the device is in use\n"), out
);
2174 fputs(_(" --no-tell-kernel do not tell kernel about changes\n"), out
);
2175 fputs(_(" -O, --backup-file <path> override default backup file name\n"), out
);
2176 fputs(_(" -o, --output <list> output columns\n"), out
);
2177 fputs(_(" -q, --quiet suppress extra info messages\n"), out
);
2179 _(" -w, --wipe <mode> wipe signatures (%s, %s or %s)\n"), "auto", "always", "never");
2181 _(" -W, --wipe-partitions <mode> wipe signatures from new partitions (%s, %s or %s)\n"), "auto", "always", "never");
2182 fputs(_(" -X, --label <name> specify label type (dos, gpt, ...)\n"), out
);
2183 fputs(_(" -Y, --label-nested <name> specify nested label type (dos, bsd)\n"), out
);
2184 fputs(USAGE_SEPARATOR
, out
);
2185 fputs(_(" -G, --show-pt-geometry deprecated, alias to --show-geometry\n"), out
);
2186 fputs(_(" -L, --Linux deprecated, only for backward compatibility\n"), out
);
2187 fputs(_(" -u, --unit S deprecated, only sector unit is supported\n"), out
);
2189 fputs(USAGE_SEPARATOR
, out
);
2190 fprintf(out
, " -h, --help %s\n", USAGE_OPTSTR_HELP
);
2191 fprintf(out
, " -v, --version %s\n", USAGE_OPTSTR_VERSION
);
2193 list_available_columns(out
);
2195 fprintf(out
, USAGE_MAN_TAIL("sfdisk(8)"));
2200 int main(int argc
, char *argv
[])
2202 const char *outarg
= NULL
;
2203 int rc
= -EINVAL
, c
, longidx
= -1, bytes
= 0;
2204 int colormode
= UL_COLORMODE_UNDEF
;
2206 struct sfdisk _sf
= {
2208 .wipemode
= WIPEMODE_AUTO
,
2209 .pwipemode
= WIPEMODE_AUTO
,
2210 .interactive
= isatty(STDIN_FILENO
) ? 1 : 0,
2214 OPT_CHANGE_ID
= CHAR_MAX
+ 1,
2235 static const struct option longopts
[] = {
2236 { "activate",no_argument
, NULL
, 'A' },
2237 { "append", no_argument
, NULL
, 'a' },
2238 { "backup-pt-sectors", no_argument
, NULL
, 'B' },
2239 { "backup", no_argument
, NULL
, 'b' },
2240 { "backup-file", required_argument
, NULL
, 'O' },
2241 { "bytes", no_argument
, NULL
, OPT_BYTES
},
2242 { "color", optional_argument
, NULL
, OPT_COLOR
},
2243 { "lock", optional_argument
, NULL
, OPT_LOCK
},
2244 { "delete", no_argument
, NULL
, OPT_DELETE
},
2245 { "dump", no_argument
, NULL
, 'd' },
2246 { "help", no_argument
, NULL
, 'h' },
2247 { "force", no_argument
, NULL
, 'f' },
2248 { "json", no_argument
, NULL
, 'J' },
2249 { "label", required_argument
, NULL
, 'X' },
2250 { "label-nested", required_argument
, NULL
, 'Y' },
2251 { "list", no_argument
, NULL
, 'l' },
2252 { "list-free", no_argument
, NULL
, 'F' },
2253 { "list-types", no_argument
, NULL
, 'T' },
2254 { "no-act", no_argument
, NULL
, 'n' },
2255 { "no-reread", no_argument
, NULL
, OPT_NOREREAD
},
2256 { "no-tell-kernel", no_argument
, NULL
, OPT_NOTELL
},
2257 { "move-data", optional_argument
, NULL
, OPT_MOVEDATA
},
2258 { "move-use-fsync", no_argument
, NULL
, OPT_MOVEFSYNC
},
2259 { "output", required_argument
, NULL
, 'o' },
2260 { "partno", required_argument
, NULL
, 'N' },
2261 { "reorder", no_argument
, NULL
, 'r' },
2262 { "sector-size", required_argument
, NULL
, OPT_SECTORSIZE
},
2263 { "show-geometry", no_argument
, NULL
, 'g' },
2264 { "quiet", no_argument
, NULL
, 'q' },
2265 { "verify", no_argument
, NULL
, 'V' },
2266 { "version", no_argument
, NULL
, 'v' },
2267 { "wipe", required_argument
, NULL
, 'w' },
2268 { "wipe-partitions", required_argument
, NULL
, 'W' },
2270 { "relocate", no_argument
, NULL
, OPT_RELOCATE
},
2272 { "part-uuid", no_argument
, NULL
, OPT_PARTUUID
},
2273 { "part-label", no_argument
, NULL
, OPT_PARTLABEL
},
2274 { "part-type", no_argument
, NULL
, OPT_PARTTYPE
},
2275 { "part-attrs", no_argument
, NULL
, OPT_PARTATTRS
},
2277 { "discard-free", no_argument
, NULL
, OPT_DISCARDFREE
},
2279 { "disk-id", no_argument
, NULL
, OPT_DISKID
},
2281 { "show-pt-geometry", no_argument
, NULL
, 'G' }, /* deprecated */
2282 { "unit", required_argument
, NULL
, 'u' }, /* deprecated */
2283 { "Linux", no_argument
, NULL
, 'L' }, /* deprecated */
2284 { "show-size", no_argument
, NULL
, 's' }, /* deprecated */
2286 { "change-id",no_argument
, NULL
, OPT_CHANGE_ID
}, /* deprecated */
2287 { "id", no_argument
, NULL
, 'c' }, /* deprecated */
2288 { "print-id",no_argument
, NULL
, OPT_PRINT_ID
}, /* deprecated */
2290 { NULL
, 0, NULL
, 0 },
2292 static const ul_excl_t excl
[] = { /* rows and cols in ASCII order */
2293 { 'F','d'}, /* --list-free --dump */
2294 { 'F','J'}, /* --list-free --json */
2295 { 's','u'}, /* --show-size --unit */
2298 int excl_st
[ARRAY_SIZE(excl
)] = UL_EXCL_STATUS_INIT
;
2301 setlocale(LC_ALL
, "");
2302 bindtextdomain(PACKAGE
, LOCALEDIR
);
2303 textdomain(PACKAGE
);
2304 close_stdout_atexit();
2306 while ((c
= getopt_long(argc
, argv
, "aAbBcdfFgGhJlLo:O:nN:qrsTu:vVX:Y:w:W:",
2307 longopts
, &longidx
)) != -1) {
2309 err_exclusive_options(c
, longopts
, excl
, excl_st
);
2313 sf
->act
= ACT_ACTIVATE
;
2322 sf
->act
= ACT_BACKUP_SECTORS
;
2327 warnx(_("%s is deprecated in favour of --part-type"),
2328 longopts
[longidx
].name
);
2329 sf
->act
= ACT_PARTTYPE
;
2332 warnx(_("--id is deprecated in favour of --part-type"));
2333 sf
->act
= ACT_PARTTYPE
;
2342 sf
->act
= ACT_LIST_FREE
;
2348 warnx(_("--show-pt-geometry is no more implemented. Using --show-geometry."));
2351 sf
->act
= ACT_SHOW_GEOM
;
2360 warnx(_("--Linux option is unnecessary and deprecated"));
2367 sf
->backup_file
= optarg
;
2373 sf
->partno
= strtou32_or_err(optarg
, _("failed to parse partition number")) - 1;
2379 sf
->act
= ACT_REORDER
;
2382 sf
->act
= ACT_SHOW_SIZE
;
2385 sf
->act
= ACT_LIST_TYPES
;
2389 errx(EXIT_FAILURE
, _("unsupported unit '%c'"), *optarg
);
2392 print_version(EXIT_SUCCESS
);
2397 sf
->wipemode
= wipemode_from_string(optarg
);
2398 if (sf
->wipemode
< 0)
2399 errx(EXIT_FAILURE
, _("unsupported wipe mode"));
2402 sf
->pwipemode
= wipemode_from_string(optarg
);
2403 if (sf
->pwipemode
< 0)
2404 errx(EXIT_FAILURE
, _("unsupported wipe mode"));
2410 sf
->label_nested
= optarg
;
2414 sf
->act
= ACT_PARTUUID
;
2417 sf
->act
= ACT_PARTTYPE
;
2420 sf
->act
= ACT_PARTLABEL
;
2423 sf
->act
= ACT_PARTATTRS
;
2425 case OPT_DISCARDFREE
:
2426 sf
->act
= ACT_DISCARD_FREE
;
2429 sf
->act
= ACT_DISKID
;
2438 colormode
= UL_COLORMODE_AUTO
;
2440 colormode
= colormode_or_err(optarg
);
2444 sf
->move_typescript
= optarg
;
2450 sf
->act
= ACT_DELETE
;
2456 sf
->act
= ACT_RELOCATE
;
2463 sf
->lockmode
= optarg
;
2466 case OPT_SECTORSIZE
:
2467 user_ss
= strtou32_or_err(optarg
,
2468 _("invalid sector size argument"));
2469 if (user_ss
!= 512 && user_ss
!= 1024 &&
2470 user_ss
!= 2048 && user_ss
!= 4096)
2471 errx(EXIT_FAILURE
, _("invalid sector size argument"));
2474 errtryhelp(EXIT_FAILURE
);
2478 colors_init(colormode
, "sfdisk");
2482 fdisk_set_size_unit(sf
->cxt
, FDISK_SIZEUNIT_BYTES
);
2484 fdisk_save_user_sector_size(sf
->cxt
, user_ss
, user_ss
);
2487 init_fields(NULL
, outarg
, NULL
);
2489 if (sf
->verify
&& !sf
->act
)
2490 sf
->act
= ACT_VERIFY
; /* --verify make be used with --list too */
2492 sf
->act
= ACT_FDISK
; /* default */
2494 if (sf
->movedata
&& !(sf
->act
== ACT_FDISK
&& sf
->partno
>= 0))
2495 errx(EXIT_FAILURE
, _("--movedata requires -N"));
2499 rc
= command_activate(sf
, argc
- optind
, argv
+ optind
);
2502 case ACT_BACKUP_SECTORS
:
2503 rc
= command_backup_sectors(sf
, argc
- optind
, argv
+ optind
);
2507 rc
= command_delete(sf
, argc
- optind
, argv
+ optind
);
2511 rc
= command_list_partitions(sf
, argc
- optind
, argv
+ optind
);
2514 case ACT_LIST_TYPES
:
2515 rc
= command_list_types(sf
);
2519 rc
= command_list_freespace(sf
, argc
- optind
, argv
+ optind
);
2523 rc
= command_fdisk(sf
, argc
- optind
, argv
+ optind
);
2527 rc
= command_dump(sf
, argc
- optind
, argv
+ optind
);
2531 rc
= command_show_size(sf
, argc
- optind
, argv
+ optind
);
2535 rc
= command_show_geometry(sf
, argc
- optind
, argv
+ optind
);
2539 rc
= command_verify(sf
, argc
- optind
, argv
+ optind
);
2543 rc
= command_parttype(sf
, argc
- optind
, argv
+ optind
);
2547 rc
= command_partuuid(sf
, argc
- optind
, argv
+ optind
);
2551 rc
= command_partlabel(sf
, argc
- optind
, argv
+ optind
);
2555 rc
= command_partattrs(sf
, argc
- optind
, argv
+ optind
);
2558 case ACT_DISCARD_FREE
:
2559 rc
= command_discard_free(sf
, argc
- optind
, argv
+ optind
);
2563 rc
= command_diskid(sf
, argc
- optind
, argv
+ optind
);
2567 rc
= command_reorder(sf
, argc
- optind
, argv
+ optind
);
2571 rc
= command_relocate(sf
, argc
- optind
, argv
+ optind
);
2577 DBG(MISC
, ul_debug("bye! [rc=%d]", rc
));
2578 return rc
== 0 ? EXIT_SUCCESS
: EXIT_FAILURE
;