#include <sys/time.h>
#include <time.h>
#include <limits.h>
+#include <signal.h>
+#include <poll.h>
#include <libsmartcols.h>
+#ifdef HAVE_LIBREADLINE
+# define _FUNCTION_DEF
+# include <readline/readline.h>
+#endif
#include "c.h"
#include "xalloc.h"
#include "canonicalize.h"
#include "strutils.h"
#include "closestream.h"
-#include "sysfs.h"
+#include "pager.h"
#include "fdisk.h"
# include <linux/blkpg.h>
#endif
+int pwipemode = WIPEMODE_AUTO;
+int device_is_used;
+int is_interactive;
+struct fdisk_table *original_layout;
+
+static int wipemode = WIPEMODE_AUTO;
+
/*
* fdisk debug stuff (see fdisk.h and include/debug.h)
*/
UL_DEBUG_DEFINE_MASK(fdisk);
-UL_DEBUG_DEFINE_MASKANEMS(fdisk) = UL_DEBUG_EMPTY_MASKNAMES;
+UL_DEBUG_DEFINE_MASKNAMES(fdisk) = UL_DEBUG_EMPTY_MASKNAMES;
static void fdiskprog_init_debug(void)
{
- __UL_INIT_DEBUG(fdisk, FDISKPROG_DEBUG_, 0, FDISK_DEBUG);
+ __UL_INIT_DEBUG_FROM_ENV(fdisk, FDISKPROG_DEBUG_, 0, FDISK_DEBUG);
}
-int get_user_reply(struct fdisk_context *cxt, const char *prompt,
- char *buf, size_t bufsz)
+static void reply_sighandler(int sig __attribute__((unused)))
{
- char *p;
+ DBG(ASK, ul_debug("got signal"));
+}
+
+static int reply_running;
+
+#ifdef HAVE_LIBREADLINE
+static char *reply_line;
+
+static void reply_linehandler(char *line)
+{
+ reply_line = line;
+ reply_running = 0;
+ rl_callback_handler_remove(); /* avoid duplicate prompt */
+}
+#endif
+
+int get_user_reply(const char *prompt, char *buf, size_t bufsz)
+{
+ struct sigaction oldact, act = {
+ .sa_handler = reply_sighandler
+ };
+ struct pollfd fds[] = {
+ { .fd = fileno(stdin), .events = POLLIN }
+ };
size_t sz;
+ int ret = 0;
+
+ DBG(ASK, ul_debug("asking for user reply %s", is_interactive ? "[interactive]" : ""));
+ sigemptyset(&act.sa_mask);
+ sigaction(SIGINT, &act, &oldact);
+
+#ifdef HAVE_LIBREADLINE
+ if (is_interactive)
+ rl_callback_handler_install(prompt, reply_linehandler);
+#endif
+ errno = 0;
+ reply_running = 1;
do {
- fputs(prompt, stdout);
- fflush(stdout);
+ int rc;
- if (!fgets(buf, bufsz, stdin)) {
- if (fdisk_label_is_changed(fdisk_get_label(cxt, NULL))) {
- fprintf(stderr, _("\nDo you really want to quit? "));
+ *buf = '\0';
+#ifdef HAVE_LIBREADLINE
+ if (!is_interactive)
+#endif
+ {
+ fputs(prompt, stdout);
+ fflush(stdout);
+ }
- if (fgets(buf, bufsz, stdin) && !rpmatch(buf))
- continue;
+ rc = poll(fds, 1, -1);
+ if (rc == -1 && errno == EINTR) { /* interrupted by signal */
+ DBG(ASK, ul_debug("cancel by CTRL+C"));
+ ret = -ECANCELED;
+ goto done;
+ }
+ if (rc == -1 && errno != EAGAIN) { /* error */
+ ret = -errno;
+ goto done;
+ }
+#ifdef HAVE_LIBREADLINE
+ if (is_interactive) {
+ /* read input and copy to buf[] */
+ rl_callback_read_char();
+ if (!reply_running && reply_line) {
+ sz = strlen(reply_line);
+ if (sz == 0)
+ buf[sz++] = '\n';
+ else
+ memcpy(buf, reply_line, min(sz, bufsz));
+ buf[min(sz, bufsz - 1)] = '\0';
+ free(reply_line);
+ reply_line = NULL;
}
- fdisk_unref_context(cxt);
- exit(EXIT_FAILURE);
} else
+#endif
+ {
+ if (!fgets(buf, bufsz, stdin))
+ *buf = '\0';
break;
- } while (1);
+ }
+ } while (reply_running);
- for (p = buf; *p && !isgraph(*p); p++); /* get first non-blank */
+ if (!*buf) {
+ DBG(ASK, ul_debug("cancel by CTRL+D"));
+ ret = -ECANCELED;
+ clearerr(stdin);
+ goto done;
+ }
- if (p > buf)
- memmove(buf, p, p - buf); /* remove blank space */
- sz = strlen(buf);
+ /*
+ * cleanup the reply
+ */
+ sz = ltrim_whitespace((unsigned char *) buf);
if (sz && *(buf + sz - 1) == '\n')
*(buf + sz - 1) = '\0';
- DBG(ASK, ul_debug("user's reply: >>>%s<<<", buf));
- return 0;
+done:
+#ifdef HAVE_LIBREADLINE
+ if (is_interactive)
+ rl_callback_handler_remove();
+#endif
+ sigaction(SIGINT, &oldact, NULL);
+ DBG(ASK, ul_debug("user's reply: >>>%s<<< [rc=%d]", buf, ret));
+ return ret;
}
static int ask_menu(struct fdisk_context *cxt, struct fdisk_ask *ask,
do {
char prompt[128];
- int key, c;
+ int key, c, rc;
const char *name, *desc;
size_t i = 0;
/* ask for key */
snprintf(prompt, sizeof(prompt), _("Select (default %c): "), dft);
- get_user_reply(cxt, prompt, buf, bufsz);
+ rc = get_user_reply(prompt, buf, bufsz);
+ if (rc)
+ return rc;
if (!*buf) {
fdisk_info(cxt, _("Using default response %c."), dft);
c = dft;
assert(q);
DBG(ASK, ul_debug("asking for number "
- "['%s', <%ju,%ju>, default=%ju, range: %s]",
+ "['%s', <%"PRIu64",%"PRIu64">, default=%"PRIu64", range: %s]",
q, low, high, dflt, range));
if (range && dflt >= low && dflt <= high) {
snprintf(prompt, sizeof(prompt), _("%s (%s, default %c): "),
q, range, tochar(dflt));
else
- snprintf(prompt, sizeof(prompt), _("%s (%s, default %ju): "),
+ snprintf(prompt, sizeof(prompt), _("%s (%s, default %"PRIu64"): "),
q, range, dflt);
} else if (dflt >= low && dflt <= high) {
snprintf(prompt, sizeof(prompt), _("%s (%c-%c, default %c): "),
q, tochar(low), tochar(high), tochar(dflt));
else
- snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju, default %ju): "),
+ snprintf(prompt, sizeof(prompt),
+ _("%s (%"PRIu64"-%"PRIu64", default %"PRIu64"): "),
q, low, high, dflt);
} else if (inchar)
snprintf(prompt, sizeof(prompt), _("%s (%c-%c): "),
q, tochar(low), tochar(high));
else
- snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju): "),
+ snprintf(prompt, sizeof(prompt), _("%s (%"PRIu64"-%"PRIu64"): "),
q, low, high);
do {
- int rc = get_user_reply(cxt, prompt, buf, bufsz);
- uint64_t num;
+ int rc = get_user_reply(prompt, buf, bufsz);
+ uint64_t num = 0;
if (rc)
return rc;
assert(q);
- DBG(ASK, ul_debug("asking for offset ['%s', <%ju,%ju>, base=%ju, default=%ju, range: %s]",
+ DBG(ASK, ul_debug("asking for offset ['%s', <%"PRIu64",%"PRIu64">, base=%"PRIu64", default=%"PRIu64", range: %s]",
q, low, high, base, dflt, range));
if (range && dflt >= low && dflt <= high)
- snprintf(prompt, sizeof(prompt), _("%s (%s, default %ju): "), q, range, dflt);
+ snprintf(prompt, sizeof(prompt), _("%s (%s, default %"PRIu64"): "),
+ q, range, dflt);
else if (dflt >= low && dflt <= high)
- snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju, default %ju): "), q, low, high, dflt);
+ snprintf(prompt, sizeof(prompt),
+ _("%s (%"PRIu64"-%"PRIu64", default %"PRIu64"): "),
+ q, low, high, dflt);
else
- snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju): "), q, low, high);
+ snprintf(prompt, sizeof(prompt), _("%s (%"PRIu64"-%"PRIu64"): "),
+ q, low, high);
do {
- uint64_t num = 0;
+ uintmax_t num = 0;
char sig = 0, *p;
int pwr = 0;
- int rc = get_user_reply(cxt, prompt, buf, bufsz);
+ int rc = get_user_reply(prompt, buf, bufsz);
if (rc)
return rc;
if (!*buf && dflt >= low && dflt <= high)
}
if (sig == '+')
num += base;
+ else if (sig == '-' && fdisk_ask_number_is_wrap_negative(ask))
+ num = high - num;
else if (sig == '-')
num = base - num;
num, sig, pwr,
sig ? "relative" : "absolute"));
if (num >= low && num <= high) {
- if (sig)
+ if (sig && pwr)
fdisk_ask_number_set_relative(ask, 1);
- return fdisk_ask_number_set_result(ask, num);
+ return fdisk_ask_number_set_result(ask, (uint64_t)num);
}
fdisk_warnx(cxt, _("Value out of range."));
} while (1);
void *data __attribute__((__unused__)))
{
int rc = 0;
- char buf[BUFSIZ];
+ char buf[BUFSIZ] = { '\0' };
assert(cxt);
assert(ask);
fputs_info(ask, stdout);
break;
case FDISK_ASKTYPE_WARNX:
+ fflush(stdout);
color_scheme_fenable("warn", UL_COLOR_RED, stderr);
fputs(fdisk_ask_print_get_mesg(ask), stderr);
color_fdisable(stderr);
fputc('\n', stderr);
break;
case FDISK_ASKTYPE_WARN:
+ fflush(stdout);
color_scheme_fenable("warn", UL_COLOR_RED, stderr);
fputs(fdisk_ask_print_get_mesg(ask), stderr);
errno = fdisk_ask_print_get_errno(ask);
do {
int x;
fputs(fdisk_ask_get_query(ask), stdout);
- rc = get_user_reply(cxt, _(" [Y]es/[N]o: "), buf, sizeof(buf));
+ rc = get_user_reply(_(" [Y]es/[N]o: "), buf, sizeof(buf));
if (rc)
break;
x = rpmatch(buf);
- if (x == 1 || x == 0) {
+ if (x == RPMATCH_YES || x == RPMATCH_NO) {
fdisk_ask_yesno_set_result(ask, x);
break;
}
char prmt[BUFSIZ];
snprintf(prmt, sizeof(prmt), "%s: ", fdisk_ask_get_query(ask));
fputc('\n', stdout);
- rc = get_user_reply(cxt, prmt, buf, sizeof(buf));
+ rc = get_user_reply(prmt, buf, sizeof(buf));
if (rc == 0)
fdisk_ask_string_set_result(ask, xstrdup(buf));
DBG(ASK, ul_debug("string ask: reply '%s' [rc=%d]", buf, rc));
return rc;
}
-struct fdisk_parttype *ask_partition_type(struct fdisk_context *cxt)
+static struct fdisk_parttype *ask_partition_type(struct fdisk_context *cxt, int *canceled)
{
const char *q;
struct fdisk_label *lb;
if (!lb)
return NULL;
+ *canceled = 0;
q = fdisk_label_has_code_parttypes(lb) ?
- _("Partition type (type L to list all types): ") :
- _("Hex code (type L to list all codes): ");
+ _("Hex code (type L to list all codes): ") :
+ _("Partition type (type L to list all types): ");
do {
- char buf[256];
- int rc = get_user_reply(cxt, q, buf, sizeof(buf));
+ char buf[256] = { '\0' };
+ int rc = get_user_reply(q, buf, sizeof(buf));
- if (rc)
+ if (rc) {
+ if (rc == -ECANCELED)
+ *canceled = 1;
break;
+ }
if (buf[1] == '\0' && toupper(*buf) == 'L')
list_partition_types(cxt);
- else if (*buf)
- return fdisk_label_parse_parttype(lb, buf);
+ else if (*buf) {
+ struct fdisk_parttype *t = fdisk_label_parse_parttype(lb, buf);
+
+ if (!t)
+ fdisk_info(cxt, _("Failed to parse '%s' partition type."), buf);
+ return t;
+ }
} while (1);
return NULL;
}
+
void list_partition_types(struct fdisk_context *cxt)
{
size_t ntypes = 0;
- struct fdisk_label *lb = fdisk_get_label(cxt, NULL);
+ struct fdisk_label *lb;
assert(cxt);
lb = fdisk_get_label(cxt, NULL);
*/
size_t i;
+ pager_open();
+
for (i = 0; i < ntypes; i++) {
const struct fdisk_parttype *t = fdisk_label_get_parttype(lb, i);
printf("%3zu %-30s %s\n", i + 1,
fdisk_parttype_get_name(t),
fdisk_parttype_get_string(t));
}
+
+ pager_close();
}
putchar('\n');
}
struct fdisk_parttype *t = NULL;
struct fdisk_partition *pa = NULL;
const char *old = NULL;
+ int canceled = 0;
assert(cxt);
old = t ? fdisk_parttype_get_name(t) : _("Unknown");
do {
- t = ask_partition_type(cxt);
+ t = ask_partition_type(cxt, &canceled);
+ if (canceled)
+ break;
} while (!t);
- if (fdisk_set_partition_type(cxt, i, t) == 0)
- fdisk_sinfo(cxt, FDISK_INFO_SUCCESS,
+ if (canceled == 0 && t && fdisk_set_partition_type(cxt, i, t) == 0)
+ fdisk_info(cxt,
_("Changed type of partition '%s' to '%s'."),
old, t ? fdisk_parttype_get_name(t) : _("Unknown"));
else
i + 1, old);
fdisk_unref_partition(pa);
+ fdisk_unref_parttype(t);
+}
+
+int print_partition_info(struct fdisk_context *cxt)
+{
+ struct fdisk_partition *pa = NULL;
+ int rc = 0;
+ size_t i, nfields;
+ int *fields = NULL;
+ struct fdisk_label *lb = fdisk_get_label(cxt, NULL);
+
+ if ((rc = fdisk_ask_partnum(cxt, &i, FALSE)))
+ return rc;
+
+ if ((rc = fdisk_get_partition(cxt, i, &pa))) {
+ fdisk_warnx(cxt, _("Partition %zu does not exist yet!"), i + 1);
+ return rc;
+ }
+
+ if ((rc = fdisk_label_get_fields_ids_all(lb, cxt, &fields, &nfields)))
+ goto clean_data;
+
+ for (i = 0; i < nfields; ++i) {
+ int id = fields[i];
+ char *data = NULL;
+ const struct fdisk_field *fd = fdisk_label_get_field(lb, id);
+
+ if (!fd)
+ continue;
+
+ rc = fdisk_partition_to_string(pa, cxt, id, &data);
+ if (rc < 0)
+ goto clean_data;
+ if (!data || !*data)
+ continue;
+ fdisk_info(cxt, "%15s: %s", fdisk_field_get_name(fd), data);
+ free(data);
+ }
+
+clean_data:
+ fdisk_unref_partition(pa);
+ free(fields);
+ return rc;
}
static size_t skip_empty(const unsigned char *buf, size_t i, size_t sz)
if (l == 0) {
if (all == 0 && !next)
next = skip_empty(buf, i, sz);
- printf("%08jx ", base + i);
+ printf("%08jx ", (intmax_t)base + i);
}
printf(" %02x", buf[i]);
if (l == 7) /* words separator */
}
static void dump_blkdev(struct fdisk_context *cxt, const char *name,
- off_t offset, size_t size, int all)
+ uint64_t offset, size_t size, int all)
{
int fd = fdisk_get_devfd(cxt);
- fdisk_info(cxt, _("\n%s: offset = %ju, size = %zu bytes."),
+ fdisk_info(cxt, _("\n%s: offset = %"PRIu64", size = %zu bytes."),
name, offset, size);
assert(fd >= 0);
- if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
+ if (lseek(fd, (off_t) offset, SEEK_SET) == (off_t) -1)
fdisk_warn(cxt, _("cannot seek"));
else {
unsigned char *buf = xmalloc(size);
int all = !isatty(STDOUT_FILENO);
int i = 0;
const char *name = NULL;
- off_t offset = 0;
+ uint64_t offset = 0;
size_t size = 0;
assert(cxt);
dump_blkdev(cxt, name, offset, size, all);
}
-static sector_t get_dev_blocks(char *dev)
+static fdisk_sector_t get_dev_blocks(char *dev)
{
int fd, ret;
- sector_t size;
+ fdisk_sector_t size;
if ((fd = open(dev, O_RDONLY)) < 0)
err(EXIT_FAILURE, _("cannot open %s"), dev);
- ret = blkdev_get_sectors(fd, &size);
+ ret = blkdev_get_sectors(fd, (unsigned long long *) &size);
close(fd);
if (ret < 0)
err(EXIT_FAILURE, _("BLKGETSIZE ioctl failed on %s"), dev);
return size/2;
}
-static void __attribute__ ((__noreturn__)) usage(FILE *out)
+
+void follow_wipe_mode(struct fdisk_context *cxt)
{
+ int dowipe = wipemode == WIPEMODE_ALWAYS ? 1 : 0;
+
+ if (isatty(STDIN_FILENO) && wipemode == WIPEMODE_AUTO)
+ dowipe = 1; /* do it in interactive mode */
+
+ if (fdisk_is_ptcollision(cxt) && wipemode != WIPEMODE_NEVER)
+ dowipe = 1; /* always remove old PT */
+
+ fdisk_enable_wipe(cxt, dowipe);
+ if (dowipe)
+ fdisk_warnx(cxt, _(
+ "The device contains '%s' signature and it will be removed by a write command. "
+ "See fdisk(8) man page and --wipe option for more details."),
+ fdisk_get_collision(cxt));
+ else
+ fdisk_warnx(cxt, _(
+ "The device contains '%s' signature and it may remain on the device. "
+ "It is recommended to wipe the device with wipefs(8) or "
+ "fdisk --wipe, in order to avoid possible collisions."),
+ fdisk_get_collision(cxt));
+}
+
+static void __attribute__((__noreturn__)) usage(void)
+{
+ FILE *out = stdout;
+
fputs(USAGE_HEADER, out);
fprintf(out,
" %1$s [options] -l [<disk>] list partition table(s)\n"),
program_invocation_short_name);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(_("Display or manipulate a disk partition table.\n"), out);
+
fputs(USAGE_OPTIONS, out);
fputs(_(" -b, --sector-size <size> physical and logical sector size\n"), out);
+ fputs(_(" -B, --protect-boot don't erase bootbits when creating a new label\n"), out);
fputs(_(" -c, --compatibility[=<mode>] mode is 'dos' or 'nondos' (default)\n"), out);
- fputs(_(" -L, --color[=<when>] colorize output (auto, always or never)\n"), out);
- fputs(_(" -l, --list display partitions end exit\n"), out);
+ fprintf(out,
+ _(" -L, --color[=<when>] colorize output (%s, %s or %s)\n"), "auto", "always", "never");
+ fprintf(out,
+ " %s\n", USAGE_COLORS_DEFAULT);
+ fputs(_(" -l, --list display partitions and exit\n"), out);
+ fputs(_(" -o, --output <list> output columns\n"), out);
fputs(_(" -t, --type <type> recognize specified partition table type only\n"), out);
fputs(_(" -u, --units[=<unit>] display units: 'cylinders' or 'sectors' (default)\n"), out);
fputs(_(" -s, --getsz display device size in 512-byte sectors [DEPRECATED]\n"), out);
+ fputs(_(" --bytes print SIZE in bytes rather than in human readable format\n"), out);
+ fprintf(out,
+ _(" -w, --wipe <mode> wipe signatures (%s, %s or %s)\n"), "auto", "always", "never");
+ fprintf(out,
+ _(" -W, --wipe-partitions <mode> wipe signatures from new partitions (%s, %s or %s)\n"), "auto", "always", "never");
fputs(USAGE_SEPARATOR, out);
fputs(_(" -C, --cylinders <number> specify the number of cylinders\n"), out);
fputs(_(" -S, --sectors <number> specify the number of sectors per track\n"), out);
fputs(USAGE_SEPARATOR, out);
- fputs(USAGE_HELP, out);
- fputs(USAGE_VERSION, out);
+ printf(USAGE_HELP_OPTIONS(31));
list_available_columns(out);
- fprintf(out, USAGE_MAN_TAIL("fdisk(8)"));
- exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+ printf(USAGE_MAN_TAIL("fdisk(8)"));
+ exit(EXIT_SUCCESS);
}
int colormode = UL_COLORMODE_UNDEF;
struct fdisk_context *cxt;
char *outarg = NULL;
-
+ enum {
+ OPT_BYTES = CHAR_MAX + 1
+ };
static const struct option longopts[] = {
+ { "bytes", no_argument, NULL, OPT_BYTES },
{ "color", optional_argument, NULL, 'L' },
{ "compatibility", optional_argument, NULL, 'c' },
{ "cylinders", required_argument, NULL, 'C' },
{ "type", required_argument, NULL, 't' },
{ "units", optional_argument, NULL, 'u' },
{ "version", no_argument, NULL, 'V' },
+ { "output", no_argument, NULL, 'o' },
+ { "protect-boot", no_argument, NULL, 'B' },
+ { "wipe", required_argument, NULL, 'w' },
+ { "wipe-partitions",required_argument, NULL, 'W' },
{ NULL, 0, NULL, 0 }
};
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- atexit(close_stdout);
+ close_stdout_atexit();
fdisk_init_debug(0);
+ scols_init_debug(0);
fdiskprog_init_debug();
cxt = fdisk_new_context();
fdisk_set_ask(cxt, ask_callback, NULL);
- while ((c = getopt_long(argc, argv, "b:c::C:hH:lL::o:sS:t:u::vV",
+ while ((c = getopt_long(argc, argv, "b:Bc::C:hH:lL::o:sS:t:u::vVw:W:",
longopts, NULL)) != -1) {
switch (c) {
case 'b':
size_t sz = strtou32_or_err(optarg,
_("invalid sector size argument"));
if (sz != 512 && sz != 1024 && sz != 2048 && sz != 4096)
- usage(stderr);
+ errx(EXIT_FAILURE, _("invalid sector size argument"));
fdisk_save_user_sector_size(cxt, sz, sz);
break;
}
+ case 'B':
+ fdisk_enable_bootbits_protection(cxt, 1);
+ break;
case 'C':
fdisk_save_user_geometry(cxt,
strtou32_or_err(optarg,
fdisk_dos_enable_compatible(lb, TRUE);
else if (strcmp(p, "nondos") == 0)
fdisk_dos_enable_compatible(lb, FALSE);
- else {
- warnx(_("unknown compatibility mode '%s'"), p);
- usage(stderr);
- }
+ else
+ errx(EXIT_FAILURE, _("unknown compatibility mode '%s'"), p);
}
/* use default if no optarg specified */
break;
act = ACT_LIST;
break;
case 'L':
+ colormode = UL_COLORMODE_AUTO;
if (optarg)
colormode = colormode_or_err(optarg,
_("unsupported color mode"));
if (!lb)
errx(EXIT_FAILURE, _("unsupported disklabel: %s"), optarg);
fdisk_label_set_disabled(lb, 0);
+ break;
}
case 'u':
if (optarg && *optarg == '=')
optarg++;
if (fdisk_set_unit(cxt, optarg) != 0)
- usage(stderr);
+ errx(EXIT_FAILURE, _("unsupported unit"));
break;
case 'V': /* preferred for util-linux */
case 'v': /* for backward compatibility only */
- printf(UTIL_LINUX_VERSION);
- return EXIT_SUCCESS;
+ print_version(EXIT_SUCCESS);
+ case 'w':
+ wipemode = wipemode_from_string(optarg);
+ if (wipemode < 0)
+ errx(EXIT_FAILURE, _("unsupported wipe mode"));
+ break;
+ case 'W':
+ pwipemode = wipemode_from_string(optarg);
+ if (pwipemode < 0)
+ errx(EXIT_FAILURE, _("unsupported wipe mode"));
+ break;
case 'h':
- usage(stdout);
+ usage();
+ case OPT_BYTES:
+ fdisk_set_size_unit(cxt, FDISK_SIZEUNIT_BYTES);
+ break;
default:
- usage(stderr);
+ errtryhelp(EXIT_FAILURE);
}
}
" be used with one specified device only."));
colors_init(colormode, "fdisk");
+ is_interactive = isatty(STDIN_FILENO);
switch (act) {
case ACT_LIST:
if (argc > optind) {
int k;
- for (k = optind; k < argc; k++)
- print_device_pt(cxt, argv[k], 1, 0);
+ int ct = 0;
+
+ for (rc = 0, k = optind; k < argc; k++) {
+ if (ct)
+ fputs("\n\n", stdout);
+
+ rc += print_device_pt(cxt, argv[k], 1, 0);
+ ct++;
+ }
+ if (rc)
+ return EXIT_FAILURE;
} else
print_all_devices_pt(cxt, 0);
break;
case ACT_SHOWSIZE:
/* deprecated */
- if (argc - optind <= 0)
- usage(stderr);
-
+ if (argc - optind <= 0) {
+ warnx(_("bad usage"));
+ errtryhelp(EXIT_FAILURE);
+ }
for (i = optind; i < argc; i++) {
+ uintmax_t blks = get_dev_blocks(argv[i]);
+
if (argc - optind == 1)
- printf("%llu\n", get_dev_blocks(argv[i]));
+ printf("%ju\n", blks);
else
- printf("%s: %llu\n", argv[i], get_dev_blocks(argv[i]));
+ printf("%s: %ju\n", argv[i], blks);
}
break;
case ACT_FDISK:
- if (argc-optind != 1)
- usage(stderr);
+ if (argc-optind != 1) {
+ warnx(_("bad usage"));
+ errtryhelp(EXIT_FAILURE);
+ }
/* Here starts interactive mode, use fdisk_{warn,info,..} functions */
color_scheme_enable("welcome", UL_COLOR_GREEN);
if (rc == -EACCES) {
rc = fdisk_assign_device(cxt, argv[optind], 1);
if (rc == 0)
- fdisk_warnx(cxt, _("Device open in read-only mode."));
+ fdisk_warnx(cxt, _("Device is open in read-only mode."));
}
if (rc)
err(EXIT_FAILURE, _("cannot open %s"), argv[optind]);
fflush(stdout);
+ if (fdisk_get_collision(cxt))
+ follow_wipe_mode(cxt);
+
if (!fdisk_has_label(cxt)) {
fdisk_info(cxt, _("Device does not contain a recognized partition table."));
fdisk_create_disklabel(cxt, NULL);
init_fields(cxt, outarg, NULL); /* -o <columns> */
+ if (!fdisk_is_readonly(cxt)) {
+ fdisk_get_partitions(cxt, &original_layout);
+ device_is_used = fdisk_device_is_used(cxt);
+ }
+
while (1)
process_fdisk_menu(&cxt);
}