]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - disk-utils/cfdisk.c
misc: cosmetics, remove argument from usage(FILE*)
[thirdparty/util-linux.git] / disk-utils / cfdisk.c
index 5e46136950cfc7924b0d226f7f001edae578610c..e17bc916713f1b0fb37f9a687ae546663df0c16c 100644 (file)
 #include <sys/ioctl.h>
 #include <libfdisk.h>
 
-#ifdef HAVE_LIBBLKID
-# include <blkid.h>    /* keep it optional */
-#endif
-
 #ifdef HAVE_LIBMOUNT
 # include <libmount.h> /* keep it optional for non-linux systems */
 #endif
 #include "strutils.h"
 #include "xalloc.h"
 #include "mbsalign.h"
+#include "mbsedit.h"
 #include "colors.h"
 #include "debug.h"
 #include "list.h"
 
+static const char *default_disks[] = {
 #ifdef __GNU__
-# define DEFAULT_DEVICE "/dev/hd0"
-# define ALTERNATE_DEVICE "/dev/sd0"
+               "/dev/hd0",
+               "/dev/sd0",
 #elif defined(__FreeBSD__)
-# define DEFAULT_DEVICE "/dev/ad0"
-# define ALTERNATE_DEVICE "/dev/da0"
+               "/dev/ad0",
+               "/dev/da0",
 #else
-# define DEFAULT_DEVICE "/dev/sda"
-# define ALTERNATE_DEVICE "/dev/hda"
+               "/dev/sda",
+               "/dev/vda",
+               "/dev/hda",
 #endif
+};
 
 #define ARROW_CURSOR_STRING    ">>  "
 #define ARROW_CURSOR_DUMMY     "    "
@@ -94,7 +94,7 @@
 #define MENU_H_POSTSTR_SZ      (sizeof(MENU_H_POSTSTR) - 1)
 
 #define TABLE_START_LINE       4
-#define MENU_START_LINE                (ui_lines - 5)
+#define MENU_START_LINE                (ui_lines - 4)          /* The menu maybe use two lines */
 #define INFO_LINE              (ui_lines - 2)
 #define WARN_LINE              INFO_LINE
 #define HINT_LINE              (ui_lines - 1)
 #ifndef KEY_DELETE
 # define KEY_DELETE    '\177'
 #endif
