ACT_LIST_FREE,
ACT_LIST_TYPES,
ACT_REORDER,
+ ACT_RELOCATE,
ACT_SHOW_SIZE,
ACT_SHOW_GEOM,
ACT_VERIFY,
ACT_PARTLABEL,
ACT_PARTATTRS,
ACT_DISKID,
- ACT_DELETE
+ ACT_DELETE,
+ ACT_BACKUP_SECTORS,
};
struct sfdisk {
int partno; /* -N <partno>, default -1 */
int wipemode; /* remove foreign signatures from disk */
int pwipemode; /* remove foreign signatures from partitions */
+ const char *lockmode; /* as specified by --lock */
const char *label; /* --label <label> */
const char *label_nested; /* --label-nested <label> */
const char *backup_file; /* -O <path> */
force : 1, /* do also stupid things */
backup : 1, /* backup sectors before write PT */
container : 1, /* PT contains container (MBR extended) partitions */
+ unused : 1, /* PT contains unused partition */
append : 1, /* don't create new PT, append partitions only */
json : 1, /* JSON dump */
movedata: 1, /* move data after resize */
if (!sf->cxt)
err(EXIT_FAILURE, _("failed to allocate libfdisk context"));
fdisk_set_ask(sf->cxt, ask_callback, (void *) sf);
- fdisk_enable_bootbits_protection(sf->cxt, 1);
+
+ if (sf->wipemode != WIPEMODE_ALWAYS)
+ fdisk_enable_bootbits_protection(sf->cxt, 1);
if (sf->label_nested) {
struct fdisk_context *x = fdisk_new_nested_context(sf->cxt,
free(tpl);
}
+static int assign_device(struct sfdisk *sf, const char *devname, int rdonly)
+{
+ struct fdisk_context *cxt = sf->cxt;
+
+ if (fdisk_assign_device(cxt, devname, rdonly) != 0)
+ err(EXIT_FAILURE, _("cannot open %s"), devname);
+
+ if (!fdisk_is_readonly(cxt)) {
+ if (blkdev_lock(fdisk_get_devfd(cxt), devname, sf->lockmode) != 0) {
+ fdisk_deassign_device(cxt, 1);
+ exit(EXIT_FAILURE);
+ }
+ if (sf->backup)
+ backup_partition_table(sf, devname);
+ }
+ return 0;
+}
+
+
static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_partition *orig_pa)
{
struct fdisk_partition *pa = get_partition(sf->cxt, partno);
FILE *f = NULL;
int ok = 0, fd, backward = 0;
fdisk_sector_t nsectors, from, to, step, i, prev;
- size_t io, ss, step_bytes, cc;
+ size_t io, ss, step_bytes, cc, ioerr = 0;
uintmax_t src, dst, nbytes;
- int errsv, progress = 0;
+ int progress = 0, rc = 0;
struct timeval prev_time;
uint64_t bytes_per_sec = 0;
warnx(_("failed to get start of the old partition; ignoring --move-data"));
else if (fdisk_partition_get_start(pa) == fdisk_partition_get_start(orig_pa))
warnx(_("start of the partition has not been moved; ignoring --move-data"));
- else if (fdisk_partition_get_size(orig_pa) < fdisk_partition_get_size(pa))
+ else if (fdisk_partition_get_size(orig_pa) > fdisk_partition_get_size(pa))
warnx(_("new partition is smaller than original; ignoring --move-data"));
else
ok = 1;
from = fdisk_partition_get_start(orig_pa);
to = fdisk_partition_get_start(pa);
-
if ((to >= from && from + nsectors >= to) ||
(from >= to && to + nsectors >= from)) {
/* source and target overlay, check if we need to copy
#if defined(POSIX_FADV_SEQUENTIAL) && defined(HAVE_POSIX_FADVISE)
if (!backward)
- posix_fadvise(fd, from * ss, nsectors * ss, POSIX_FADV_SEQUENTIAL);
+ ignore_result( posix_fadvise(fd, from * ss,
+ nsectors * ss, POSIX_FADV_SEQUENTIAL) );
#endif
devname = fdisk_partname(fdisk_get_devname(sf->cxt), partno+1);
if (sf->move_typescript)
typescript = mk_backup_filename_tpl(sf->move_typescript, devname, ".move");
if (!sf->quiet) {
- fdisk_info(sf->cxt,"");
+ fdisk_info(sf->cxt, "%s", "");
color_scheme_enable("header", UL_COLOR_BOLD);
fdisk_info(sf->cxt, sf->noact ? _("Data move: (--no-act)") : _("Data move:"));
color_disable();
fdisk_ask_yesno(sf->cxt, _("Do you want to move partition data?"), &yes);
if (!yes) {
fdisk_info(sf->cxt, _("Leaving."));
+ free(devname);
return 0;
}
}
if (typescript) {
f = fopen(typescript, "w");
if (!f) {
+ rc = -errno;
fdisk_warn(sf->cxt, _("cannot open %s"), typescript);
- goto fail;
+ goto done;
}
/* don't translate */
(uintmax_t)to, (uintmax_t)to * ss);
fprintf(f, "# Area size (sectors/bytes): %ju/%ju\n",
(uintmax_t)nsectors, (uintmax_t)nsectors * ss);
- fprintf(f, "# Step size (sectors/bytes): %zu/%zu\n", step, step_bytes);
+ fprintf(f, "# Step size (sectors/bytes): %" PRIu64 "/%zu\n", step, step_bytes);
fprintf(f, "# Steps: %ju\n", ((uintmax_t) nsectors / step) + 1);
fprintf(f, "#\n");
fprintf(f, "# <step>: <from> <to> (step offsets in bytes)\n");
prev = 0;
for (cc = 1, i = 0; i < nsectors && nbytes > 0; i += step, cc++) {
- ssize_t rc;
-
- if (backward)
- src -= step_bytes, dst -= step_bytes;
-
- DBG(MISC, ul_debug("#%05zu: src=%ju dst=%ju", cc, src, dst));
if (nbytes < step_bytes) {
- DBG(MISC, ul_debug(" aligning step from %ju to %ju",
- step_bytes, nbytes));
+ DBG(MISC, ul_debug("aligning step #%05zu from %zu to %ju",
+ cc, step_bytes, nbytes));
step_bytes = nbytes;
}
nbytes -= step_bytes;
+ if (backward)
+ src -= step_bytes, dst -= step_bytes;
+
+ DBG(MISC, ul_debug("#%05zu: src=%ju dst=%ju", cc, src, dst));
+
if (!sf->noact) {
/* read source */
- if (lseek(fd, src, SEEK_SET) == (off_t) -1)
- goto fail;
- rc = read(fd, buf, step_bytes);
- if (rc < 0 || rc != (ssize_t) step_bytes)
- goto fail;
+ if (lseek(fd, src, SEEK_SET) == (off_t) -1 ||
+ read_all(fd, buf, step_bytes) != (ssize_t) step_bytes) {
+ if (f)
+ fprintf(f, "%05zu: read error %12ju %12ju\n", cc, src, dst);
+ fdisk_warn(sf->cxt,
+ _("cannot read at offset: %ju; continue"), src);
+ ioerr++;
+ goto next;
+ }
/* write target */
- if (lseek(fd, dst, SEEK_SET) == (off_t) -1)
- goto fail;
- rc = write(fd, buf, step_bytes);
- if (rc < 0 || rc != (ssize_t) step_bytes)
- goto fail;
- if (sf->movefsync)
- fsync(fd);
+ if (lseek(fd, dst, SEEK_SET) == (off_t) -1 ||
+ write_all(fd, buf, step_bytes) != 0) {
+ if (f)
+ fprintf(f, "%05zu: write error %12ju %12ju\n", cc, src, dst);
+ fdisk_warn(sf->cxt,
+ _("cannot write at offset: %ju; continue"), dst);
+ ioerr++;
+ goto next;
+ }
+ if (sf->movefsync && fsync(fd) != 0)
+ fdisk_warn(sf->cxt,
+ _("cannot fsync at offset: %ju; continue"), dst);
}
/* write log */
fputc('\r', stdout);
}
-
+next:
if (!backward)
src += step_bytes, dst += step_bytes;
}
- if (progress) {
+ if (progress && nsectors) {
int x = get_terminal_width(80);
for (; x > 0; x--)
fputc(' ', stdout);
fflush(stdout);
fputc('\r', stdout);
+
+ if (i > nsectors)
+ /* see for() above; @i has to be greater than @nsectors
+ * on success due to i += step */
+ i = nsectors;
+
fprintf(stdout, _("Moved %ju from %ju sectors (%.0f%%)."),
i, nsectors,
100.0 / ((double) nsectors/(i+1)));
fputc('\n', stdout);
}
+ rc = 0;
+done:
if (f)
fclose(f);
free(buf);
- free(devname);
free(typescript);
if (sf->noact)
fdisk_info(sf->cxt, _("Your data has not been moved (--no-act)."));
+ if (ioerr) {
+ fdisk_info(sf->cxt, _("%zu I/O errors detected!"), ioerr);
+ rc = -EIO;
+ } else if (rc)
+ warn(_("%s: failed to move data"), devname);
- return 0;
-fail:
- errsv = -errno;
- warn(_("%s: failed to move data"), devname);
- if (f)
- fclose(f);
- free(buf);
free(devname);
- free(typescript);
- return errsv;
+ return rc;
}
static int write_changes(struct sfdisk *sf)
fdisk_enable_listonly(sf->cxt, 1);
if (argc) {
- int i, ct = 0;
+ int i;
- for (i = 0; i < argc; i++) {
- if (ct)
- fputs("\n\n", stdout);
- if (print_device_pt(sf->cxt, argv[i], 1, sf->verify) != 0)
+ for (i = 0; i < argc; i++)
+ if (print_device_pt(sf->cxt, argv[i], 1, sf->verify, i) != 0)
fail++;
- ct++;
- }
} else
print_all_devices_pt(sf->cxt, sf->verify);
fdisk_enable_listonly(sf->cxt, 1);
if (argc) {
- int i, ct = 0;
+ int i;
- for (i = 0; i < argc; i++) {
- if (ct)
- fputs("\n\n", stdout);
- if (print_device_freespace(sf->cxt, argv[i], 1) != 0)
+ for (i = 0; i < argc; i++)
+ if (print_device_freespace(sf->cxt, argv[i], 1, i) != 0)
fail++;
- ct++;
- }
} else
print_all_devices_freespace(sf->cxt);
fdisk_enable_listonly(sf->cxt, 1);
- if (fdisk_assign_device(sf->cxt, devname, 1)) {
- warn(_("cannot open %s"), devname);
- return 1;
- }
+ assign_device(sf, devname, 1);
color_scheme_enable("header", UL_COLOR_BOLD);
fdisk_info(sf->cxt, "%s:", devname);
{
fdisk_enable_listonly(sf->cxt, 1);
- if (fdisk_assign_device(sf->cxt, devname, 1)) {
- warn(_("cannot open %s"), devname);
- return 1;
- }
+ assign_device(sf, devname, 1);
fdisk_info(sf->cxt, "%s: %ju cylinders, %ju heads, %ju sectors/track",
devname,
/* --activate <device> */
listonly = argc == 1;
- rc = fdisk_assign_device(sf->cxt, devname, listonly);
- if (rc)
- err(EXIT_FAILURE, _("cannot open %s"), devname);
+ assign_device(sf, devname, listonly);
if (fdisk_is_label(sf->cxt, GPT)) {
if (fdisk_gpt_is_hybrid(sf->cxt))
} else if (!fdisk_is_label(sf->cxt, DOS))
errx(EXIT_FAILURE, _("toggle boot flags is supported for MBR or PMBR only"));
- if (!listonly && sf->backup)
- backup_partition_table(sf, devname);
-
nparts = fdisk_get_npartitions(sf->cxt);
for (i = 0; i < nparts; i++) {
char *data = NULL;
errx(EXIT_FAILURE, _("no disk device specified"));
devname = argv[0];
- if (fdisk_assign_device(sf->cxt, devname, 0) != 0)
- err(EXIT_FAILURE, _("cannot open %s"), devname);
-
- if (sf->backup)
- backup_partition_table(sf, devname);
+ assign_device(sf, devname, 0);
/* delete all */
if (argc == 1) {
if (!devname)
errx(EXIT_FAILURE, _("no disk device specified"));
- rc = fdisk_assign_device(sf->cxt, devname, 0); /* read-write */
- if (rc)
- err(EXIT_FAILURE, _("cannot open %s"), devname);
-
- if (sf->backup)
- backup_partition_table(sf, devname);
+ assign_device(sf, devname, 0); /* read-write */
if (fdisk_reorder_partitions(sf->cxt) == 1) /* unchanged */
rc = fdisk_deassign_device(sf->cxt, 1);
if (!devname)
errx(EXIT_FAILURE, _("no disk device specified"));
- rc = fdisk_assign_device(sf->cxt, devname, 1); /* read-only */
- if (rc)
- err(EXIT_FAILURE, _("cannot open %s"), devname);
+ assign_device(sf, devname, 1); /* read-only */
if (!fdisk_has_label(sf->cxt))
errx(EXIT_FAILURE, _("%s: does not contain a recognized partition table"), devname);
return 0;
}
+/*
+ * sfdisk --backup-pt-sectors <device>
+ */
+static int command_backup_sectors(struct sfdisk *sf, int argc, char **argv)
+{
+ const char *devname = NULL;
+
+ if (argc)
+ devname = argv[0];
+ if (!devname)
+ errx(EXIT_FAILURE, _("no disk device specified"));
+
+ assign_device(sf, devname, 1); /* read-only */
+
+ if (!fdisk_has_label(sf->cxt))
+ errx(EXIT_FAILURE, _("%s: does not contain a recognized partition table"), devname);
+
+ backup_partition_table(sf, devname);
+
+ fdisk_deassign_device(sf->cxt, 1); /* no-sync() */
+ return 0;
+}
+
static void assign_device_partition(struct sfdisk *sf,
const char *devname,
size_t partno,
if (rc)
err(EXIT_FAILURE, _("cannot open %s"), devname);
+ if (!fdisk_is_readonly(sf->cxt)
+ && blkdev_lock(fdisk_get_devfd(sf->cxt), devname, sf->lockmode) != 0) {
+ fdisk_deassign_device(sf->cxt, 1);
+ return;
+ }
lb = fdisk_get_label(sf->cxt, NULL);
if (!lb)
errx(EXIT_FAILURE, _("%s: no partition table found"), devname);
backup_partition_table(sf, devname);
/* parse <type> and apply to PT */
- type = fdisk_label_parse_parttype(lb, typestr);
+ type = fdisk_label_advparse_parttype(lb, typestr,
+ FDISK_PARTTYPE_PARSE_DATA
+ | FDISK_PARTTYPE_PARSE_ALIAS
+ | FDISK_PARTTYPE_PARSE_NAME
+ | FDISK_PARTTYPE_PARSE_SHORTCUT);
if (!type)
errx(EXIT_FAILURE, _("failed to parse %s partition type '%s'"),
fdisk_label_get_name(lb), typestr);
else if (argc > 2)
errx(EXIT_FAILURE, _("unexpected arguments"));
- if (fdisk_assign_device(sf->cxt, devname, !str) != 0)
- err(EXIT_FAILURE, _("cannot open %s"), devname);
+ assign_device(sf, devname, !str);
/* print */
if (!str) {
return 0;
}
- /* change */
- if (sf->backup)
- backup_partition_table(sf, devname);
-
if (fdisk_set_disklabel_id_from_string(sf->cxt, str) != 0)
errx(EXIT_FAILURE, _("%s: failed to set disklabel ID"), devname);
return write_changes(sf);
}
+/*
+ * sfdisk --relocate <mode> <device>
+ */
+static int command_relocate(struct sfdisk *sf, int argc, char **argv)
+{
+ const char *devname = NULL;
+ const char *oper = NULL;
+ struct fdisk_label *lb;
+
+ if (!argc)
+ errx(EXIT_FAILURE, _("no relocate operation specified"));
+ if (argc < 2)
+ errx(EXIT_FAILURE, _("no disk device specified"));
+ if (argc > 2)
+ errx(EXIT_FAILURE, _("unexpected arguments"));
+
+ oper = argv[0];
+ devname = argv[1];
+ lb = fdisk_get_label(sf->cxt, "gpt");
+
+ if (strcmp(oper, "gpt-bak-mini") == 0)
+ fdisk_gpt_enable_minimize(lb, 1);
+
+ else if (strcmp(oper, "gpt-bak-std") != 0)
+ errx(EXIT_FAILURE, _("unsupported relocation operation"));
+
+ assign_device(sf, devname, 0);
+
+ fdisk_label_set_changed(lb, 1);
+
+ return write_changes(sf);
+}
+
static void sfdisk_print_partition(struct sfdisk *sf, size_t n)
{
struct fdisk_partition *pa = NULL;
fputc('\n', stdout);
fputs(_(" <type> The partition type. Default is a Linux data partition.\n"), stdout);
- fputs(_(" MBR: hex or L,S,E,X,U,R,V shortcuts.\n"), stdout);
+ fputs(_(" MBR: hex or L,S,Ex,X,U,R,V shortcuts.\n"), stdout);
fputs(_(" GPT: UUID or L,S,H,U,R,V shortcuts.\n"), stdout);
fputc('\n', stdout);
return rc;
}
-static int has_container(struct sfdisk *sf)
+static int has_container_or_unused(struct sfdisk *sf)
{
size_t i, nparts;
struct fdisk_partition *pa = NULL;
- if (sf->container)
- return sf->container;
+ if (sf->container || sf->unused)
+ return 1;
nparts = fdisk_get_npartitions(sf->cxt);
for (i = 0; i < nparts; i++) {
+
+ if (!fdisk_is_partition_used(sf->cxt, i)) {
+ sf->unused = 1;
+ continue;
+ }
if (fdisk_get_partition(sf->cxt, i, &pa) != 0)
continue;
- if (fdisk_partition_is_container(pa)) {
+ if (fdisk_partition_is_container(pa))
sf->container = 1;
- break;
- }
}
fdisk_unref_partition(pa);
- return sf->container;
+ return sf->container || sf->unused;
}
static size_t last_pt_partno(struct sfdisk *sf)
if (dowipe) {
if (!fdisk_is_ptcollision(sf->cxt)) {
fdisk_warnx(sf->cxt, _(
- "The device contains '%s' signature and it will be removed by a write command. "
+ "The device contains '%s' signature and it may be removed by a write command. "
"See sfdisk(8) man page and --wipe option for more details."),
fdisk_get_collision(sf->cxt));
fputc('\n', stdout);
*/
static int command_fdisk(struct sfdisk *sf, int argc, char **argv)
{
- int rc = 0, partno = sf->partno, created = 0, unused = 0;
+ int rc = 0, partno = sf->partno, created = 0, unused = 0, ignored = 0;
struct fdisk_script *dp;
struct fdisk_table *tb = NULL;
const char *devname = NULL, *label;
if (!devname)
errx(EXIT_FAILURE, _("no disk device specified"));
- rc = fdisk_assign_device(sf->cxt, devname, 0);
- if (rc)
- err(EXIT_FAILURE, _("cannot open %s"), devname);
+ assign_device(sf, devname, 0);
dp = fdisk_new_script(sf->cxt);
if (!dp)
if (fdisk_get_collision(sf->cxt))
follow_wipe_mode(sf);
- if (sf->backup)
- backup_partition_table(sf, devname);
-
if (!sf->quiet) {
list_disk_geometry(sf->cxt);
if (fdisk_has_label(sf->cxt)) {
if (created
&& partno < 0
&& next_partno == fdisk_get_npartitions(sf->cxt)
- && !has_container(sf)) {
+ && !has_container_or_unused(sf)) {
fdisk_info(sf->cxt, _("All partitions used."));
rc = SFDISK_DONE_ASK;
break;
buf[sizeof(buf) - 1] = '\0';
fdisk_warnx(sf->cxt, _("Unknown script header '%s' -- ignore."), buf);
continue;
- } else if (rc < 0) {
+ }
+
+ if (rc < 0) {
DBG(PARSE, ul_debug("script parsing failed, trying sfdisk specific commands"));
buf[sizeof(buf) - 1] = '\0';
rc = loop_control_commands(sf, dp, buf);
if (rc)
break;
continue;
- } else if (rc == 1) {
+ }
+
+ if (rc == 1) {
rc = SFDISK_DONE_EOF;
if (!sf->quiet)
fputs(_("Done.\n"), stdout);
if (ignore_partition(pa)) {
fdisk_info(sf->cxt, _("Ignoring partition."));
next_partno++;
+ ignored++;
continue;
}
if (!created) { /* create a new disklabel */
rc = fdisk_apply_script_headers(sf->cxt, dp);
created = !rc;
- if (rc)
- fdisk_warnx(sf->cxt, _(
- "Failed to apply script headers, "
- "disk label not created."));
+ if (rc) {
+ errno = -rc;
+ fdisk_warn(sf->cxt, _(
+ "Failed to apply script headers, disk label not created"));
+ }
if (rc == 0 && fdisk_get_collision(sf->cxt))
follow_wipe_mode(sf);
rc = fdisk_set_partition(sf->cxt, partno, pa);
rc = rc == 0 ? SFDISK_DONE_ASK : SFDISK_DONE_ABORT;
break;
- } else if (!rc) { /* add partition */
+ }
+
+ if (!rc) { /* add partition */
if (!sf->interactive && !sf->quiet &&
(!sf->prompt || startswith(sf->prompt, SFDISK_PROMPT))) {
refresh_prompt_buffer(sf, devname, next_partno, created);
rc = fdisk_add_partition(sf->cxt, pa, &cur_partno);
if (rc) {
errno = -rc;
- fdisk_warn(sf->cxt, _("Failed to add #%d partition"), next_partno + 1);
+ fdisk_warn(sf->cxt, _("Failed to add #%zu partition"), next_partno + 1);
}
}
/* create empty disk label if label, but no partition specified */
if ((rc == SFDISK_DONE_EOF || rc == SFDISK_DONE_WRITE) && created == 0
&& fdisk_script_has_force_label(dp) == 1
- && fdisk_table_get_nents(tb) == 0
+ && fdisk_table_get_nents(tb) == (size_t) ignored
&& fdisk_script_get_header(dp, "label")) {
int xrc = fdisk_apply_script_headers(sf->cxt, dp);
fputs(_(" -A, --activate <dev> [<part> ...] list or set bootable (P)MBR partitions\n"), out);
fputs(_(" -d, --dump <dev> dump partition table (usable for later input)\n"), out);
fputs(_(" -J, --json <dev> dump partition table in JSON format\n"), out);
+ fputs(_(" -B, --backup-pt-sectors <dev> binary partition table backup (see -b and -O)\n"), out);
fputs(_(" -g, --show-geometry [<dev> ...] list geometry of all or specified devices\n"), out);
fputs(_(" -l, --list [<dev> ...] list partitions of each device\n"), out);
fputs(_(" -F, --list-free [<dev> ...] list unpartitioned free areas of each device\n"), out);
fputs(USAGE_SEPARATOR, out);
fputs(_(" --disk-id <dev> [<str>] print or change disk label ID (UUID)\n"), out);
+ fputs(_(" --relocate <oper> <dev> move partition header\n"), out);
- fputs(USAGE_SEPARATOR, out);
+ fputs(USAGE_ARGUMENTS, out);
fputs(_(" <dev> device (usually disk) path\n"), out);
fputs(_(" <part> partition number\n"), out);
fputs(_(" <type> partition type, GUID for GPT, hex for MBR\n"), out);
fputs(_(" --move-data[=<typescript>] move partition data after relocation (requires -N)\n"), out);
fputs(_(" --move-use-fsync use fsync after each write when move data\n"), out);
fputs(_(" -f, --force disable all consistency checking\n"), out);
+
fprintf(out,
_(" --color[=<when>] colorize output (%s, %s or %s)\n"), "auto", "always", "never");
fprintf(out,
" %s\n", USAGE_COLORS_DEFAULT);
+ fprintf(out,
+ _(" --lock[=<mode>] use exclusive device lock (%s, %s or %s)\n"), "yes", "no", "nonblock");
fputs(_(" -N, --partno <num> specify partition number\n"), out);
fputs(_(" -n, --no-act do everything except write to device\n"), out);
fputs(_(" --no-reread do not check whether the device is in use\n"), out);
fputs(_(" -u, --unit S deprecated, only sector unit is supported\n"), out);
fputs(USAGE_SEPARATOR, out);
- printf( " -h, --help %s\n", USAGE_OPTSTR_HELP);
- printf( " -v, --version %s\n", USAGE_OPTSTR_VERSION);
+ fprintf(out, " -h, --help %s\n", USAGE_OPTSTR_HELP);
+ fprintf(out, " -v, --version %s\n", USAGE_OPTSTR_VERSION);
list_available_columns(out);
- printf(USAGE_MAN_TAIL("sfdisk(8)"));
+ fprintf(out, USAGE_MAN_TAIL("sfdisk(8)"));
exit(EXIT_SUCCESS);
}
OPT_MOVEDATA,
OPT_MOVEFSYNC,
OPT_DELETE,
- OPT_NOTELL
+ OPT_NOTELL,
+ OPT_RELOCATE,
+ OPT_LOCK,
};
static const struct option longopts[] = {
{ "activate",no_argument, NULL, 'A' },
{ "append", no_argument, NULL, 'a' },
+ { "backup-pt-sectors", no_argument, NULL, 'B' },
{ "backup", no_argument, NULL, 'b' },
{ "backup-file", required_argument, NULL, 'O' },
{ "bytes", no_argument, NULL, OPT_BYTES },
{ "color", optional_argument, NULL, OPT_COLOR },
+ { "lock", optional_argument, NULL, OPT_LOCK },
{ "delete", no_argument, NULL, OPT_DELETE },
{ "dump", no_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "wipe", required_argument, NULL, 'w' },
{ "wipe-partitions", required_argument, NULL, 'W' },
+ { "relocate", no_argument, NULL, OPT_RELOCATE },
+
{ "part-uuid", no_argument, NULL, OPT_PARTUUID },
{ "part-label", no_argument, NULL, OPT_PARTLABEL },
{ "part-type", no_argument, NULL, OPT_PARTTYPE },
{ NULL, 0, NULL, 0 },
};
static const ul_excl_t excl[] = { /* rows and cols in ASCII order */
- { 'F','J','d'}, /* --list-free --json --dump */
+ { 'F','d'}, /* --list-free --dump */
+ { 'F','J'}, /* --list-free --json */
{ 's','u'}, /* --show-size --unit */
{ 0 }
};
textdomain(PACKAGE);
close_stdout_atexit();
- while ((c = getopt_long(argc, argv, "aAbcdfFgGhJlLo:O:nN:qrsTu:vVX:Y:w:W:",
+ while ((c = getopt_long(argc, argv, "aAbBcdfFgGhJlLo:O:nN:qrsTu:vVX:Y:w:W:",
longopts, &longidx)) != -1) {
err_exclusive_options(c, longopts, excl, excl_st);
case 'b':
sf->backup = 1;
break;
+ case 'B':
+ sf->act = ACT_BACKUP_SECTORS;
+ break;
case OPT_CHANGE_ID:
case OPT_PRINT_ID:
case OPT_ID:
case OPT_NOTELL:
sf->notell = 1;
break;
+ case OPT_RELOCATE:
+ sf->act = ACT_RELOCATE;
+ break;
+ case OPT_LOCK:
+ sf->lockmode = "1";
+ if (optarg) {
+ if (*optarg == '=')
+ optarg++;
+ sf->lockmode = optarg;
+ }
+ break;
default:
errtryhelp(EXIT_FAILURE);
}
rc = command_activate(sf, argc - optind, argv + optind);
break;
+ case ACT_BACKUP_SECTORS:
+ rc = command_backup_sectors(sf, argc - optind, argv + optind);
+ break;
+
case ACT_DELETE:
rc = command_delete(sf, argc - optind, argv + optind);
break;
case ACT_REORDER:
rc = command_reorder(sf, argc - optind, argv + optind);
break;
+
+ case ACT_RELOCATE:
+ rc = command_relocate(sf, argc - optind, argv + optind);
+ break;
}
sfdisk_deinit(sf);
DBG(MISC, ul_debug("bye! [rc=%d]", rc));
return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
-