+#ifndef KEY_DC
+# define KEY_DC                0423
+#endif
+
 
 /* colors */
 enum {
@@ -146,8 +150,8 @@ static int ui_resize;
 
 /* ncurses LINES and COLS may be actual variables or *macros*, but we need
  * something portable and writable */
-size_t ui_lines;
-size_t ui_cols;
+static size_t ui_lines;
+static size_t ui_cols;
 
 /* menu item */
 struct cfdisk_menuitem {
@@ -180,7 +184,7 @@ static struct cfdisk_menuitem main_menuitems[] = {
        { 'b', N_("Bootable"), N_("Toggle bootable flag of the current partition") },
        { 'd', N_("Delete"), N_("Delete the current partition") },
        { 'n', N_("New"), N_("Create new partition from free space") },
-       { 'q', N_("Quit"), N_("Quit program without writing partition table") },
+       { 'q', N_("Quit"), N_("Quit program without writing changes") },
        { 't', N_("Type"), N_("Change the partition type") },
        { 'h', N_("Help"), N_("Print help screen") },
        { 's', N_("Sort"), N_("Fix partitions order") },
@@ -241,7 +245,7 @@ struct cfdisk {
 /*
  * let's use include/debug.h stuff for cfdisk too
  */
-UL_DEBUG_DEFINE_MASK(cfdisk);
+static UL_DEBUG_DEFINE_MASK(cfdisk);
 UL_DEBUG_DEFINE_MASKNAMES(cfdisk) = UL_DEBUG_EMPTY_MASKNAMES;
 
 #define CFDISK_DEBUG_INIT      (1 << 1)
@@ -319,7 +323,7 @@ static char *table_to_string(struct cfdisk *cf, struct fdisk_table *tb)
 {
        struct fdisk_partition *pa;
        struct fdisk_label *lb;
-       struct fdisk_iter *itr = NULL;
+       struct fdisk_iter *itr;
        struct libscols_table *table = NULL;
        struct libscols_iter *s_itr = NULL;
        char *res = NULL;
@@ -354,6 +358,11 @@ static char *table_to_string(struct cfdisk *cf, struct fdisk_table *tb)
        if (!table)
                goto done;
        scols_table_enable_maxout(table, 1);
+       scols_table_enable_nowrap(table, 1);
+
+#if !defined(HAVE_LIBNCURSESW) || !defined(HAVE_WIDECHAR)
+       scols_table_enable_ascii(table, 1);
+#endif
 
        /* headers */
        for (i = 0; i < cf->nfields; i++) {
@@ -532,7 +541,7 @@ static int is_freespace(struct cfdisk *cf, size_t i)
 }
 
 /* converts libfdisk FDISK_ASKTYPE_MENU to cfdisk menu and returns user's
- * responseback to libfdisk
+ * response back to libfdisk
  */
 static int ask_menu(struct fdisk_ask *ask, struct cfdisk *cf)
 {
@@ -591,12 +600,12 @@ static int ask_menu(struct fdisk_ask *ask, struct cfdisk *cf)
 
 /* libfdisk callback
  */
-static int ask_callback(struct fdisk_context *cxt, struct fdisk_ask *ask,
-                   void *data __attribute__((__unused__)))
+static int ask_callback(struct fdisk_context *cxt __attribute__((__unused__)),
+                       struct fdisk_ask *ask,
+                       void *data __attribute__((__unused__)))
 {
        int rc = 0;
 
-       assert(cxt);
        assert(ask);
 
        switch(fdisk_ask_get_type(ask)) {
@@ -1040,9 +1049,10 @@ static void ui_draw_menuitem(struct cfdisk *cf,
                             struct cfdisk_menuitem *d,
                             size_t idx)
 {
-       char buf[80 * MB_CUR_MAX], *ptr = buf;
+       char *buf, *ptr;
        const char *name;
        size_t width;
+       const size_t buf_sz = 80 * MB_CUR_MAX;
        int ln, cl, vert = cf->menu->vertical;
 
        if (!menuitem_on_page(cf, idx))
@@ -1050,6 +1060,7 @@ static void ui_draw_menuitem(struct cfdisk *cf,
        ln = menuitem_get_line(cf, idx);
        cl = menuitem_get_column(cf, idx);
 
+       ptr = buf = xmalloc(buf_sz);
        /* string width */
        if (vert) {
                width = cf->menu->width + MENU_V_SPADDING;
@@ -1059,7 +1070,7 @@ static void ui_draw_menuitem(struct cfdisk *cf,
                width = MENU_H_SPADDING + cf->menu->width + MENU_H_SPADDING;
 
        name = _(d->name);
-       mbsalign(name, ptr, sizeof(buf), &width,
+       mbsalign(name, ptr, buf_sz, &width,
                        vert ? MBS_ALIGN_LEFT : MBS_ALIGN_CENTER,
                        0);
 
@@ -1078,6 +1089,7 @@ static void ui_draw_menuitem(struct cfdisk *cf,
                mvprintw(ln, cl, "%s", buf);
        else
                mvprintw(ln, cl, "%s%s%s", MENU_H_PRESTR, buf, MENU_H_POSTSTR);
+       free(buf);
 
        if (cf->menu->idx == idx) {
                standend();
@@ -1178,6 +1190,7 @@ static void ui_draw_menu(struct cfdisk *cf)
 inline static int extra_insert_pair(struct cfdisk_line *l, const char *name, const char *data)
 {
        struct libscols_line *lsl;
+       int rc;
 
        assert(l);
        assert(l->extra);
@@ -1189,22 +1202,31 @@ inline static int extra_insert_pair(struct cfdisk_line *l, const char *name, con
        if (!lsl)
                return -ENOMEM;
 
-       scols_line_set_data(lsl, 0, name);
-       scols_line_set_data(lsl, 1, data);
+       rc = scols_line_set_data(lsl, 0, name);
+       if (!rc)
+               rc = scols_line_set_data(lsl, 1, data);
 
-       return 0;
+       return rc;
 }
 
-#ifdef HAVE_LIBMOUNT
-static char *get_mountpoint(struct cfdisk *cf, const char *uuid, const char *label)
+#ifndef HAVE_LIBMOUNT
+static char *get_mountpoint(   struct cfdisk *cf __attribute__((unused)),
+                               const char *tagname __attribute__((unused)),
+                               const char *tagdata __attribute__((unused)))
+{
+       return NULL;
+}
+#else
+static char *get_mountpoint(struct cfdisk *cf, const char *tagname, const char *tagdata)
 {
        struct libmnt_fs *fs = NULL;
        char *target = NULL;
        int mounted = 0;
 
-       assert(uuid || label);
+       assert(tagname);
+       assert(tagdata);
 
-       DBG(UI, ul_debug("asking for mountpoint [uuid=%s, label=%s]", uuid, label));
+       DBG(UI, ul_debug("asking for mountpoint [%s=%s]", tagname, tagdata));
 
        if (!cf->mntcache)
                cf->mntcache = mnt_new_cache();
@@ -1219,9 +1241,7 @@ static char *get_mountpoint(struct cfdisk *cf, const char *uuid, const char *lab
        }
 
        if (cf->mtab)
-               fs = mnt_table_find_tag(cf->mtab,
-                                       uuid ? "UUID" : "LABEL",
-                                       uuid ? : label, MNT_ITER_FORWARD);
+               fs = mnt_table_find_tag(cf->mtab, tagname, tagdata, MNT_ITER_FORWARD);
 
        /* 2nd try fstab */
        if (!fs) {
@@ -1233,9 +1253,7 @@ static char *get_mountpoint(struct cfdisk *cf, const char *uuid, const char *lab
                        }
                }
                if (cf->fstab)
-                       fs = mnt_table_find_tag(cf->fstab,
-                                       uuid ? "UUID" : "LABEL",
-                                       uuid ? : label, MNT_ITER_FORWARD);
+                       fs = mnt_table_find_tag(cf->fstab, tagname, tagdata, MNT_ITER_FORWARD);
        } else
                mounted = 1;
 
@@ -1255,18 +1273,22 @@ static void extra_prepare_data(struct cfdisk *cf)
        struct fdisk_partition *pa = get_current_partition(cf);
        struct cfdisk_line *l = &cf->lines[cf->lines_idx];
        char *data = NULL;
-       char *devuuid = NULL, *devlabel = NULL;
+       char *mountpoint = NULL;
 
        DBG(UI, ul_debug("preparing extra data"));
 
        /* string data should not equal an empty string */
        if (!fdisk_partition_to_string(pa, cf->cxt, FDISK_FIELD_NAME, &data) && data) {
                extra_insert_pair(l, _("Partition name:"), data);
+               if (!mountpoint)
+                       mountpoint = get_mountpoint(cf, "PARTLABEL", data);
                free(data);
        }
 
        if (!fdisk_partition_to_string(pa, cf->cxt, FDISK_FIELD_UUID, &data) && data) {
                extra_insert_pair(l, _("Partition UUID:"), data);
+               if (!mountpoint)
+                       mountpoint = get_mountpoint(cf, "PARTUUID", data);
                free(data);
        }
 
@@ -1306,62 +1328,28 @@ static void extra_prepare_data(struct cfdisk *cf)
                free(data);
        }
 
-       if (!fdisk_partition_to_string(pa, cf->cxt, FDISK_FIELD_SADDR, &data) && data) {
-               extra_insert_pair(l, _("Start C/H/S:"), data);
+       if (!fdisk_partition_to_string(pa, cf->cxt, FDISK_FIELD_FSUUID, &data) && data) {
+               extra_insert_pair(l, _("Filesystem UUID:"), data);
+               if (!mountpoint)
+                       mountpoint = get_mountpoint(cf, "UUID", data);
                free(data);
        }
 
-       if (!fdisk_partition_to_string(pa, cf->cxt, FDISK_FIELD_EADDR, &data) && data) {
-               extra_insert_pair(l, _("End C/H/S:"), data);
+       if (!fdisk_partition_to_string(pa, cf->cxt, FDISK_FIELD_FSLABEL, &data) && data) {
+               extra_insert_pair(l, _("Filesystem LABEL:"), data);
+               if (!mountpoint)
+                       mountpoint = get_mountpoint(cf, "LABEL", data);
                free(data);
        }
-
-#ifdef HAVE_LIBBLKID
-       if (fdisk_partition_has_start(pa) && fdisk_partition_has_size(pa)) {
-               int fd;
-               uintmax_t start, size;
-               blkid_probe pr = blkid_new_probe();
-
-               if (!pr)
-                       goto done;
-
-               DBG(UI, ul_debug("blkid prober: %p", pr));
-
-               start = fdisk_partition_get_start(pa) * fdisk_get_sector_size(cf->cxt);
-               size = fdisk_partition_get_size(pa) * fdisk_get_sector_size(cf->cxt);
-               fd = fdisk_get_devfd(cf->cxt);
-
-               if (blkid_probe_set_device(pr, fd, start, size) == 0 &&
-                   blkid_do_fullprobe(pr) == 0) {
-                       const char *bdata = NULL;
-
-                       if (!blkid_probe_lookup_value(pr, "TYPE", &bdata, NULL))
-                               extra_insert_pair(l, _("Filesystem:"), bdata);
-                       if (!blkid_probe_lookup_value(pr, "LABEL", &bdata, NULL)) {
-                               extra_insert_pair(l, _("Filesystem label:"), bdata);
-                               devlabel = xstrdup(bdata);
-                       }
-                       if (!blkid_probe_lookup_value(pr, "UUID", &bdata, NULL)) {
-                               extra_insert_pair(l, _("Filesystem UUID:"), bdata);
-                               devuuid = xstrdup(bdata);
-                       }
-               }
-               blkid_free_probe(pr);
+       if (!fdisk_partition_to_string(pa, cf->cxt, FDISK_FIELD_FSTYPE, &data) && data) {
+               extra_insert_pair(l, _("Filesystem:"), data);
+               free(data);
        }
-#endif /* HAVE_LIBBLKID */
 
-#ifdef HAVE_LIBMOUNT
-       if (devuuid || devlabel) {
-               data = get_mountpoint(cf, devuuid, devlabel);
-               if (data) {
-                       extra_insert_pair(l, _("Mountpoint:"), data);
-                       free(data);
-               }
+       if (mountpoint) {
+               extra_insert_pair(l, _("Mountpoint:"), mountpoint);
+               free(mountpoint);
        }
-#endif /* HAVE_LIBMOUNT */
-done:
-       free(devlabel);
-       free(devuuid);
 }
 
 static int ui_draw_extra(struct cfdisk *cf)
@@ -1483,7 +1471,7 @@ static int ui_menu_move(struct cfdisk *cf, int key)
        assert(cf);
        assert(cf->menu);
 
-       if (key == ERR)
+       if (key == (int) ERR)
                return 0;       /* ignore errors */
 
        m = cf->menu;
@@ -1537,12 +1525,19 @@ static int ui_menu_move(struct cfdisk *cf, int key)
                }
        }
 
-       return 1;       /* key irrelevant for menu move */
+       if (key == '\014') {            /* ^L refresh */
+               ui_menu_resize(cf);
+               return 0;
+       }
+
+       DBG(MENU, ul_debug(" no menu move key"));
+       return 1;
 }
 
 /* but don't call me from ui_run(), this is for pop-up menus only */
 static void ui_menu_resize(struct cfdisk *cf)
 {
+       DBG(MENU, ul_debug("menu resize/refresh"));
        resize();
        ui_clean_menu(cf);
        menu_refresh_size(cf);
@@ -1712,14 +1707,15 @@ static int ui_refresh(struct cfdisk *cf)
        return 0;
 }
 
-static ssize_t ui_get_string(struct cfdisk *cf, const char *prompt,
+static ssize_t ui_get_string(const char *prompt,
                             const char *hint, char *buf, size_t len)
 {
-       size_t cells = 0;
-       ssize_t i = 0, rc = -1;
        int ln = MENU_START_LINE, cl = 1;
+       ssize_t rc = -1;
+       struct mbs_editor *edit;
+
+       DBG(UI, ul_debug("ui get string"));
 
-       assert(cf);
        assert(buf);
        assert(len);
 
@@ -1734,30 +1730,33 @@ static ssize_t ui_get_string(struct cfdisk *cf, const char *prompt,
                cl += mbs_safe_width(prompt);
        }
 
-       /* default value */
-       if (*buf) {
-               i = strlen(buf);
-               cells = mbs_safe_width(buf);
-               mvaddstr(ln, cl, buf);
-       }
+       edit = mbs_new_edit(buf, len, ui_cols - cl);
+       if (!edit)
+               goto done;
+
+       mbs_edit_goto(edit, MBS_EDIT_END);
 
        if (hint)
                ui_hint(hint);
        else
                ui_clean_hint();
 
-       move(ln, cl + cells);
        curs_set(1);
-       refresh();
 
        while (1) {
+               wint_t c;       /* we have fallback in widechar.h */
+
+               move(ln, cl);
+               clrtoeol();
+               mvaddstr(ln, cl, edit->buf);
+               move(ln, cl + edit->cursor_cells);
+               refresh();
+
 #if !defined(HAVE_SLCURSES_H) && !defined(HAVE_SLANG_SLCURSES_H) && \
     defined(HAVE_LIBNCURSESW) && defined(HAVE_WIDECHAR)
-               wint_t c;
                if (get_wch(&c) == ERR) {
 #else
-               int c;
-               if ((c = getch()) == ERR) {
+               if ((c = getch()) == (wint_t) ERR) {
 #endif
                        if (ui_resize) {
                                resize();
@@ -1768,72 +1767,55 @@ static ssize_t ui_get_string(struct cfdisk *cf, const char *prompt,
                        else
                                goto done;
                }
+
+               DBG(UI, ul_debug("ui get string: key=%lc", c));
+
                if (c == '\r' || c == '\n' || c == KEY_ENTER)
                        break;
 
+               rc = 1;
+
                switch (c) {
                case KEY_ESC:
                        rc = -CFDISK_ERR_ESC;
                        goto done;
-               case KEY_LEFT:          /* TODO: implement full buffer editor */
+               case KEY_LEFT:
+                       rc = mbs_edit_goto(edit, MBS_EDIT_LEFT);
+                       break;
                case KEY_RIGHT:
+                       rc = mbs_edit_goto(edit, MBS_EDIT_RIGHT);
+                       break;
                case KEY_END:
+                       rc = mbs_edit_goto(edit, MBS_EDIT_END);
+                       break;
                case KEY_HOME:
+                       rc = mbs_edit_goto(edit, MBS_EDIT_HOME);
+                       break;
                case KEY_UP:
                case KEY_DOWN:
-                       beep();
                        break;
-               case KEY_DELETE:
+               case KEY_DC:
+                       rc = mbs_edit_delete(edit);
+                       break;
                case '\b':
                case KEY_BACKSPACE:
-                       if (i > 0) {
-                               cells--;
-                               i = mbs_truncate(buf, &cells);
-                               if (i < 0)
-                                       goto done;
-                               mvaddch(ln, cl + cells, ' ');
-                               move(ln, cl + cells);
-                       } else
-                               beep();
+                       rc = mbs_edit_backspace(edit);
                        break;
-
                default:
-#if defined(HAVE_LIBNCURSESW) && defined(HAVE_WIDECHAR)
-                       if (i + 1 < (ssize_t) len && iswprint(c)) {
-                               wchar_t wc = (wchar_t) c;
-                               char s[MB_CUR_MAX + 1];
-                               int sz = wctomb(s, wc);
-
-                               if (sz > 0 && sz + i < (ssize_t) len) {
-                                       s[sz] = '\0';
-                                       mvaddnstr(ln, cl + cells, s, sz);
-                                       memcpy(buf + i, s, sz);
-                                       i += sz;
-                                       buf[i] = '\0';
-                                       cells += wcwidth(wc);
-                               } else
-                                       beep();
-                       }
-#else
-                       if (i + 1 < (ssize_t) len && isprint(c)) {
-                               mvaddch(ln, cl + cells, c);
-                               buf[i++] = c;
-                               buf[i] = '\0';
-                               cells++;
-                       }
-#endif
-                       else
-                               beep();
+                       rc = mbs_edit_insert(edit, c);
+                       break;
                }
-               refresh();
+               if (rc == 1)
+                       beep();
        }
 
-       rc = i;         /* success */
+       rc = strlen(edit->buf);         /* success */
 done:
        move(ln, 0);
        clrtoeol();
        curs_set(0);
        refresh();
+       mbs_free_edit(edit);
 
        return rc;
 }
@@ -1856,7 +1838,7 @@ static int ui_get_size(struct cfdisk *cf, const char *prompt, uintmax_t *res,
        do {
                int pwr = 0, insec = 0;
 
-               rc = ui_get_string(cf, prompt,
+               rc = ui_get_string(prompt,
                                _("May be followed by M for MiB, G for GiB, "
                                  "T for TiB, or S for sectors."),
                                buf, sizeof(buf));
@@ -2005,7 +1987,7 @@ static int ui_script_read(struct cfdisk *cf)
        int rc;
 
        erase();
-       rc = ui_get_string(cf,  _("Enter script file name: "),
+       rc = ui_get_string(     _("Enter script file name: "),
                                _("The script file will be applied to in-memory partition table."),
                                buf, sizeof(buf));
        if (rc <= 0)
@@ -2035,7 +2017,7 @@ static int ui_script_write(struct cfdisk *cf)
        FILE *f = NULL;
        int rc;
 
-       rc = ui_get_string(cf,  _("Enter script file name: "),
+       rc = ui_get_string(     _("Enter script file name: "),
                                _("The current in-memory partition table will be dumped to the file."),
                                buf, sizeof(buf));
        if (rc <= 0)
@@ -2110,6 +2092,8 @@ static int ui_create_label(struct cfdisk *cf)
 
 
        do {
+               int key;
+
                if (refresh_menu) {
                        ui_draw_menu(cf);
                        ui_hint(_("Select a type to create a new label or press 'L' to load script file."));
@@ -2117,7 +2101,7 @@ static int ui_create_label(struct cfdisk *cf)
                        refresh_menu = 0;
                }
 
-               int key = getch();
+               key = getch();
 
                if (ui_resize)
                        ui_menu_resize(cf);
@@ -2182,7 +2166,10 @@ static int ui_help(void)
                N_("Note: All of the commands can be entered with either upper or lower"),
                N_("case letters (except for Write)."),
                "  ",
-               N_("Use lsblk(8) or partx(8) to see more details about the device.")
+               N_("Use lsblk(8) or partx(8) to see more details about the device."),
+               "  ",
+               "  ",
+               "Copyright (C) 2014-2017 Karel Zak <kzak@redhat.com>"
        };
 
        erase();
@@ -2368,7 +2355,7 @@ static int main_menu_action(struct cfdisk *cf, int key)
                        break;
                }
 
-               rc = ui_get_string(cf,
+               rc = ui_get_string(
                          _("Are you sure you want to write the partition "
                            "table to disk? "),
                          _("Type \"yes\" or \"no\", or press ESC to leave this dialog."),
@@ -2415,6 +2402,7 @@ static int main_menu_action(struct cfdisk *cf, int key)
 
 static void ui_resize_refresh(struct cfdisk *cf)
 {
+       DBG(UI, ul_debug("ui resize/refresh"));
        resize();
        menu_refresh_size(cf);
        lines_refresh(cf);
@@ -2443,6 +2431,14 @@ static int ui_run(struct cfdisk *cf)
        ui_cols = COLS;
        DBG(UI, ul_debug("start cols=%zu, lines=%zu", ui_cols, ui_lines));
 
+       if (fdisk_get_collision(cf->cxt)) {
+               ui_warnx(_("Device already contains a %s signature; it will be removed by a write command."),
+                               fdisk_get_collision(cf->cxt));
+               fdisk_enable_wipe(cf->cxt, 1);
+               ui_hint(_("Press a key to continue."));
+               getch();
+       }
+
        if (!fdisk_has_label(cf->cxt) || cf->zero_start) {
                rc = ui_create_label(cf);
                if (rc < 0)
@@ -2468,7 +2464,7 @@ static int ui_run(struct cfdisk *cf)
        ui_draw_extra(cf);
 
        if (fdisk_is_readonly(cf->cxt))
-               ui_warnx(_("Device open in read-only mode."));
+               ui_warnx(_("Device is open in read-only mode."));
        else if (cf->wrong_order)
                ui_info(_("Note that partition table entries are not in disk order now."));
 
@@ -2482,10 +2478,14 @@ static int ui_run(struct cfdisk *cf)
                        ui_resize_refresh(cf);
                if (key == ERR)
                        continue;
+               if (key == '\014') {            /* ^L refresh */
+                       ui_resize_refresh(cf);
+                       continue;
+               }
                if (ui_menu_move(cf, key) == 0)
                        continue;
 
-               DBG(UI, ul_debug("main action key >%c<.", key));
+               DBG(UI, ul_debug("main action key >%1$c< [\\0%1$o].", key));
 
                switch (key) {
                case KEY_DOWN:
@@ -2503,6 +2503,7 @@ static int ui_run(struct cfdisk *cf)
                                ui_table_goto(cf, (int) cf->lines_idx - cf->page_sz);
                                break;
                        }
+                       /* fallthrough */
                case KEY_HOME:
                        ui_table_goto(cf, 0);
                        break;
@@ -2511,6 +2512,7 @@ static int ui_run(struct cfdisk *cf)
                                ui_table_goto(cf, cf->lines_idx + cf->page_sz);
                                break;
                        }
+                       /* fallthrough */
                case KEY_END:
                        ui_table_goto(cf, (int) cf->nlines - 1);
                        break;
@@ -2540,8 +2542,9 @@ static int ui_run(struct cfdisk *cf)
        return 0;
 }
 
-static void __attribute__ ((__noreturn__)) usage(FILE *out)
+static void __attribute__((__noreturn__)) usage(void)
 {
+       FILE *out = stdout;
        fputs(USAGE_HEADER, out);
        fprintf(out,
              _(" %1$s [options] <disk>\n"), program_invocation_short_name);
@@ -2560,12 +2563,12 @@ static void __attribute__ ((__noreturn__)) usage(FILE *out)
        fputs(USAGE_VERSION, out);
 
        fprintf(out, USAGE_MAN_TAIL("cfdisk(8)"));
-       exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+       exit(EXIT_SUCCESS);
 }
 
 int main(int argc, char *argv[])
 {
-       const char *diskpath;
+       const char *diskpath = NULL;
        int rc, c, colormode = UL_COLORMODE_UNDEF;
        struct cfdisk _cf = { .lines_idx = 0 },
                      *cf = &_cf;
@@ -2575,7 +2578,7 @@ int main(int argc, char *argv[])
                { "help",    no_argument,       NULL, 'h' },
                { "version", no_argument,       NULL, 'V' },
                { "zero",    no_argument,       NULL, 'z' },
-               { NULL, 0, 0, 0 },
+               { NULL, 0, NULL, 0 },
        };
 
        setlocale(LC_ALL, "");
@@ -2586,7 +2589,7 @@ int main(int argc, char *argv[])
        while((c = getopt_long(argc, argv, "L::hVz", longopts, NULL)) != -1) {
                switch(c) {
                case 'h':
-                       usage(stdout);
+                       usage();
                        break;
                case 'L':
                        colormode = UL_COLORMODE_AUTO;
@@ -2600,6 +2603,8 @@ int main(int argc, char *argv[])
                case 'z':
                        cf->zero_start = 1;
                        break;
+               default:
+                       errtryhelp(EXIT_FAILURE);
                }
        }
 
@@ -2614,18 +2619,25 @@ int main(int argc, char *argv[])
 
        fdisk_set_ask(cf->cxt, ask_callback, (void *) cf);
 
-       if (optind == argc)
-               diskpath = access(DEFAULT_DEVICE, F_OK) == 0 ?
-                                       DEFAULT_DEVICE : ALTERNATE_DEVICE;
-       else
+       if (optind == argc) {
+               size_t i;
+
+               for (i = 0; i < ARRAY_SIZE(default_disks); i++) {
+                       if (access(default_disks[i], F_OK) == 0) {
+                               diskpath = default_disks[i];
+                               break;
+                       }
+               }
+               if (!diskpath)
+                       diskpath = default_disks[0];    /* default, used for "cannot open" */
+       } else
                diskpath = argv[optind];
 
        rc = fdisk_assign_device(cf->cxt, diskpath, 0);
        if (rc == -EACCES)
                rc = fdisk_assign_device(cf->cxt, diskpath, 1);
        if (rc != 0)
-               err(EXIT_FAILURE, _("cannot open %s"),
-                               optind == argc ? DEFAULT_DEVICE : diskpath);
+               err(EXIT_FAILURE, _("cannot open %s"), diskpath);
 
        /* Don't use err(), warn() from this point */
        ui_init(cf);