summaryrefslogtreecommitdiffstats
path: root/fdisks/cfdisk.c
diff options
context:
space:
mode:
authorKarel Zak2014-01-09 14:49:45 +0100
committerKarel Zak2014-03-11 11:35:13 +0100
commit8c3a5a440f71ccdbf69ec7ed4f2bb087e858c83f (patch)
treeebf9988fa097375d371b95c935eda7af8cb7eec6 /fdisks/cfdisk.c
parentinclude/xalloc: add xvasprintf() (diff)
downloadkernel-qcow2-util-linux-8c3a5a440f71ccdbf69ec7ed4f2bb087e858c83f.tar.gz
kernel-qcow2-util-linux-8c3a5a440f71ccdbf69ec7ed4f2bb087e858c83f.tar.xz
kernel-qcow2-util-linux-8c3a5a440f71ccdbf69ec7ed4f2bb087e858c83f.zip
cfdisk: basic UI stuff
Diffstat (limited to 'fdisks/cfdisk.c')
-rw-r--r--fdisks/cfdisk.c3221
1 files changed, 524 insertions, 2697 deletions
diff --git a/fdisks/cfdisk.c b/fdisks/cfdisk.c
index 1a95c1e0b..50c38a41d 100644
--- a/fdisks/cfdisk.c
+++ b/fdisks/cfdisk.c
@@ -1,69 +1,7 @@
-/****************************************************************************
- *
- * CFDISK
- *
- * cfdisk is a curses based disk drive partitioning program that can
- * create partitions for a wide variety of operating systems including
- * Linux, MS-DOS and OS/2.
- *
- * cfdisk was inspired by the fdisk program, by A. V. Le Blanc
- * (LeBlanc@mcc.ac.uk).
- *
- * Copyright (C) 1994 Kevin E. Martin (martin@cs.unc.edu)
- *
- * cfdisk is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * cfdisk is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Created: Fri Jan 28 22:46:58 1994, martin@cs.unc.edu
- * >2GB patches: Sat Feb 11 09:08:10 1995, faith@cs.unc.edu
- * Prettier menus: Sat Feb 11 09:08:25 1995, Janne Kukonlehto
- * <jtklehto@stekt.oulu.fi>
- * Versions 0.8e-p: aeb@cwi.nl
- * Rebaptised 2.9p, following util-linux versioning.
- *
- * Recognition of NTFS / HPFS difference inspired by patches
- * from Marty Leisner <leisner@sdsp.mc.xerox.com>
- * Exit codes by Enrique Zanardi <ezanardi@ull.es>:
- * 0: all went well
- * 1: command line error, out of memory
- * 2: hardware problems [Cannot open/seek/read/write disk drive].
- * 3: ioctl(fd, HDIO_GETGEO,...) failed. (Probably it is not a disk.)
- * 4: bad partition table on disk. [Bad primary/logical partition].
- *
- * Sat, 23 Jan 1999 19:34:45 +0100 <Vincent.Renardias@ldsol.com>
- * Internationalized + provided initial French translation.
- * Sat Mar 20 09:26:34 EST 1999 <acme@conectiva.com.br>
- * Some more i18n.
- * Sun Jul 18 03:19:42 MEST 1999 <aeb@cwi.nl>
- * Terabyte-sized disks.
- * Sat Jun 30 05:23:19 EST 2001 <nathans@sgi.com>
- * XFS label recognition.
- * Thu Nov 22 15:42:56 CET 2001 <flavio.stanchina@tin.it>
- * ext3 and ReiserFS recognition.
- * Sun Oct 12 17:43:43 CEST 2003 <flavio.stanchina@tin.it>
- * JFS recognition; ReiserFS label recognition.
- *
- ****************************************************************************/
-
#include <stdlib.h>
#include <stdio.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <ctype.h>
#include <errno.h>
-#include <getopt.h>
-#include <fcntl.h>
+#include <signal.h>
#ifdef HAVE_SLANG_H
#include <slang.h>
@@ -83,2807 +21,696 @@
#include <ncurses/ncurses.h>
#endif
-#include <signal.h>
-#include <math.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-
-#ifdef HAVE_LIBBLKID
-#include <blkid.h>
-#endif
-
#ifdef HAVE_WIDECHAR
#include <wctype.h>
#endif
+#include "c.h"
#include "closestream.h"
#include "nls.h"
-#include "rpmatch.h"
-#include "blkdev.h"
#include "strutils.h"
+#include "xalloc.h"
#include "mbsalign.h"
-#include "widechar.h"
-struct systypes {
- unsigned char type;
- char *name;
+#include "fdiskP.h"
+
+#define ARROW_CURSOR_STRING ">>> "
+#define ARROW_CURSOR_DUMMY " "
+#define ARROW_CURSOR_WIDTH (sizeof(ARROW_CURSOR_STRING) - 1)
+
+#define MENU_PADDING 2
+#define TABLE_START_LINE 4
+#define MENU_START_LINE (LINES - 5)
+
+
+struct cfdisk_menudesc {
+ int key; /* keyboard shortcut */
+ const char *name; /* item name */
+ const char *desc; /* item description */
};
-static struct systypes i386_sys_types[] = {
- #include "pt-mbr-partnames.h"
+struct cfdisk_menu {
+ struct cfdisk_menudesc *desc;
+ char *ignore;
+ size_t id;
+ size_t width;
+ size_t nitems;
+ struct cfdisk_menu *prev;
};
-#ifdef __GNU__
-#define DEFAULT_DEVICE "/dev/hd0"
-#define ALTERNATE_DEVICE "/dev/sd0"
-#elif defined(__FreeBSD__)
-#define DEFAULT_DEVICE "/dev/ad0"
-#define ALTERNATE_DEVICE "/dev/da0"
-#else
-#define DEFAULT_DEVICE "/dev/hda"
-#define ALTERNATE_DEVICE "/dev/sda"
-#endif
+static struct cfdisk_menudesc menu_main[] = {
+ { 'b', N_("Bootable"), N_("Toggle bootable flag of the current partition") },
+ { 'd', N_("Delete"), N_("Delete the current partition") },
+// { 'g', N_("Geometry"), N_("Change disk geometry (experts only)") },
+// { 'h', N_("Help"), N_("Print help screen") },
+// { 'm', N_("Maximize"), N_("Maximize disk usage of the current partition (experts only)") },
+ { 'n', N_("New"), N_("Create new partition from free space") },
+// { 'p', N_("Print"), N_("Print partition table to the screen or to a file") },
+ { 'q', N_("Quit"), N_("Quit program without writing partition table") },
+ { 't', N_("Type"), N_("Change the partition type") },
+// { 'u', N_("Units"), N_("Change units of the partition size display (MB, sect, cyl)") },
+ { 'W', N_("Write"), N_("Write partition table to disk (this might destroy data)") },
+ { 0, NULL, NULL }
+};
-/* With K=1024 we have `binary' megabytes, gigabytes, etc.
- Some misguided hackers like that.
- With K=1000 we have MB and GB that follow the standards
- [SI, ATA, IEEE etc] and the disk manufacturers and the law. */
-#define K 1000
-
-#define LINE_LENGTH 80
-#define MAXIMUM_PARTS 60
-
-#define SECTOR_SIZE 512
-
-#define MAX_HEADS 256
-#define MAX_SECTORS 63
-
-#define ACTIVE_FLAG 0x80
-#define PART_TABLE_FLAG0 0x55
-#define PART_TABLE_FLAG1 0xAA
-
-#define UNUSABLE -1
-#define FREE_SPACE 0x00
-#define DOS_EXTENDED 0x05
-#define OS2_OR_NTFS 0x07
-#define WIN98_EXTENDED 0x0f
-#define LINUX_EXTENDED 0x85
-#define LINUX_MINIX 0x81
-#define LINUX_SWAP 0x82
-#define LINUX 0x83
-
-#define PRI_OR_LOG -1
-#define PRIMARY -2
-#define LOGICAL -3
-
-#define COL_ID_WIDTH 25
-
-#define ESC '\033'
-#define DEL '\177'
-#define BELL '\007'
-#define REDRAWKEY '\014' /* ^L */
-
-/* Display units */
-#define GIGABYTES 1
-#define MEGABYTES 2
-#define SECTORS 3
-#define CYLINDERS 4
-
-#define GS_DEFAULT -1
-#define GS_ESCAPE -2
-
-#define PRINT_RAW_TABLE 1
-#define PRINT_SECTOR_TABLE 2
-#define PRINT_PARTITION_TABLE 4
-
-#define IS_PRIMARY(p) ((p) >= 0 && (p) < 4)
-#define IS_LOGICAL(p) ((p) > 3)
-
-#define round_int(d) ((double)((int)(d+0.5)))
-#define ceiling(d) ((double)(((d) != (int)(d)) ? (int)(d+1.0) : (int)(d)))
-
-struct partition {
- unsigned char boot_ind; /* 0x80 - active */
- unsigned char head; /* starting head */
- unsigned char sector; /* starting sector */
- unsigned char cyl; /* starting cylinder */
- unsigned char sys_ind; /* What partition type */
- unsigned char end_head; /* end head */
- unsigned char end_sector; /* end sector */
- unsigned char end_cyl; /* end cylinder */
- unsigned char start4[4]; /* starting sector counting from 0 */
- unsigned char size4[4]; /* nr of sectors in partition */
+enum {
+ CFDISK_MENU_MAIN = 0,
};
-int heads = 0;
-int sectors = 0;
-long long cylinders = 0;
-int cylinder_size = 0; /* heads * sectors */
-long long actual_size = 0; /* (in 512-byte sectors) - set using ioctl */
- /* explicitly given user values */
-int user_heads = 0, user_sectors = 0;
-long long user_cylinders = 0;
- /* kernel values; ignore the cylinders */
-int kern_heads = 0, kern_sectors = 0;
- /* partition-table derived values */
-int pt_heads = 0, pt_sectors = 0;
-
-
-static void
-set_hsc0(unsigned char *h, unsigned char *s, int *c, long long sector) {
- *s = sector % sectors + 1;
- sector /= sectors;
- *h = sector % heads;
- sector /= heads;
- *c = sector;
-}
+static struct cfdisk_menudesc *menus[] = {
+ [CFDISK_MENU_MAIN] = menu_main
+};
-static void
-set_hsc(unsigned char *h, unsigned char *s, unsigned char *c,
- long long sector) {
- int cc;
+struct cfdisk {
+ struct fdisk_context *cxt; /* libfdisk context */
+ struct fdisk_table *table; /* partition table */
- if (sector >= 1024*cylinder_size)
- sector = 1024*cylinder_size - 1;
- set_hsc0(h, s, &cc, sector);
- *c = cc & 0xFF;
- *s |= (cc >> 2) & 0xC0;
-}
+ struct cfdisk_menu *menu; /* the current menu */
+ size_t menu_idx;
-static void
-set_hsc_begin(struct partition *p, long long sector) {
- set_hsc(& p->head, & p->sector, & p->cyl, sector);
-}
+ int *cols; /* output columns */
+ size_t ncols; /* number of columns */
-static void
-set_hsc_end(struct partition *p, long long sector) {
- set_hsc(& p->end_head, & p->end_sector, & p->end_cyl, sector);
-}
+ char *linesbuf; /* table as string */
+ size_t linesbufsz; /* size of the tb_buf */
-#define is_extended(x) ((x) == DOS_EXTENDED || (x) == WIN98_EXTENDED || \
- (x) == LINUX_EXTENDED)
-
-/* start_sect and nr_sects are stored little endian on all machines */
-/* moreover, they are not aligned correctly */
-static void
-store4_little_endian(unsigned char *cp, unsigned int val) {
- cp[0] = (val & 0xff);
- cp[1] = ((val >> 8) & 0xff);
- cp[2] = ((val >> 16) & 0xff);
- cp[3] = ((val >> 24) & 0xff);
-}
+ char **lines; /* array with lines */
+ size_t nlines; /* number of lines */
+ size_t lines_idx; /* current line <0..N>, exclude header */
-static unsigned int
-read4_little_endian(unsigned char *cp) {
- return (unsigned int)(cp[0]) + ((unsigned int)(cp[1]) << 8)
- + ((unsigned int)(cp[2]) << 16)
- + ((unsigned int)(cp[3]) << 24);
-}
+ unsigned int ui_enabled : 1;
+};
-static void
-set_start_sect(struct partition *p, unsigned int start_sect) {
- store4_little_endian(p->start4, start_sect);
-}
+static int cols_init(struct cfdisk *cf)
+{
+ assert(cf);
-static unsigned int
-get_start_sect(struct partition *p) {
- return read4_little_endian(p->start4);
-}
+ free(cf->cols);
+ cf->cols = NULL;
+ cf->ncols = 0;
-static void
-set_nr_sects(struct partition *p, unsigned int nr_sects) {
- store4_little_endian(p->size4, nr_sects);
+ return fdisk_get_columns(cf->cxt, 0, &cf->cols, &cf->ncols);
}
-static unsigned int
-get_nr_sects(struct partition *p) {
- return read4_little_endian(p->size4);
-}
+/* It would be possible to use fdisk_table_to_string(), but we want some
+ * extension to the output format, so let's do it without libfdisk
+ */
+static char *table_to_string(struct cfdisk *cf, struct fdisk_table *tb)
+{
+ struct fdisk_partition *pa;
+ const struct fdisk_column *col;
+ struct fdisk_label *lb;
+ struct fdisk_iter *itr = NULL;
+ struct tt *tt = NULL;
+ char *res = NULL;
+ size_t i;
+
+ DBG(FRONTEND, dbgprint("table: convert to string"));
+
+ assert(cf);
+ assert(cf->cxt);
+ assert(cf->cols);
+ assert(tb);
+
+ lb = fdisk_context_get_label(cf->cxt, NULL);
+ assert(lb);
+
+ tt = tt_new_table(TT_FL_FREEDATA | TT_FL_MAX);
+ if (!tt)
+ goto done;
+ itr = fdisk_new_iter(FDISK_ITER_FORWARD);
+ if (!itr)
+ goto done;
-#define ALIGNMENT 2
-typedef union {
- struct {
- unsigned char align[ALIGNMENT];
- unsigned char b[SECTOR_SIZE];
- } c;
- struct {
- unsigned char align[ALIGNMENT];
- unsigned char buffer[0x1BE];
- struct partition part[4];
- unsigned char magicflag[2];
- } p;
-} partition_table;
-
-typedef struct {
- long long first_sector; /* first sector in partition */
- long long last_sector; /* last sector in partition */
- long offset; /* offset from first sector to start of data */
- int flags; /* active == 0x80 */
- int id; /* filesystem type */
- int num; /* number of partition -- primary vs. logical */
-#define LABELSZ 16
- char volume_label[LABELSZ+1];
-#define OSTYPESZ 8
- char ostype[OSTYPESZ+1];
-#define FSTYPESZ 12
- char fstype[FSTYPESZ+1];
-} partition_info;
-
-char *disk_device = DEFAULT_DEVICE;
-int fd;
-int changed = FALSE;
-int opened = FALSE;
-int opentype;
-int curses_started = 0;
-
-partition_info p_info[MAXIMUM_PARTS];
-partition_info ext_info;
-int num_parts = 0;
-
-int logical = 0;
-long long logical_sectors[MAXIMUM_PARTS];
-
-#ifdef HAVE_SIGHANDLER_T
-sighandler_t old_SIGINT, old_SIGTERM;
-#else
-void (* old_SIGINT)(int), (* old_SIGTERM)(int);
-#endif
+ /* headers */
+ for (i = 0; i < cf->ncols; i++) {
+ col = fdisk_label_get_column(lb, cf->cols[i]);
+ if (col)
+ tt_define_column(tt, col->name,
+ col->width,
+ col->tt_flags);
+ }
+
+ /* data */
+ while (fdisk_table_next_partition(tb, itr, &pa) == 0) {
+ struct tt_line *ln = tt_add_line(tt, NULL);
+ if (!ln)
+ goto done;
+ for (i = 0; i < cf->ncols; i++) {
+ char *cdata = NULL;
+
+ col = fdisk_label_get_column(lb, cf->cols[i]);
+ if (!col)
+ continue;
+ if (fdisk_partition_to_string(pa, cf->cxt, col->id, &cdata))
+ continue;
+ tt_line_set_data(ln, i, cdata);
+ }
+ }
-int arrow_cursor = FALSE;
-int display_units = MEGABYTES;
-int zero_table = FALSE;
-int use_partition_table_geometry = FALSE;
-int print_only = 0;
-
-/* Curses screen information */
-int cur_part = 0;
-int warning_last_time = FALSE;
-int defined = FALSE;
-int COLUMNS = 80;
-int NUM_ON_SCREEN = 1;
-
-/* Y coordinates */
-int HEADER_START = 0;
-int DISK_TABLE_START = 6;
-int WARNING_START = 23;
-int COMMAND_LINE_Y = 21;
-
-/* X coordinates */
-int NAME_START = 4;
-int FLAGS_START = 16;
-int PTYPE_START = 28;
-int FSTYPE_START = 38;
-int LABEL_START = 54;
-int SIZE_START = 68;
-int COMMAND_LINE_X = 5;
-
-static void die_x(int ret);
-static void draw_screen(void);
-
-/* Guaranteed alloc */
-static void *
-xmalloc (size_t size) {
- void *t;
-
- if (size == 0)
- return NULL;
-
- t = malloc (size);
- if (t == NULL) {
- fprintf (stderr, _("%s: Out of memory!\n"), "cfdisk");
- die_x(1);
- }
- return t;
-}
+ if (!tt_is_empty(tt)) {
+ tt_set_termreduce(tt, ARROW_CURSOR_WIDTH);
+ tt_print_table_to_string(tt, &res);
+ }
+done:
+ tt_free_table(tt);
+ fdisk_free_iter(itr);
-/* Some libc's have their own basename() */
-static char *
-my_basename(char *devname) {
- char *s = strrchr(devname, '/');
- return s ? s+1 : devname;
+ return res;
}
-static char *
-partition_type_name(unsigned char type) {
- struct systypes *s = i386_sys_types;
- while(s->name && s->type != type)
- s++;
- return s->name;
-}
+static int lines_refresh_buffer(struct cfdisk *cf)
+{
+ int rc;
+ char *p;
+ size_t i;
-static char *
-partition_type_text(int i) {
- if (p_info[i].id == UNUSABLE)
- return _("Unusable");
- else if (p_info[i].id == FREE_SPACE)
- return _("Free Space");
- else if (*p_info[i].fstype)
- return p_info[i].fstype;
- else
- return _(partition_type_name(p_info[i].id));
-}
+ assert(cf);
-static void
-fdexit(int ret) {
- if (opened) {
- if (changed) {
- if (close_fd(fd) != 0) {
- fprintf(stderr, _("write failed\n"));
- exit(2);
- }
- } else
- close(fd);
- }
- if (changed) {
- fprintf(stderr, _("Disk has been changed.\n"));
-#if 0
- fprintf(stderr, _("Reboot the system to ensure the partition "
- "table is correctly updated.\n"));
-#endif
+ DBG(FRONTEND, dbgprint("refresing buffer"));
- fprintf( stderr, _("\nWARNING: If you have created or modified any\n"
- "DOS 6.x partitions, please see the cfdisk manual\n"
- "page for additional information.\n") );
- }
+ free(cf->linesbuf);
+ free(cf->lines);
+ cf->linesbuf = NULL;
+ cf->linesbufsz = 0;
+ cf->lines = NULL;
+ cf->nlines = 0;
- exit(ret);
-}
+ fdisk_unref_table(cf->table);
+ fdisk_context_enable_freespace(cf->cxt, 1);
-/*
- * Note that @len is size of @str buffer.
- *
- * Returns number of read bytes (without \0).
- */
-static int
-get_string(char *str, int len, char *def) {
- size_t cells = 0;
- ssize_t i = 0;
- int x, y;
- int use_def = FALSE;
- wint_t c;
-
- getyx(stdscr, y, x);
- clrtoeol();
-
- str[i] = 0;
-
- if (def != NULL) {
- mvaddstr(y, x, def);
- move(y, x);
- use_def = TRUE;
- }
-
- refresh();
-
- while (1) {
-#if !defined(HAVE_SLCURSES_H) && !defined(HAVE_SLANG_SLCURSES_H) && \
- defined(HAVE_LIBNCURSESW) && defined(HAVE_WIDECHAR)
- if (get_wch(&c) == ERR) {
-#else
- if ((c = getch()) == ERR) {
-#endif
- if (!isatty(STDIN_FILENO))
- exit(2);
- else
- break;
- }
- if (c == '\r' || c == '\n' || c == KEY_ENTER)
- break;
+ rc = fdisk_get_table(cf->cxt, &cf->table);
+ if (rc)
+ return rc;
- switch (c) {
- case ESC:
- move(y, x);
- clrtoeol();
- refresh();
- return GS_ESCAPE;
- case DEL:
- case '\b':
- case KEY_BACKSPACE:
- if (i > 0) {
- cells--;
- i = mbs_truncate(str, &cells);
- if (i < 0)
- return GS_ESCAPE;
- mvaddch(y, x + cells, ' ');
- move(y, x + cells);
- } else if (use_def) {
- clrtoeol();
- use_def = FALSE;
- } else
- putchar(BELL);
- break;
- default:
-#if defined(HAVE_LIBNCURSESW) && defined(HAVE_WIDECHAR)
- if (i + 1 < 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 < len) {
- s[sz] = '\0';
- mvaddnstr(y, x + cells, s, sz);
- if (use_def) {
- clrtoeol();
- use_def = FALSE;
- }
- memcpy(str + i, s, sz);
- i += sz;
- str[i] = '\0';
- cells += wcwidth(wc);
- } else
- putchar(BELL);
- }
-#else
- if (i + 1 < len && isprint(c)) {
- mvaddch(y, x + cells, c);
- if (use_def) {
- clrtoeol();
- use_def = FALSE;
- }
- str[i++] = c;
- str[i] = 0;
- cells++;
- }
-#endif
- else
- putchar(BELL);
- }
- refresh();
- }
+ cf->linesbuf = table_to_string(cf, cf->table);
+ if (!cf->linesbuf)
+ return -ENOMEM;
- if (use_def)
- return GS_DEFAULT;
- else
- return i;
-}
-
-static void
-clear_warning(void) {
- int i;
+ cf->linesbufsz = strlen(cf->linesbuf);
+ cf->nlines = fdisk_table_get_nents(cf->table) + 1; /* 1 for header line */
- if (!curses_started || !warning_last_time)
- return;
+ cf->lines = calloc(cf->nlines, sizeof(char *));
+ if (!cf->lines)
+ return -ENOMEM;
- move(WARNING_START,0);
- for (i = 0; i < COLS; i++)
- addch(' ');
+ for (p = cf->linesbuf, i = 0; p && i < cf->nlines; i++) {
+ cf->lines[i] = p;
+ p = strchr(p, '\n');
+ if (p) {
+ *p = '\0';
+ p++;
+ }
+ }
- warning_last_time = FALSE;
+ return 0;
}
-static void
-print_warning(char *s) {
- if (!curses_started) {
- fprintf(stderr, "%s\n", s);
- } else {
- mvaddstr(WARNING_START, (COLS-strlen(s))/2, s);
- putchar(BELL); /* CTRL-G */
+static int ask_callback(struct fdisk_context *cxt, struct fdisk_ask *ask,
+ void *data __attribute__((__unused__)))
+{
+ int rc = 0;
- warning_last_time = TRUE;
- }
-}
+ assert(cxt);
+ assert(ask);
-static void
-fatal(char *s, int ret) {
- char *err1 = _("FATAL ERROR");
- char *err2 = _("Press any key to exit cfdisk");
-
- if (curses_started) {
- char *str = xmalloc(strlen(s) + strlen(err1) + strlen(err2) + 10);
-
- sprintf(str, "%s: %s", err1, s);
- if (strlen(str) > (size_t) COLS)
- str[COLS] = 0;
- mvaddstr(WARNING_START, (COLS-strlen(str))/2, str);
- sprintf(str, "%s", err2);
- if (strlen(str) > (size_t) COLS)
- str[COLS] = 0;
- mvaddstr(WARNING_START+1, (COLS-strlen(str))/2, str);
- putchar(BELL); /* CTRL-G */
- refresh();
- (void)getch();
- die_x(ret);
- } else {
- fprintf(stderr, "%s: %s\n", err1, s);
- exit(ret);
- }
+ switch(fdisk_ask_get_type(ask)) {
+ case FDISK_ASKTYPE_INFO:
+ fputs(fdisk_ask_print_get_mesg(ask), stdout);
+ fputc('\n', stdout);
+ break;
+ case FDISK_ASKTYPE_WARNX:
+ fputs(fdisk_ask_print_get_mesg(ask), stderr);
+ fputc('\n', stderr);
+ break;
+ case FDISK_ASKTYPE_WARN:
+ fputs(fdisk_ask_print_get_mesg(ask), stderr);
+ errno = fdisk_ask_print_get_errno(ask);
+ fprintf(stderr, ": %m\n");
+ break;
+ default:
+ warnx(_("internal error: unsupported dialog type %d"), fdisk_ask_get_type(ask));
+ return -EINVAL;
+ }
+ return rc;
}
-static void
-die(int dummy __attribute__((__unused__))) {
- die_x(0);
-}
-static void
-die_x(int ret) {
- signal(SIGINT, old_SIGINT);
- signal(SIGTERM, old_SIGTERM);
+static int ui_end(struct cfdisk *cf)
+{
+ if (cf && !cf->ui_enabled)
+ return -EINVAL;
+
#if defined(HAVE_SLCURSES_H) || defined(HAVE_SLANG_SLCURSES_H)
- SLsmg_gotorc(LINES-1, 0);
- SLsmg_refresh();
+ SLsmg_gotorc(LINES - 1, 0);
+ SLsmg_refresh();
#else
- mvcur(0, COLS-1, LINES-1, 0);
+ mvcur(0, COLS - 1, LINES-1, 0);
#endif
- nl();
- endwin();
- printf("\n");
- fdexit(ret);
+ nl();
+ endwin();
+ printf("\n");
+ return 0;
}
-static void
-read_sector(unsigned char *buffer, long long sect_num) {
- if (lseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0)
- fatal(_("Cannot seek on disk drive"), 2);
- if (read(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE)
- fatal(_("Cannot read disk drive"), 2);
-}
-
-static void
-write_sector(unsigned char *buffer, long long sect_num) {
- if (lseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0)
- fatal(_("Cannot seek on disk drive"), 2);
- if (write(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE)
- fatal(_("Cannot write disk drive"), 2);
-}
-
-#ifdef HAVE_LIBBLKID
-static void
-get_fsinfo(int i)
+static void ui_print_center(int line, const char *fmt, ...)
{
- blkid_probe pr;
- blkid_loff_t offset, size;
- const char *data;
-
- offset = (p_info[i].first_sector + p_info[i].offset) * SECTOR_SIZE;
- size = (p_info[i].last_sector - p_info[i].first_sector + 1) * SECTOR_SIZE;
- pr = blkid_new_probe();
- if (!pr)
- return;
- blkid_probe_enable_superblocks(pr, 1);
- blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL |
- BLKID_SUBLKS_TYPE);
- if (blkid_probe_set_device(pr, fd, offset, size))
- goto done;
- if (blkid_do_safeprobe(pr))
- goto done;
+ size_t width;
+ va_list ap;
+ char *buf = NULL;
- if (!blkid_probe_lookup_value(pr, "TYPE", &data, 0))
- strncpy(p_info[i].fstype, data, FSTYPESZ);
+ move(line, 0);
+ clrtoeol();
- if (!blkid_probe_lookup_value(pr, "LABEL", &data, 0))
- strncpy(p_info[i].volume_label, data, LABELSZ);
-done:
- blkid_free_probe(pr);
-}
-#endif
+ va_start(ap, fmt);
+ xvasprintf(&buf, fmt, ap);
+ va_end(ap);
-static void
-check_part_info(void) {
- int i, pri = 0, log = 0;
-
- for (i = 0; i < num_parts; i++)
- if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num))
- pri++;
- else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num))
- log++;
- if (is_extended(ext_info.id)) {
- if (log > 0)
- pri++;
- else {
- ext_info.first_sector = 0;
- ext_info.last_sector = 0;
- ext_info.offset = 0;
- ext_info.flags = 0;
- ext_info.id = FREE_SPACE;
- ext_info.num = PRIMARY;
- }
- }
-
- if (pri >= 4) {
- for (i = 0; i < num_parts; i++)
- if (p_info[i].id == FREE_SPACE || p_info[i].id == UNUSABLE) {
- if (is_extended(ext_info.id)) {
- if (p_info[i].first_sector >= ext_info.first_sector &&
- p_info[i].last_sector <= ext_info.last_sector) {
- p_info[i].id = FREE_SPACE;
- p_info[i].num = LOGICAL;
- } else if (i > 0 &&
- p_info[i-1].first_sector >=
- ext_info.first_sector &&
- p_info[i-1].last_sector <=
- ext_info.last_sector) {
- p_info[i].id = FREE_SPACE;
- p_info[i].num = LOGICAL;
- } else if (i < num_parts-1 &&
- p_info[i+1].first_sector >=
- ext_info.first_sector &&
- p_info[i+1].last_sector <=
- ext_info.last_sector) {
- p_info[i].id = FREE_SPACE;
- p_info[i].num = LOGICAL;
- } else
- p_info[i].id = UNUSABLE;
- } else /* if (!is_extended(ext_info.id)) */
- p_info[i].id = UNUSABLE;
- } else /* if (p_info[i].id > 0) */
- while (0); /* Leave these alone */
- } else { /* if (pri < 4) */
- for (i = 0; i < num_parts; i++) {
- if (p_info[i].id == UNUSABLE)
- p_info[i].id = FREE_SPACE;
- if (p_info[i].id == FREE_SPACE) {
- if (is_extended(ext_info.id)) {
- if (p_info[i].first_sector >= ext_info.first_sector &&
- p_info[i].last_sector <= ext_info.last_sector)
- p_info[i].num = LOGICAL;
- else if (i > 0 &&
- p_info[i-1].first_sector >=
- ext_info.first_sector &&
- p_info[i-1].last_sector <=
- ext_info.last_sector)
- p_info[i].num = PRI_OR_LOG;
- else if (i < num_parts-1 &&
- p_info[i+1].first_sector >=
- ext_info.first_sector &&
- p_info[i+1].last_sector <=
- ext_info.last_sector)
- p_info[i].num = PRI_OR_LOG;
- else
- p_info[i].num = PRIMARY;
- } else /* if (!is_extended(ext_info.id)) */
- p_info[i].num = PRI_OR_LOG;
- } else /* if (p_info[i].id > 0) */
- while (0); /* Leave these alone */
- }
- }
+ width = strlen(buf); /* TODO: count cells! */
+ mvaddstr(line, (COLS - width) / 2, buf);
+ free(buf);
}
-static void
-remove_part(int i) {
- int p;
- for (p = i; p < num_parts; p++)
- p_info[p] = p_info[p+1];
-
- num_parts--;
- if (cur_part == num_parts)
- cur_part--;
+static void die_on_signal(int dummy __attribute__((__unused__)))
+{
+ ui_end(NULL);
+ exit(EXIT_FAILURE);
}
-static void
-insert_empty_part(int i, long long first, long long last) {
- int p;
-
- for (p = num_parts; p > i; p--)
- p_info[p] = p_info[p-1];
+static void menu_update_ignore(struct cfdisk *cf)
+{
+ char *ignore = NULL;
+ struct cfdisk_menu *m;
+ struct cfdisk_menudesc *d;
- p_info[i].first_sector = first;
- p_info[i].last_sector = last;
- p_info[i].offset = 0;
- p_info[i].flags = 0;
- p_info[i].id = FREE_SPACE;
- p_info[i].num = PRI_OR_LOG;
- p_info[i].volume_label[0] = 0;
- p_info[i].fstype[0] = 0;
- p_info[i].ostype[0] = 0;
+ assert(cf);
- num_parts++;
-}
+ m = cf->menu;
+ DBG(FRONTEND, dbgprint("menu: update menu ignored keys"));
-static void
-del_part(int i) {
- int num = p_info[i].num;
-
- if (i > 0 && (p_info[i-1].id == FREE_SPACE ||
- p_info[i-1].id == UNUSABLE)) {
- /* Merge with previous partition */
- p_info[i-1].last_sector = p_info[i].last_sector;
- remove_part(i--);
- }
-
- if (i < num_parts - 1 && (p_info[i+1].id == FREE_SPACE ||
- p_info[i+1].id == UNUSABLE)) {
- /* Merge with next partition */
- p_info[i+1].first_sector = p_info[i].first_sector;
- remove_part(i);
- }
-
- if (i > 0)
- p_info[i].first_sector = p_info[i-1].last_sector + 1;
- else
- p_info[i].first_sector = 0;
-
- if (i < num_parts - 1)
- p_info[i].last_sector = p_info[i+1].first_sector - 1;
- else
- p_info[i].last_sector = actual_size - 1;
-
- p_info[i].offset = 0;
- p_info[i].flags = 0;
- p_info[i].id = FREE_SPACE;
- p_info[i].num = PRI_OR_LOG;
-
- if (IS_LOGICAL(num)) {
- /* We have a logical partition --> shrink the extended partition
- * if (1) this is the first logical drive, or (2) this is the
- * last logical drive; and if there are any other logical drives
- * then renumber the ones after "num".
- */
- if (i == 0 || (i > 0 && IS_PRIMARY(p_info[i-1].num))) {
- ext_info.first_sector = p_info[i].last_sector + 1;
- ext_info.offset = 0;
+ switch (m->id) {
+ case CFDISK_MENU_MAIN:
+ break;
}
- if (i == num_parts-1 ||
- (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num)))
- ext_info.last_sector = p_info[i].first_sector - 1;
- for (i = 0; i < num_parts; i++)
- if (p_info[i].num > num)
- p_info[i].num--;
- }
-
- /* Clean up the rest of the partitions */
- check_part_info();
-}
-static int
-add_part(int num, int id, int flags, long long first, long long last,
- long long offset, int want_label, char **errmsg) {
- int i, pri = 0, log = 0;
-
- if (num_parts == MAXIMUM_PARTS) {
- *errmsg = _("Too many partitions");
- return -1;
- }
-
- if (first < 0) {
- *errmsg = _("Partition begins before sector 0");
- return -1;
- }
-
- if (last < 0) {
- *errmsg = _("Partition ends before sector 0");
- return -1;
- }
-
- if (first >= actual_size) {
- *errmsg = _("Partition begins after end-of-disk");
- return -1;
- }
-
- if (last >= actual_size) {
- *errmsg = _("Partition ends after end-of-disk");
- return -1;
- }
-
- for (i = 0; i < num_parts; i++) {
- if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num))
- pri++;
- else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num))
- log++;
- }
- if (is_extended(ext_info.id) && log > 0)
- pri++;
-
- if (IS_PRIMARY(num)) {
- if (pri >= 4) {
- return -1; /* no room for more */
- } else
- pri++;
- }
-
- for (i = 0; i < num_parts && p_info[i].last_sector < first; i++);
-
- if (i < num_parts && p_info[i].id != FREE_SPACE) {
- if (last < p_info[i].first_sector)
- *errmsg = _("logical partitions not in disk order");
- else if (first + offset <= p_info[i].last_sector &&
- p_info[i].first_sector + p_info[i].offset <= last)
- *errmsg = _("logical partitions overlap");
- else
- /* the enlarged logical partition starts at the
- partition table sector that defines it */
- *errmsg = _("enlarged logical partitions overlap");
- return -1;
- }
-
- if (i == num_parts || last > p_info[i].last_sector) {
- return -1;
- }
-
- if (is_extended(id)) {
- if (ext_info.id != FREE_SPACE) {
- return -1; /* second extended */
- }
- else if (IS_PRIMARY(num)) {
- ext_info.first_sector = first;
- ext_info.last_sector = last;
- ext_info.offset = offset;
- ext_info.flags = flags;
- ext_info.id = id;
- ext_info.num = num;
- ext_info.volume_label[0] = 0;
- ext_info.fstype[0] = 0;
- ext_info.ostype[0] = 0;
- return 0;
- } else {
- return -1; /* explicit extended logical */
+ /* return if no change */
+ if ( (!m->ignore && (!ignore || !*ignore))
+ || (m->ignore && ignore && strcmp(m->ignore, ignore) == 0)) {
+ free(ignore);
+ return;
}
- }
- if (IS_LOGICAL(num)) {
- if (!is_extended(ext_info.id)) {
- print_warning(_("!!!! Internal error creating logical "
- "drive with no extended partition !!!!"));
- } else {
- /* We might have a logical partition outside of the extended
- * partition's range --> we have to extend the extended
- * partition's range to encompass this new partition, but we
- * must make sure that there are no primary partitions between
- * it and the closest logical drive in extended partition.
- */
- if (first < ext_info.first_sector) {
- if (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num)) {
- print_warning(_("Cannot create logical drive here -- would create two extended partitions"));
- return -1;
- } else {
- if (first == 0) {
- ext_info.first_sector = 0;
- ext_info.offset = first = offset;
- } else {
- ext_info.first_sector = first;
- }
- }
- } else if (last > ext_info.last_sector) {
- if (i > 0 && IS_PRIMARY(p_info[i-1].num)) {
- print_warning(_("Cannot create logical drive here -- would create two extended partitions"));
- return -1;
- } else {
- ext_info.last_sector = last;
- }
- }
- }
- }
-
- if (first != p_info[i].first_sector &&
- !(IS_LOGICAL(num) && first == offset)) {
- insert_empty_part(i, p_info[i].first_sector, first-1);
- i++;
- }
-
- if (last != p_info[i].last_sector)
- insert_empty_part(i+1, last+1, p_info[i].last_sector);
-
- p_info[i].first_sector = first;
- p_info[i].last_sector = last;
- p_info[i].offset = offset;
- p_info[i].flags = flags;
- p_info[i].id = id;
- p_info[i].num = num;
- p_info[i].volume_label[0] = 0;
- p_info[i].fstype[0] = 0;
- p_info[i].ostype[0] = 0;
-
-#ifdef HAVE_LIBBLKID
- if (want_label)
- get_fsinfo(i);
-#endif
- check_part_info();
+ free(m->ignore);
+ m->ignore = ignore;
+ m->nitems = 0;
- return 0;
+ for (d = m->desc; d->name; d++) {
+ if (m->ignore && strchr(m->ignore, d->key))
+ m->nitems++;
+ }
}
-static int
-find_primary(void) {
- int num = 0, cur = 0;
-
- while (cur < num_parts && IS_PRIMARY(num))
- if ((p_info[cur].id > 0 && p_info[cur].num == num) ||
- (is_extended(ext_info.id) && ext_info.num == num)) {
- num++;
- cur = 0;
- } else
- cur++;
+static struct cfdisk_menu *menu_push(struct cfdisk *cf, size_t id)
+{
+ struct cfdisk_menu *m = xcalloc(1, sizeof(*m));
+ struct cfdisk_menudesc *d;
- if (!IS_PRIMARY(num))
- return -1;
- else
- return num;
-}
+ assert(cf);
+ assert(id < ARRAY_SIZE(menus));
-static int
-find_logical(int i) {
- int num = -1;
- int j;
+ DBG(FRONTEND, dbgprint("menu: new menu"));
- for (j = i; j < num_parts && num == -1; j++)
- if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num))
- num = p_info[j].num;
+ m->prev = cf->menu;
+ m->id = id;
+ m->desc = menus[id];
- if (num == -1) {
- num = 4;
- for (j = 0; j < num_parts; j++)
- if (p_info[j].id > 0 && p_info[j].num == num)
- num++;
- }
+ for (d = m->desc; d->name; d++) {
+ const char *name = _(d->name);
+ size_t len = strlen(name); /* TODO: we care about cells! */
+ if (len > m->width)
+ m->width = len;
+ m->nitems++;
+ }
- return num;
+ cf->menu = m;
+ return m;
}
-/*
- * Command menu support by Janne Kukonlehto <jtklehto@phoenix.oulu.fi>
- * September 1994
- */
-
-/* Constants for menuType parameter of menuSelect function */
-#define MENU_ACCEPT_OTHERS 4
-#define MENU_BUTTON 8
-/* Miscellenous constants */
-#define MENU_SPACING 2
-#define MENU_MAX_ITEMS 256 /* for simpleMenu function */
-
-struct MenuItem
+static struct cfdisk_menu *menu_pop(struct cfdisk *cf)
{
- int key; /* Keyboard shortcut; if zero, then there is no more items in the menu item table */
- char *name; /* Item name, should be eight characters with current implementation */
- char *desc; /* Item description to be printed when item is selected */
-};
-
-/*
- * Actual function which prints the button bar and highlights the active button
- * Should not be called directly. Call function menuSelect instead.
- */
+ struct cfdisk_menu *m = NULL;
-static int
-menuUpdate( int y, int x, struct MenuItem *menuItems, int itemLength,
- char *available, int menuType, int current ) {
- int i, lmargin = x;
- char *mcd;
+ assert(cf);
- /* Print available buttons */
- move( y, x ); clrtoeol();
+ DBG(FRONTEND, dbgprint("menu: rem menu"));
- for( i = 0; menuItems[i].key; i++ ) {
- char buff[20];
- int lenName;
- const char *mi;
-
- /* Search next available button */
- while( menuItems[i].key && !strchr(available, menuItems[i].key) )
- i++;
-
- if( !menuItems[i].key ) break; /* No more menu items */
-
- /* If selected item is not available and we have bypassed it,
- make current item selected */
- if( current < i && menuItems[current].key < 0 ) current = i;
-
- /* If current item is selected, highlight it */
- if( current == i ) /*attron( A_REVERSE )*/ standout ();
-
- /* Print item */
- /* Because of a bug in gettext() we must not translate empty strings */
- if (menuItems[i].name[0])
- mi = _(menuItems[i].name);
- else
- mi = "";
- lenName = strlen( mi );
-#if 0
- if(lenName > itemLength || lenName >= sizeof(buff))
- print_warning(_("Menu item too long. Menu may look odd."));
-#endif
- if ((size_t) lenName >= sizeof(buff)) { /* truncate ridiculously long string */
- xstrncpy(buff, mi, sizeof(buff));
- } else if (lenName >= itemLength) {
- snprintf(buff, sizeof(buff),
- (menuType & MENU_BUTTON) ? "[%s]" : "%s", mi);
- } else {
- snprintf(buff, sizeof(buff),
- (menuType & MENU_BUTTON) ? "[%*s%-*s]" : "%*s%-*s",
- (itemLength - lenName) / 2, "",
- (itemLength - lenName + 1) / 2 + lenName, mi);
+ if (cf->menu) {
+ m = cf->menu->prev;
+ free(cf->menu->ignore);
+ free(cf->menu);
}
- mvaddstr( y, x, buff );
-
- /* Lowlight after selected item */
- if( current == i ) /*attroff( A_REVERSE )*/ standend ();
-
- /* Calculate position for the next item */
- x += itemLength + MENU_SPACING;
- if( menuType & MENU_BUTTON ) x += 2;
- if( x > COLUMNS - lmargin - 12 )
- {
- x = lmargin;
- y ++ ;
- }
- }
-
- /* Print the description of selected item */
- mcd = _(menuItems[current].desc);
- mvaddstr( WARNING_START + 1, (COLUMNS - strlen( mcd )) / 2, mcd );
- return y;
+ cf->menu = m;
+ return cf->menu;
}
-/* This function takes a list of menu items, lets the user choose one *
- * and returns the keyboard shortcut value of the selected menu item */
-
-static int
-menuSelect( int y, int x, struct MenuItem *menuItems, int itemLength,
- char *available, int menuType, int menuDefault ) {
- int i, ylast = y, key = 0, current = menuDefault;
-
- /* Make sure that the current is one of the available items */
- while( !strchr(available, menuItems[current].key) ) {
- current ++ ;
- if( !menuItems[current].key ) current = 0;
- }
-
- keypad(stdscr, TRUE);
-
- /* Repeat until allowable choice has been made */
- while( !key ) {
- /* Display the menu and read a command */
- ylast = menuUpdate( y, x, menuItems, itemLength, available,
- menuType, current );
- refresh();
- key = getch();
-
- if (key == ERR)
- if (!isatty(STDIN_FILENO))
- exit(2);
-
- /* Clear out all prompts and such */
- clear_warning();
- for (i = y; i < ylast; i++) {
- move(i, x);
- clrtoeol();
- }
- move( WARNING_START + 1, 0 );
- clrtoeol();
-
- switch (key) {
- case KEY_RIGHT:
- case '\t':
- /* Select next menu item */
- do {
- current++;
- if (!menuItems[current].key)
- current = 0;
- } while (!strchr(available, menuItems[current].key));
- key = 0;
- break;
- case KEY_LEFT:
-#ifdef KEY_BTAB
- case KEY_BTAB: /* Back tab */
-#endif
- /* Select previous menu item */
- do {
- current--;
- if (current < 0) {
- while (menuItems[current + 1].key)
- current++;
- }
- } while (!strchr(available, menuItems[current].key));
- key = 0;
- break;
- case KEY_ENTER:
- case '\n':
- case '\r':
- /* Enter equals the keyboard shortcut of current menu item */
- key = menuItems[current].key;
- break;
- }
- /* Should all keys to be accepted? */
- if( key && (menuType & MENU_ACCEPT_OTHERS) ) break;
-
- /* Is pressed key among acceptable ones? */
- if( key && (strchr(available, tolower(key)) || strchr(available, key)))
- break;
-
- /* The key has not been accepted so far -> let's reject it */
- if (key) {
- key = 0;
- putchar( BELL );
- print_warning(_("Illegal key"));
- }
- }
-
- keypad(stdscr, FALSE);
-
- /* Clear out prompts and such */
- clear_warning();
- for( i = y; i <= ylast; i ++ ) {
- move( i, x );
- clrtoeol();
- }
- move( WARNING_START + 1, 0 );
- clrtoeol();
- return key;
-}
+static int ui_init(struct cfdisk *cf)
+{
+ struct sigaction sa;
-/* A function which displays "Press a key to continue" *
- * and waits for a keypress. *
- * Perhaps calling function menuSelect is a bit overkill but who cares? */
+ DBG(FRONTEND, dbgprint("ui: init"));
-static void
-menuContinue(void) {
- static struct MenuItem menuContinueBtn[]=
- {
- { 'c', "", N_("Press a key to continue") },
- { 0, NULL, NULL }
- };
+ /* setup SIGCHLD handler */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = die_on_signal;
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
- menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X,
- menuContinueBtn, 0, "c", MENU_ACCEPT_OTHERS, 0 );
-}
+ cf->ui_enabled = 1;
+ initscr();
-/* Function menuSelect takes way too many parameters *
- * Luckily, most of time we can do with this function */
-
-static int
-menuSimple(struct MenuItem *menuItems, int menuDefault) {
- int i, j, itemLength = 0;
- char available[MENU_MAX_ITEMS];
-
- for(i = 0; menuItems[i].key; i++)
- {
- j = strlen( _(menuItems[i].name) );
- if( j > itemLength ) itemLength = j;
- available[i] = menuItems[i].key;
- }
- available[i] = 0;
- return menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuItems, itemLength,
- available, MENU_BUTTON, menuDefault);
-}
+ cbreak();
+ noecho();
+ nonl();
+ curs_set(0);
+ keypad(stdscr, TRUE);
-/* End of command menu support code */
-
-static void
-new_part(int i) {
- char response[LINE_LENGTH], def[LINE_LENGTH];
- char c;
- long long first = p_info[i].first_sector;
- long long last = p_info[i].last_sector;
- long long offset = 0;
- int flags = 0;
- int id = LINUX;
- int num = -1;
- long long num_sects = last - first + 1;
- int len, ext, j;
- char *errmsg;
- double sectors_per_MB = K*K / 512.0;
-
- if (p_info[i].num == PRI_OR_LOG) {
- static struct MenuItem menuPartType[]=
- {
- { 'p', N_("Primary"), N_("Create a new primary partition") },
- { 'l', N_("Logical"), N_("Create a new logical partition") },
- { ESC, N_("Cancel"), N_("Don't create a partition") },
- { 0, NULL, NULL }
- };
-
- c = menuSimple( menuPartType, 0 );
- if (toupper(c) == 'P')
- num = find_primary();
- else if (toupper(c) == 'L')
- num = find_logical(i);
- else
- return;
- } else if (p_info[i].num == PRIMARY)
- num = find_primary();
- else if (p_info[i].num == LOGICAL)
- num = find_logical(i);
- else
- print_warning(_("!!! Internal error !!!"));
-
- snprintf(def, sizeof(def), "%.2f", num_sects/sectors_per_MB);
- mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, _("Size (in MB): "));
- if ((len = get_string(response, LINE_LENGTH, def)) <= 0 &&
- len != GS_DEFAULT)
- return;
- else if (len > 0) {
-#define num_cyls(bytes) (round_int(bytes/SECTOR_SIZE/cylinder_size))
- for (j = 0;
- j < len-1 && (isdigit(response[j]) || response[j] == '.');
- j++);
- if (toupper(response[j]) == 'K') {
- num_sects = num_cyls(atof(response)*K)*cylinder_size;
- } else if (toupper(response[j]) == 'M') {
- num_sects = num_cyls(atof(response)*K*K)*cylinder_size;
- } else if (toupper(response[j]) == 'G') {
- num_sects = num_cyls(atof(response)*K*K*K)*cylinder_size;
- } else if (toupper(response[j]) == 'C') {
- num_sects = round_int(atof(response))*cylinder_size;
- } else if (toupper(response[j]) == 'S') {
- num_sects = round_int(atof(response));
- } else {
- num_sects = num_cyls(atof(response)*K*K)*cylinder_size;
- }
- }
-
- if (num_sects <= 0 ||
- num_sects > p_info[i].last_sector - p_info[i].first_sector + 1)
- return;
-
- move( COMMAND_LINE_Y, COMMAND_LINE_X ); clrtoeol();
- if (num_sects < p_info[i].last_sector - p_info[i].first_sector + 1) {
- /* Determine where inside free space to put partition.
- */
- static struct MenuItem menuPlace[]=
- {
- { 'b', N_("Beginning"), N_("Add partition at beginning of free space") },
- { 'e', N_("End"), N_("Add partition at end of free space") },
- { ESC, N_("Cancel"), N_("Don't create a partition") },
- { 0, NULL, NULL }
- };
- c = menuSimple( menuPlace, 0 );
- if (toupper(c) == 'B')
- last = first + num_sects - 1;
- else if (toupper(c) == 'E')
- first = last - num_sects + 1;
- else
- return;
- }
-
- if (IS_LOGICAL(num) && !is_extended(ext_info.id)) {
- /* We want to add a logical partition, but need to create an
- * extended partition first.
- */
- if ((ext = find_primary()) < 0) {
- print_warning(_("No room to create the extended partition"));
- return;
- }
- errmsg = 0;
- if (add_part(ext, DOS_EXTENDED, 0, first, last,
- (first == 0 ? sectors : 0), 0, &errmsg) && errmsg)
- print_warning(errmsg);
- first = ext_info.first_sector + ext_info.offset;
- }
-
- /* increment number of all partitions past this one */
- if (IS_LOGICAL(num)) {
-#if 0
- /* original text - ok, but fails when partitions not in disk order */
- for (j = i; j < num_parts; j++)
- if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num))
- p_info[j].num++;
-#else
- /* always ok */
- for (j = 0; j < num_parts; j++)
- if (p_info[j].id > 0 && p_info[j].num >= num)
- p_info[j].num++;
-#endif
- }
-
- /* Now we have a complete partition to ourselves */
- if (first == 0 || IS_LOGICAL(num))
- offset = sectors;
-
- errmsg = 0;
- if (add_part(num, id, flags, first, last, offset, 0, &errmsg) && errmsg)
- print_warning(errmsg);
+ return 0;
}
-static void
-get_kernel_geometry(void) {
-#ifdef HDIO_GETGEO
- struct hd_geometry geometry;
+static size_t menuitem_get_line(struct cfdisk *cf, size_t idx)
+{
+ size_t len = cf->menu->width + 4 + MENU_PADDING; /* item width */
+ size_t items = COLS / len; /* items per line */
- if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
- kern_heads = geometry.heads;
- kern_sectors = geometry.sectors;
- }
-#endif
+ return MENU_START_LINE + ((idx / items));
}
-static int
-said_yes(char answer) {
- char reply[2];
+static int menuitem_get_column(struct cfdisk *cf, size_t idx)
+{
+ size_t len = cf->menu->width + 4 + MENU_PADDING; /* item width */
+ size_t items = COLS / len; /* items per line */
+ size_t extra = items < cf->menu->nitems ? /* extra space on line */
+ COLS % len : /* - multi-line menu */
+ COLS - (cf->menu->nitems * len); /* - one line menu */
- reply[0] = answer;
- reply[1] = 0;
+ extra += MENU_PADDING; /* add padding after last item to extra */
- return (rpmatch(reply) == 1) ? 1 : 0;
+ if (idx < items)
+ return (idx * len) + (extra / 2);
+ return ((idx % items) * len) + (extra / 2);
}
-static void
-get_partition_table_geometry(partition_table *bufp) {
- struct partition *p;
- int i,h,s,hh,ss;
- int first = TRUE;
- int bad = FALSE;
-
- for (i=0; i<66; i++)
- if (bufp->c.b[446+i])
- goto nonz;
-
- /* zero table */
- if (!curses_started) {
- fatal(_("No partition table.\n"), 3);
- return;
- } else {
- mvaddstr(WARNING_START, 0,
- _("No partition table. Starting with zero table."));
- putchar(BELL);
- refresh();
- zero_table = TRUE;
- return;
- }
- nonz:
- if (bufp->p.magicflag[0] != PART_TABLE_FLAG0 ||
- bufp->p.magicflag[1] != PART_TABLE_FLAG1) {
- if (!curses_started)
- fatal(_("Bad signature on partition table"), 3);
-
- /* Matthew Wilcox */
- mvaddstr(WARNING_START, 0,
- _("Unknown partition table type"));
- mvaddstr(WARNING_START+1, 0,
- _("Do you wish to start with a zero table [y/N] ?"));
- putchar(BELL);
- refresh();
- {
- int cont = getch();
- if (cont == EOF || !said_yes(cont))
- die_x(3);
- }
- zero_table = TRUE;
- return;
- }
-
- hh = ss = 0;
- for (i=0; i<4; i++) {
- p = &(bufp->p.part[i]);
- if (p->sys_ind != 0) {
- h = p->end_head + 1;
- s = (p->end_sector & 077);
- if (first) {
- hh = h;
- ss = s;
- first = FALSE;
- } else if (hh != h || ss != s)
- bad = TRUE;
- }
- }
+static struct cfdisk_menudesc *menu_get_menuitem(struct cfdisk *cf, size_t idx)
+{
+ struct cfdisk_menudesc *d;
+ size_t i;
- if (!first && !bad) {
- pt_heads = hh;
- pt_sectors = ss;
+ for (i = 0, d = cf->menu->desc; d->name; d++) {
+ if (cf->menu->ignore && strchr(cf->menu->ignore, d->key))
+ continue;
+ if (i++ == idx)
+ return d;
}
-}
-static void
-decide_on_geometry(void) {
- heads = (user_heads ? user_heads :
- pt_heads ? pt_heads :
- kern_heads ? kern_heads : 255);
- sectors = (user_sectors ? user_sectors :
- pt_sectors ? pt_sectors :
- kern_sectors ? kern_sectors : 63);
- cylinder_size = heads*sectors;
- cylinders = actual_size/cylinder_size;
- if (user_cylinders > 0)
- cylinders = user_cylinders;
-
- if (cylinder_size * cylinders > actual_size)
- print_warning(_("You specified more cylinders than fit on disk"));
+ return NULL;
}
-static void
-clear_p_info(void) {
- num_parts = 1;
- p_info[0].first_sector = 0;
- p_info[0].last_sector = actual_size - 1;
- p_info[0].offset = 0;
- p_info[0].flags = 0;
- p_info[0].id = FREE_SPACE;
- p_info[0].num = PRI_OR_LOG;
-
- ext_info.first_sector = 0;
- ext_info.last_sector = 0;
- ext_info.offset = 0;
- ext_info.flags = 0;
- ext_info.id = FREE_SPACE;
- ext_info.num = PRIMARY;
+static void ui_draw_menuitem(struct cfdisk *cf,
+ struct cfdisk_menudesc *d,
+ size_t idx)
+{
+ char buf[80 * MB_CUR_MAX];
+ const char *name;
+ size_t width = cf->menu->width + 2; /* 2 = blank around string */
+ int ln, cl;
+
+ name = _(d->name);
+ mbsalign(name, buf, sizeof(buf), &width, MBS_ALIGN_CENTER, 0);
+
+ ln = menuitem_get_line(cf, idx);
+ cl = menuitem_get_column(cf, idx);
+
+ DBG(FRONTEND, dbgprint("ui: menuitem: cl=%d, ln=%d, item='%s'",
+ cl, ln, buf));
+
+ if (cf->menu_idx == idx) {
+ standout();
+ mvprintw(ln, cl, "[%s]", buf);
+ standend();
+ if (d->desc)
+ ui_print_center(LINES - 1, d->desc);
+ } else
+ mvprintw(ln, cl, "[%s]", buf);
}
-static void
-fill_p_info(void) {
- int pn, i;
- long long bs, bsz;
- unsigned long long llsectors;
- struct partition *p;
- partition_table buffer;
- partition_info tmp_ext;
-
- memset(&tmp_ext, 0, sizeof tmp_ext);
- tmp_ext.id = FREE_SPACE;
- tmp_ext.num = PRIMARY;
-
- if ((fd = open(disk_device, O_RDWR)) < 0) {
- if ((fd = open(disk_device, O_RDONLY)) < 0)
- fatal(_("Cannot open disk drive"), 2);
- opentype = O_RDONLY;
- print_warning(_("Opened disk read-only - you have no permission to write"));
- if (curses_started) {
- refresh();
- getch();
- clear_warning();
- }
- } else
- opentype = O_RDWR;
- opened = TRUE;
-
-#ifdef BLKFLSBUF
- /* Blocks are visible in more than one way:
- e.g. as block on /dev/hda and as block on /dev/hda3
- By a bug in the Linux buffer cache, we will see the old
- contents of /dev/hda when the change was made to /dev/hda3.
- In order to avoid this, discard all blocks on /dev/hda.
- Note that partition table blocks do not live in /dev/hdaN,
- so this only plays a role if we want to show volume labels. */
- ioctl(fd, BLKFLSBUF); /* ignore errors */
- /* e.g. Permission Denied */
-#endif
-
- if (blkdev_get_sectors(fd, &llsectors) == -1)
- fatal(_("Cannot get disk size"), 3);
- actual_size = llsectors;
-
- read_sector(buffer.c.b, 0);
-
- get_kernel_geometry();
-
- if (!zero_table || use_partition_table_geometry)
- get_partition_table_geometry(& buffer);
-
- decide_on_geometry();
-
- clear_p_info();
-
- if (!zero_table) {
- char *errmsg = "";
+static void ui_draw_menu(struct cfdisk *cf)
+{
+ struct cfdisk_menudesc *d;
+ size_t i = 0;
- for (i = 0; i < 4; i++) {
- p = & buffer.p.part[i];
- bs = get_start_sect(p);
- bsz = get_nr_sects(p);
+ assert(cf);
+ assert(cf->menu);
- if (p->sys_ind > 0 &&
- add_part(i, p->sys_ind, p->boot_ind,
- ((bs <= sectors) ? 0 : bs), bs + bsz - 1,
- ((bs <= sectors) ? bs : 0), 1, &errmsg)) {
- char *bad = _("Bad primary partition");
- char *msg = (char *) xmalloc(strlen(bad) + strlen(errmsg) + 30);
- sprintf(msg, "%s %d: %s", bad, i + 1, errmsg);
- fatal(msg, 4);
- }
- if (is_extended(buffer.p.part[i].sys_ind))
- tmp_ext = ext_info;
- }
+ DBG(FRONTEND, dbgprint("ui: menu: draw start"));
- if (is_extended(tmp_ext.id)) {
- ext_info = tmp_ext;
- logical_sectors[logical] =
- ext_info.first_sector + ext_info.offset;
- read_sector(buffer.c.b, logical_sectors[logical++]);
- i = 4;
- do {
- for (pn = 0;
- pn < 4 && (!buffer.p.part[pn].sys_ind ||
- is_extended(buffer.p.part[pn].sys_ind));
- pn++);
-
- if (pn < 4) {
- p = & buffer.p.part[pn];
- bs = get_start_sect(p);
- bsz = get_nr_sects(p);
-
- if (add_part(i++, p->sys_ind, p->boot_ind,
- logical_sectors[logical-1],
- logical_sectors[logical-1] + bs + bsz - 1,
- bs, 1, &errmsg)) {
- char *bad = _("Bad logical partition");
- char *msg = (char *) xmalloc(strlen(bad) + strlen(errmsg) + 30);
- sprintf(msg, "%s %d: %s", bad, i, errmsg);
- fatal(msg, 4);
- }
- }
+ menu_update_ignore(cf);
- for (pn = 0;
- pn < 4 && !is_extended(buffer.p.part[pn].sys_ind);
- pn++);
- if (pn < 4) {
- p = & buffer.p.part[pn];
- bs = get_start_sect(p);
- logical_sectors[logical] = ext_info.first_sector
- + ext_info.offset + bs;
- read_sector(buffer.c.b, logical_sectors[logical++]);
- }
- } while (pn < 4 && logical < MAXIMUM_PARTS-4);
- }
- }
-}
+ while ((d = menu_get_menuitem(cf, i)))
+ ui_draw_menuitem(cf, d, i++);
-static void
-fill_part_table(struct partition *p, partition_info *pi) {
- long long begin;
-
- p->boot_ind = pi->flags;
- p->sys_ind = pi->id;
- begin = pi->first_sector + pi->offset;
- if (IS_LOGICAL(pi->num))
- set_start_sect(p,pi->offset);
- else
- set_start_sect(p,begin);
- set_nr_sects(p, pi->last_sector - begin + 1);
- set_hsc_begin(p, begin);
- set_hsc_end(p, pi->last_sector);
+ DBG(FRONTEND, dbgprint("ui: menu: draw end."));
}
-static void
-fill_primary_table(partition_table *buffer) {
- int i;
-
- /* Zero out existing table */
- for (i = 0x1BE; i < SECTOR_SIZE; i++)
- buffer->c.b[i] = 0;
-
- for (i = 0; i < num_parts; i++)
- if (IS_PRIMARY(p_info[i].num))
- fill_part_table(&(buffer->p.part[p_info[i].num]), &(p_info[i]));
+static void ui_menu_goto(struct cfdisk *cf, int where)
+{
+ struct cfdisk_menudesc *d;
+ size_t old;
+
+ if (where < 0)
+ where = cf->menu->nitems - 1;
+ else if ((size_t) where > cf->menu->nitems - 1)
+ where = 0;
+ if ((size_t) where == cf->menu_idx)
+ return;
- if (is_extended(ext_info.id))
- fill_part_table(&(buffer->p.part[ext_info.num]), &ext_info);
+ old = cf->menu_idx;
+ cf->menu_idx = where;
- buffer->p.magicflag[0] = PART_TABLE_FLAG0;
- buffer->p.magicflag[1] = PART_TABLE_FLAG1;
-}
+ d = menu_get_menuitem(cf, old);
+ ui_draw_menuitem(cf, d, old);
-static void
-fill_logical_table(partition_table *buffer, partition_info *pi) {
- struct partition *p;
- int i;
-
- for (i = 0; i < logical && pi->first_sector != logical_sectors[i]; i++);
- if (i == logical || buffer->p.magicflag[0] != PART_TABLE_FLAG0
- || buffer->p.magicflag[1] != PART_TABLE_FLAG1)
- for (i = 0; i < SECTOR_SIZE; i++)
- buffer->c.b[i] = 0;
-
- /* Zero out existing table */
- for (i = 0x1BE; i < SECTOR_SIZE; i++)
- buffer->c.b[i] = 0;
-
- fill_part_table(&(buffer->p.part[0]), pi);
-
- for (i = 0;
- i < num_parts && pi->num != p_info[i].num - 1;
- i++);
-
- if (i < num_parts) {
- p = &(buffer->p.part[1]);
- pi = &(p_info[i]);
-
- p->boot_ind = 0;
- p->sys_ind = DOS_EXTENDED;
- set_start_sect(p, pi->first_sector - ext_info.first_sector - ext_info.offset);
- set_nr_sects(p, pi->last_sector - pi->first_sector + 1);
- set_hsc_begin(p, pi->first_sector);
- set_hsc_end(p, pi->last_sector);
- }
-
- buffer->p.magicflag[0] = PART_TABLE_FLAG0;
- buffer->p.magicflag[1] = PART_TABLE_FLAG1;
+ d = menu_get_menuitem(cf, where);
+ ui_draw_menuitem(cf, d, where);
}
-static void
-write_part_table(void) {
- int i, ct, done = FALSE, len;
- partition_table buffer;
- struct stat s;
- int is_bdev;
- char response[LINE_LENGTH];
-
- if (opentype == O_RDONLY) {
- print_warning(_("Opened disk read-only - you have no permission to write"));
- refresh();
- getch();
- clear_warning();
- return;
- }
-
- is_bdev = 0;
- if(fstat(fd, &s) == 0 && S_ISBLK(s.st_mode))
- is_bdev = 1;
-
- if (is_bdev) {
- print_warning(_("Warning!! This may destroy data on your disk!"));
-
- while (!done) {
- mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
- _("Are you sure you want to write the partition table "
- "to disk? (yes or no): "));
- len = get_string(response, LINE_LENGTH, NULL);
- clear_warning();
- if (len == GS_ESCAPE)
- return;
- else if (strcasecmp(response, _("no")) == 0 ||
- strcasecmp(response, "no") == 0) {
- print_warning(_("Did not write partition table to disk"));
- return;
- } else if (strcasecmp(response, _("yes")) == 0 ||
- strcasecmp(response, "yes") == 0)
- done = TRUE;
- else
- print_warning(_("Please enter `yes' or `no'"));
- }
-
- clear_warning();
- print_warning(_("Writing partition table to disk..."));
- refresh();
- }
-
- read_sector(buffer.c.b, 0);
- fill_primary_table(&buffer);
- write_sector(buffer.c.b, 0);
-
- for (i = 0; i < num_parts; i++)
- if (IS_LOGICAL(p_info[i].num)) {
- read_sector(buffer.c.b, p_info[i].first_sector);
- fill_logical_table(&buffer, &(p_info[i]));
- write_sector(buffer.c.b, p_info[i].first_sector);
- }
-
- if (is_bdev) {
-#ifdef BLKRRPART
- sync();
- if (!ioctl(fd,BLKRRPART))
- changed = TRUE;
-#endif
- sync();
-
- clear_warning();
- if (changed)
- print_warning(_("Wrote partition table to disk"));
- else
- print_warning(_("Wrote partition table, but re-read table failed. Run partprobe(8), kpartx(8) or reboot to update table."));
- } else
- print_warning(_("Wrote partition table to disk"));
-
- /* Check: unique bootable primary partition? */
- ct = 0;
- for (i = 0; i < num_parts; i++)
- if (IS_PRIMARY(i) && p_info[i].flags == ACTIVE_FLAG)
- ct++;
- if (ct == 0)
- print_warning(_("No primary partitions are marked bootable. DOS MBR cannot boot this."));
- if (ct > 1)
- print_warning(_("More than one primary partition is marked bootable. DOS MBR cannot boot this."));
+static int ui_menu_action(struct cfdisk *cf, int key)
+{
+ return 0;
}
-static void
-fp_printf(FILE *fp, char *format, ...) {
- va_list args;
- char buf[1024];
- int y, x __attribute__((unused));
-
- va_start(args, format);
- vsnprintf(buf, sizeof(buf), format, args);
- va_end(args);
-
- if (fp == NULL) {
- /* The following works best if the string to be printed has at
- most only one newline. */
- printw("%s", buf);
- getyx(stdscr, y, x);
- if (y >= COMMAND_LINE_Y-2) {
- menuContinue();
- erase();
- move(0, 0);
- }
- } else
- fprintf(fp, "%s", buf);
-}
+static void ui_draw_partition(struct cfdisk *cf, size_t i)
+{
+ int ln = TABLE_START_LINE + 1 + i; /* skip table header */
+ int cl = ARROW_CURSOR_WIDTH; /* we need extra space for cursor */
-#define MAX_PER_LINE 16
-static void
-print_file_buffer(FILE *fp, unsigned char *buffer) {
- int i,l;
-
- for (i = 0, l = 0; i < SECTOR_SIZE; i++, l++) {
- if (l == 0)
- fp_printf(fp, "0x%03X:", i);
- fp_printf(fp, " %02X", buffer[i]);
- if (l == MAX_PER_LINE - 1) {
- fp_printf(fp, "\n");
- l = -1;
- }
- }
- if (l > 0)
- fp_printf(fp, "\n");
- fp_printf(fp, "\n");
-}
+ DBG(FRONTEND, dbgprint("ui: draw partition %zu", i));
-static void
-print_raw_table(void) {
- int i, to_file;
- partition_table buffer;
- char fname[LINE_LENGTH];
- FILE *fp;
-
- if (print_only) {
- fp = stdout;
- to_file = TRUE;
- } else {
- mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
- _("Enter filename or press RETURN to display on screen: "));
-
- if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0)
- return;
-
- if (to_file) {
- if ((fp = fopen(fname, "w")) == NULL) {
- char errstr[LINE_LENGTH];
- snprintf(errstr, sizeof(errstr),
- _("cannot open %s"), fname);
- print_warning(errstr);
- return;
- }
+ if (cf->lines_idx == i) {
+ standout();
+ mvaddstr(ln, 0, ARROW_CURSOR_STRING);
+ mvaddstr(ln, cl, cf->lines[i + 1]);
+ standend();
} else {
- fp = NULL;
- erase();
- move(0, 0);
- }
- }
-
- fp_printf(fp, _("Disk Drive: %s\n"), disk_device);
-
- fp_printf(fp, _("Sector 0:\n"));
- read_sector(buffer.c.b, 0);
- fill_primary_table(&buffer);
- print_file_buffer(fp, buffer.c.b);
-
- for (i = 0; i < num_parts; i++)
- if (IS_LOGICAL(p_info[i].num)) {
- fp_printf(fp, _("Sector %d:\n"), p_info[i].first_sector);
- read_sector(buffer.c.b, p_info[i].first_sector);
- fill_logical_table(&buffer, &(p_info[i]));
- print_file_buffer(fp, buffer.c.b);
+ mvaddstr(ln, 0, ARROW_CURSOR_DUMMY);
+ mvaddstr(ln, cl, cf->lines[i + 1]);
}
- if (to_file) {
- if (!print_only)
- if (close_stream(fp) != 0) {
- char errstr[LINE_LENGTH];
- snprintf(errstr, sizeof(errstr), _("write failed: %s"), fname);
- print_warning(errstr);
- }
- } else {
- menuContinue();
- }
-}
-
-static void
-print_p_info_entry(FILE *fp, partition_info *p) {
- long long size;
- char part_str[40];
-
- if (p->id == UNUSABLE)
- fp_printf(fp, _(" None "));
- else if (p->id == FREE_SPACE && p->num == PRI_OR_LOG)
- fp_printf(fp, _(" Pri/Log"));
- else if (p->id == FREE_SPACE && p->num == PRIMARY)
- fp_printf(fp, _(" Primary"));
- else if (p->id == FREE_SPACE && p->num == LOGICAL)
- fp_printf(fp, _(" Logical"));
- else
- fp_printf(fp, "%2d %-7.7s", p->num+1,
- IS_LOGICAL(p->num) ? _("Logical") : _("Primary"));
-
- fp_printf(fp, " ");
-
- fp_printf(fp, "%11lld%c", p->first_sector,
- ((p->first_sector/cylinder_size) !=
- ((float)p->first_sector/cylinder_size) ?
- '*' : ' '));
-
- fp_printf(fp, "%11lld%c", p->last_sector,
- (((p->last_sector+1)/cylinder_size) !=
- ((float)(p->last_sector+1)/cylinder_size) ?
- '*' : ' '));
-
- fp_printf(fp, "%6ld%c", p->offset,
- ((((p->first_sector == 0 || IS_LOGICAL(p->num)) &&
- (p->offset != sectors)) ||
- (p->first_sector != 0 && IS_PRIMARY(p->num) &&
- p->offset != 0)) ?
- '#' : ' '));
-
- size = p->last_sector - p->first_sector + 1;
- fp_printf(fp, "%11lld%c", size,
- ((size/cylinder_size) != ((float)size/cylinder_size) ?
- '*' : ' '));
-
- /* fp_printf(fp, " "); */
-
- if (p->id == UNUSABLE)
- sprintf(part_str, "%.15s", _("Unusable"));
- else if (p->id == FREE_SPACE)
- sprintf(part_str, "%.15s", _("Free Space"));
- else if (partition_type_name(p->id))
- sprintf(part_str, "%.15s (%02X)", _(partition_type_name(p->id)), p->id);
- else
- sprintf(part_str, "%.15s (%02X)", _("Unknown"), p->id);
- fp_printf(fp, "%-20.20s", part_str);
-
- fp_printf(fp, " ");
-
- if (p->flags == ACTIVE_FLAG)
- fp_printf(fp, _("Boot"), p->flags);
- else if (p->flags != 0)
- fp_printf(fp, _("(%02X)"), p->flags);
- else
- fp_printf(fp, _("None"), p->flags);
-
- fp_printf(fp, "\n");
-}
-
-static void
-print_p_info(void) {
- char fname[LINE_LENGTH];
- FILE *fp;
- int i, to_file, pext = is_extended(ext_info.id);
-
- if (print_only) {
- fp = stdout;
- to_file = TRUE;
- } else {
- mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
- _("Enter filename or press RETURN to display on screen: "));
-
- if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0)
- return;
-
- if (to_file) {
- if ((fp = fopen(fname, "w")) == NULL) {
- char errstr[LINE_LENGTH];
- snprintf(errstr, LINE_LENGTH, _("cannot open %s"), fname);
- print_warning(errstr);
- return;
- }
- } else {
- fp = NULL;
- erase();
- move(0, 0);
- }
- }
-
- fp_printf(fp, _("Partition Table for %s\n"), disk_device);
- fp_printf(fp, "\n");
- fp_printf(fp, _(" First Last\n"));
- fp_printf(fp, _(" # Type Sector Sector Offset Length Filesystem Type (ID) Flag\n"));
- fp_printf(fp, _("-- ------- ----------- ----------- ------ ----------- -------------------- ----\n"));
-
- for (i = 0; i < num_parts; i++) {
- if (pext && (p_info[i].first_sector >= ext_info.first_sector)) {
- print_p_info_entry(fp,&ext_info);
- pext = FALSE;
- }
- print_p_info_entry(fp, &(p_info[i]));
- }
-
- if (to_file) {
- if (!print_only)
- if (close_stream(fp) != 0) {
- char errstr[LINE_LENGTH];
- snprintf(errstr, sizeof(errstr), _("write failed: %s"), fname);
- print_warning(errstr);
- }
- } else {
- menuContinue();
- }
}
-static void
-print_part_entry(FILE *fp, int num, partition_info *pi) {
- long long first = 0, start = 0, end = 0, size = 0;
- unsigned char ss, es, sh, eh;
- int sc, ec;
- int flags = 0, id = 0;
-
- ss = sh = es = eh = 0;
- sc = ec = 0;
+static int ui_draw_table(struct cfdisk *cf)
+{
+ int cl = ARROW_CURSOR_WIDTH;
+ size_t i, nparts = fdisk_table_get_nents(cf->table);
- if (pi != NULL) {
- flags = pi->flags;
- id = pi->id;
+ DBG(FRONTEND, dbgprint("ui: draw table"));
- if (IS_LOGICAL(num))
- first = pi->offset;
- else
- first = pi->first_sector + pi->offset;
+ if (cf->nlines - 2 < cf->lines_idx)
+ cf->lines_idx = cf->nlines - 2; /* don't count header */
- start = pi->first_sector + pi->offset;
- end = pi->last_sector;
- size = end - start + 1;
+ /* print header */
+ attron(A_BOLD);
+ mvaddstr(TABLE_START_LINE, cl, cf->lines[0]);
+ attroff(A_BOLD);
- set_hsc0(&sh, &ss, &sc, start);
- set_hsc0(&eh, &es, &ec, end);
- }
+ /* print partitions */
+ for (i = 0; i < nparts; i++)
+ ui_draw_partition(cf, i);
- fp_printf(fp, "%2d 0x%02X %4d %4d %5d 0x%02X %4d %4d %5d %11lld %11lld\n",
- num+1, flags, sh, ss, sc, id, eh, es, ec, first, size);
+ return 0;
}
+static int ui_table_goto(struct cfdisk *cf, int where)
+{
+ size_t old;
+ size_t nparts = fdisk_table_get_nents(cf->table);
-static void
-print_part_table(void) {
- int i, j, to_file;
- char fname[LINE_LENGTH];
- FILE *fp;
+ DBG(FRONTEND, dbgprint("ui: goto table %d", where));
- if (print_only) {
- fp = stdout;
- to_file = TRUE;
- } else {
- mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
- _("Enter filename or press RETURN to display on screen: "));
+ if (where < 0)
+ where = 0;
+ else if ((size_t) where > nparts - 1)
+ where = nparts - 1;
- if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0)
- return;
+ if ((size_t) where == cf->lines_idx)
+ return 0;
- if (to_file) {
- if ((fp = fopen(fname, "w")) == NULL) {
- char errstr[LINE_LENGTH];
- snprintf(errstr, LINE_LENGTH, _("cannot open %s"), fname);
- print_warning(errstr);
- return;
- }
- } else {
- fp = NULL;
- erase();
- move(0, 0);
- }
- }
-
- fp_printf(fp, _("Partition Table for %s\n"), disk_device);
- fp_printf(fp, "\n");
- /* Three-line heading. Read "Start Sector" etc vertically. */
- fp_printf(fp, _(" ---Starting---- ----Ending----- Start Number of\n"));
- fp_printf(fp, _(" # Flags Head Sect Cyl ID Head Sect Cyl Sector Sectors\n"));
- fp_printf(fp, _("-- ----- ---- ---- ----- ---- ---- ---- ----- ----------- -----------\n"));
-
- for (i = 0; i < 4; i++) {
- for (j = 0;
- j < num_parts && (p_info[j].id <= 0 || p_info[j].num != i);
- j++);
- if (j < num_parts) {
- print_part_entry(fp, i, &(p_info[j]));
- } else if (is_extended(ext_info.id) && ext_info.num == i) {
- print_part_entry(fp, i, &ext_info);
- } else {
- print_part_entry(fp, i, NULL);
- }
- }
-
- for (i = 0; i < num_parts; i++)
- if (IS_LOGICAL(p_info[i].num))
- print_part_entry(fp, p_info[i].num, &(p_info[i]));
-
- if (to_file) {
- if (!print_only)
- if (close_stream(fp) != 0) {
- char errstr[LINE_LENGTH];
- snprintf(errstr, sizeof(errstr), _("write failed: %s"), fname);
- print_warning(errstr);
- }
- } else {
- menuContinue();
- }
-}
+ old = cf->lines_idx;
+ cf->lines_idx = where;
-static void
-print_tables(void) {
- int done = FALSE;
-
- static struct MenuItem menuFormat[]=
- {
- { 'r', N_("Raw"), N_("Print the table using raw data format") },
- { 's', N_("Sectors"), N_("Print the table ordered by sectors") },
- { 't', N_("Table"), N_("Just print the partition table") },
- { ESC, N_("Cancel"), N_("Don't print the table") },
- { 0, NULL, NULL }
- };
-
- while (!done)
- switch ( toupper(menuSimple( menuFormat, 2)) ) {
- case 'R':
- print_raw_table();
- done = TRUE;
- break;
- case 'S':
- print_p_info();
- done = TRUE;
- break;
- case 'T':
- print_part_table();
- done = TRUE;
- break;
- case ESC:
- done = TRUE;
- break;
- }
+ ui_draw_partition(cf, old); /* cleanup old */
+ ui_draw_partition(cf, where); /* draw new */
+ ui_draw_menu(cf);
+ refresh();
+ return 0;
}
-#define END_OF_HELP "EOHS!"
-static void
-display_help(void) {
- char *help_text[] = {
- N_("Help Screen for cfdisk"),
- "",
- N_("This is cfdisk, a curses based disk partitioning program, which"),
- N_("allows you to create, delete and modify partitions on your hard"),
- N_("disk drive."),
- "",
- N_("Copyright (C) 1994-1999 Kevin E. Martin & aeb"),
- "",
- N_("Command Meaning"),
- N_("------- -------"),
- N_(" b Toggle bootable flag of the current partition"),
- N_(" d Delete the current partition"),
- N_(" g Change cylinders, heads, sectors-per-track parameters"),
- N_(" WARNING: This option should only be used by people who"),
- N_(" know what they are doing."),
- N_(" h Print this screen"),
- N_(" m Maximize disk usage of the current partition"),
- N_(" Note: This may make the partition incompatible with"),
- N_(" DOS, OS/2, ..."),
- N_(" n Create new partition from free space"),
- N_(" p Print partition table to the screen or to a file"),
- N_(" There are several different formats for the partition"),
- N_(" that you can choose from:"),
- N_(" r - Raw data (exactly what would be written to disk)"),
- N_(" s - Table ordered by sectors"),
- N_(" t - Table in raw format"),
- N_(" q Quit program without writing partition table"),
- N_(" t Change the filesystem type"),
- N_(" u Change units of the partition size display"),
- N_(" Rotates through MB, sectors and cylinders"),
- N_(" W Write partition table to disk (must enter upper case W)"),
- N_(" Since this might destroy data on the disk, you must"),
- N_(" either confirm or deny the write by entering `yes' or"),
- N_(" `no'"),
- N_("Up Arrow Move cursor to the previous partition"),
- N_("Down Arrow Move cursor to the next partition"),
- N_("CTRL-L Redraws the screen"),
- N_(" ? Print this screen"),
- "",
- N_("Note: All of the commands can be entered with either upper or lower"),
- N_("case letters (except for Writes)."),
- END_OF_HELP
- };
-
- int cur_line = 0;
- FILE *fp = NULL;
-
- erase();
- move(0, 0);
- while (strcmp(help_text[cur_line], END_OF_HELP)) {
- if (help_text[cur_line][0])
- fp_printf(fp, "%s\n", _(help_text[cur_line]));
+static int ui_refresh(struct cfdisk *cf)
+{
+ char *id = NULL;
+ uint64_t bytes = cf->cxt->total_sectors * cf->cxt->sector_size;
+ char *strsz = size_to_human_string(SIZE_SUFFIX_SPACE
+ | SIZE_SUFFIX_3LETTER, bytes);
+ erase();
+
+ if (!cf->ui_enabled)
+ return -EINVAL;
+
+ /* header */
+ attron(A_BOLD);
+ ui_print_center(0, _("Disk: %s"), cf->cxt->dev_path);
+ attroff(A_BOLD);
+ ui_print_center(1, _("Size: %s, %ju bytes, %ju sectors"),
+ strsz, bytes, (uintmax_t) cf->cxt->total_sectors);
+ if (fdisk_get_disklabel_id(cf->cxt, &id) == 0 && id)
+ ui_print_center(2, _("Label: %s, identifier: %s"),
+ cf->cxt->label->name, id);
else
- fp_printf(fp, "\n");
- cur_line++;
- }
- menuContinue();
-}
+ ui_print_center(2, _("Label: %s"));
+ free(strsz);
-static int
-change_geometry(void) {
- int ret_val = FALSE;
- int done = FALSE;
- char def[LINE_LENGTH];
- char response[LINE_LENGTH];
- long long tmp_val;
- int i;
-
- while (!done) {
- static struct MenuItem menuGeometry[]=
- {
- { 'c', N_("Cylinders"), N_("Change cylinder geometry") },
- { 'h', N_("Heads"), N_("Change head geometry") },
- { 's', N_("Sectors"), N_("Change sector geometry") },
- { 'd', N_("Done"), N_("Done with changing geometry") },
- { 0, NULL, NULL }
- };
- move(COMMAND_LINE_Y, COMMAND_LINE_X);
- clrtoeol();
+ ui_draw_table(cf);
+ ui_draw_menu(cf);
refresh();
-
- clear_warning();
-
- switch (toupper( menuSimple(menuGeometry, 3) )) {
- case 'C':
- sprintf(def, "%llu", actual_size/cylinder_size);
- mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
- _("Enter the number of cylinders: "));
- i = get_string(response, LINE_LENGTH, def);
- if (i == GS_DEFAULT) {
- user_cylinders = actual_size/cylinder_size;
- ret_val = TRUE;
- } else if (i > 0) {
- tmp_val = atoll(response);
- if (tmp_val > 0) {
- user_cylinders = tmp_val;
- ret_val = TRUE;
- } else
- print_warning(_("Illegal cylinders value"));
- }
- break;
- case 'H':
- sprintf(def, "%d", heads);
- mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
- _("Enter the number of heads: "));
- if (get_string(response, LINE_LENGTH, def) > 0) {
- tmp_val = atoll(response);
- if (tmp_val > 0 && tmp_val <= MAX_HEADS) {
- user_heads = tmp_val;
- ret_val = TRUE;
- } else
- print_warning(_("Illegal heads value"));
- }
- break;
- case 'S':
- sprintf(def, "%d", sectors);
- mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
- _("Enter the number of sectors per track: "));
- if (get_string(response, LINE_LENGTH, def) > 0) {
- tmp_val = atoll(response);
- if (tmp_val > 0 && tmp_val <= MAX_SECTORS) {
- user_sectors = tmp_val;
- ret_val = TRUE;
- } else
- print_warning(_("Illegal sectors value"));
- }
- break;
- case ESC:
- case 'D':
- done = TRUE;
- break;
- default:
- putchar(BELL);
- break;
- }
-
- if (ret_val) {
- decide_on_geometry();
- draw_screen();
- }
- }
-
- if (ret_val) {
- long long disk_end;
-
- disk_end = actual_size-1;
-
- if (p_info[num_parts-1].last_sector > disk_end) {
- while (p_info[num_parts-1].first_sector > disk_end) {
- if (p_info[num_parts-1].id == FREE_SPACE ||
- p_info[num_parts-1].id == UNUSABLE)
- remove_part(num_parts-1);
- else
- del_part(num_parts-1);
- }
-
- p_info[num_parts-1].last_sector = disk_end;
-
- if (ext_info.last_sector > disk_end)
- ext_info.last_sector = disk_end;
- } else if (p_info[num_parts-1].last_sector < disk_end) {
- if (p_info[num_parts-1].id == FREE_SPACE ||
- p_info[num_parts-1].id == UNUSABLE) {
- p_info[num_parts-1].last_sector = disk_end;
- } else {
- insert_empty_part(num_parts,
- p_info[num_parts-1].last_sector+1,
- disk_end);
- }
- }
-
- /* Make sure the partitions are correct */
- check_part_info();
- }
-
- return ret_val;
-}
-
-static void
-change_id(int i) {
- char id[LINE_LENGTH], def[LINE_LENGTH];
- int num_types = 0;
- int num_across, num_down;
- int len, new_id = ((p_info[i].id == LINUX) ? LINUX_SWAP : LINUX);
- int y_start, y_end, row, row_min, row_max, row_offset, j, needmore;
-
- for (j = 1; i386_sys_types[j].name; j++) ;
- num_types = j-1; /* do not count the Empty type */
-
- num_across = COLS/COL_ID_WIDTH;
- num_down = (((float)num_types)/num_across + 1);
- y_start = COMMAND_LINE_Y - 1 - num_down;
- if (y_start < 1) {
- y_start = 1;
- y_end = COMMAND_LINE_Y - 2;
- } else {
- if (y_start > DISK_TABLE_START+cur_part+4)
- y_start = DISK_TABLE_START+cur_part+4;
- y_end = y_start + num_down - 1;
- }
-
- row_min = 1;
- row_max = COMMAND_LINE_Y - 2;
- row_offset = 0;
- do {
- for (j = y_start - 1; j <= y_end + 1; j++) {
- move(j, 0);
- clrtoeol();
- }
- needmore = 0;
- for (j = 1; i386_sys_types[j].name; j++) {
- row = y_start + (j-1) % num_down - row_offset;
- if (row >= row_min && row <= row_max) {
- move(row, ((j-1)/num_down)*COL_ID_WIDTH + 1);
- printw("%02X %-20.20s",
- i386_sys_types[j].type,
- _(i386_sys_types[j].name));
- }
- if (row > row_max)
- needmore = 1;
- }
- if (needmore)
- menuContinue();
- row_offset += (row_max - row_min + 1);
- } while(needmore);
-
- sprintf(def, "%02X", new_id);
- mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, _("Enter filesystem type: "));
- if ((len = get_string(id, 3, def)) <= 0 && len != GS_DEFAULT)
- return;
-
- if (len != GS_DEFAULT) {
- if (!isxdigit(id[0]))
- return;
- new_id = (isdigit(id[0]) ? id[0] - '0' : tolower(id[0]) - 'a' + 10);
- if (len == 2) {
- if (isxdigit(id[1]))
- new_id = new_id*16 +
- (isdigit(id[1]) ? id[1] - '0' : tolower(id[1]) - 'a' + 10);
- else
- return;
- }
- }
-
- if (new_id == 0)
- print_warning(_("Cannot change FS Type to empty"));
- else if (is_extended(new_id))
- print_warning(_("Cannot change FS Type to extended"));
- else
- p_info[i].id = new_id;
+ return 0;
}
-static void
-draw_partition(int i) {
- int j;
- int y = i + DISK_TABLE_START + 2 - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN;
- char *t;
- long long size;
- double fsize;
-
- if (!arrow_cursor) {
- move(y, 0);
- for (j = 0; j < COLS; j++)
- addch(' ');
- }
-
- if (p_info[i].id > 0) {
- char *dbn = my_basename(disk_device);
- int l = strlen(dbn);
- int digit_last = isdigit(dbn[l-1]);
-
- mvprintw(y, NAME_START,
- "%s%s%d", dbn, (digit_last ? "p" : ""),
- p_info[i].num+1);
- if (p_info[i].flags) {
- if (p_info[i].flags == ACTIVE_FLAG)
- mvaddstr(y, FLAGS_START, _("Boot"));
- else
- mvprintw(y, FLAGS_START, _("Unk(%02X)"), p_info[i].flags);
- if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) {
- if (p_info[i].offset != sectors)
- addstr(_(", NC"));
- } else {
- if (p_info[i].offset != 0)
- addstr(_(", NC"));
- }
- } else {
- if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) {
- if (p_info[i].offset != sectors)
- mvaddstr(y, FLAGS_START, _("NC"));
- } else {
- if (p_info[i].offset != 0)
- mvaddstr(y, FLAGS_START, _("NC"));
- }
- }
- }
- mvaddstr(y, PTYPE_START,
- (p_info[i].id == UNUSABLE ? "" :
- (IS_LOGICAL(p_info[i].num) ? _("Logical") :
- (p_info[i].num >= 0 ? _("Primary") :
- (p_info[i].num == PRI_OR_LOG ? _("Pri/Log") :
- (p_info[i].num == PRIMARY ? _("Primary") : _("Logical")))))));
-
- t = partition_type_text(i);
- if (t)
- mvaddstr(y, FSTYPE_START, t);
- else
- mvprintw(y, FSTYPE_START, _("Unknown (%02X)"), p_info[i].id);
-
- if (p_info[i].volume_label[0]) {
- int l = strlen(p_info[i].volume_label);
- int s = SIZE_START-5-l;
- mvprintw(y, (s > LABEL_START) ? LABEL_START : s,
- " [%s] ", p_info[i].volume_label);
- }
-
- size = p_info[i].last_sector - p_info[i].first_sector + 1;
- fsize = (double) size * SECTOR_SIZE;
- if (display_units == SECTORS)
- mvprintw(y, SIZE_START, "%11lld", size);
- else if (display_units == CYLINDERS)
- mvprintw(y, SIZE_START, "%11lld", size/cylinder_size);
- else if (display_units == MEGABYTES)
- mvprintw(y, SIZE_START, "%11.2f", ceiling((100*fsize)/(K*K))/100);
- else if (display_units == GIGABYTES)
- mvprintw(y, SIZE_START, "%11.2f", ceiling((100*fsize)/(K*K*K))/100);
- if (size % cylinder_size != 0 ||
- p_info[i].first_sector % cylinder_size != 0)
- mvprintw(y, COLUMNS-1, "*");
-}
+static int ui_run(struct cfdisk *cf)
+{
+ int rc;
-static void
-init_const(void) {
- if (!defined) {
- NAME_START = (((float)NAME_START)/COLUMNS)*COLS;
- FLAGS_START = (((float)FLAGS_START)/COLUMNS)*COLS;
- PTYPE_START = (((float)PTYPE_START)/COLUMNS)*COLS;
- FSTYPE_START = (((float)FSTYPE_START)/COLUMNS)*COLS;
- LABEL_START = (((float)LABEL_START)/COLUMNS)*COLS;
- SIZE_START = (((float)SIZE_START)/COLUMNS)*COLS;
- COMMAND_LINE_X = (((float)COMMAND_LINE_X)/COLUMNS)*COLS;
-
- COMMAND_LINE_Y = LINES - 4;
- WARNING_START = LINES - 2;
-
- if ((NUM_ON_SCREEN = COMMAND_LINE_Y - DISK_TABLE_START - 3) <= 0)
- NUM_ON_SCREEN = 1;
-
- COLUMNS = COLS;
- defined = TRUE;
- }
-}
+ DBG(FRONTEND, dbgprint("ui: start COLS=%d, LINES=%d", COLS, LINES));
-static void
-draw_screen(void) {
- int i;
- char *line;
+ menu_push(cf, CFDISK_MENU_MAIN);
- line = (char *) xmalloc((COLS+1)*sizeof(char));
+ rc = ui_refresh(cf);
+ if (rc)
+ return rc;
- if (warning_last_time) {
- for (i = 0; i < COLS; i++) {
- move(WARNING_START, i);
- line[i] = inch();
- }
- line[COLS] = 0;
- }
-
- erase();
-
- if (warning_last_time)
- mvaddstr(WARNING_START, 0, line);
-
-
- snprintf(line, COLS+1, "cfdisk (%s)", PACKAGE_STRING);
- mvaddstr(HEADER_START, (COLS-strlen(line))/2, line);
- snprintf(line, COLS+1, _("Disk Drive: %s"), disk_device);
- mvaddstr(HEADER_START+2, (COLS-strlen(line))/2, line);
- {
- long long bytes = actual_size*(long long) SECTOR_SIZE;
- long long megabytes = bytes/(K*K);
-
- if (megabytes < 10000)
- sprintf(line, _("Size: %lld bytes, %lld MB"),
- bytes, megabytes);
- else
- sprintf(line, _("Size: %lld bytes, %lld.%lld GB"),
- bytes, megabytes/K, (10*megabytes/K)%10);
- }
- mvaddstr(HEADER_START+3, (COLS-strlen(line))/2, line);
- snprintf(line, COLS+1, _("Heads: %d Sectors per Track: %d Cylinders: %lld"),
- heads, sectors, cylinders);
- mvaddstr(HEADER_START+4, (COLS-strlen(line))/2, line);
-
- mvaddstr(DISK_TABLE_START, NAME_START, _("Name"));
- mvaddstr(DISK_TABLE_START, FLAGS_START, _("Flags"));
- mvaddstr(DISK_TABLE_START, PTYPE_START-1, _("Part Type"));
- mvaddstr(DISK_TABLE_START, FSTYPE_START, _("FS Type"));
- mvaddstr(DISK_TABLE_START, LABEL_START+1, _("[Label]"));
- if (display_units == SECTORS)
- mvaddstr(DISK_TABLE_START, SIZE_START, _(" Sectors"));
- else if (display_units == CYLINDERS)
- mvaddstr(DISK_TABLE_START, SIZE_START, _(" Cylinders"));
- else if (display_units == MEGABYTES)
- mvaddstr(DISK_TABLE_START, SIZE_START, _(" Size (MB)"));
- else if (display_units == GIGABYTES)
- mvaddstr(DISK_TABLE_START, SIZE_START, _(" Size (GB)"));
-
- move(DISK_TABLE_START+1, 1);
- for (i = 1; i < COLS-1; i++)
- addch('-');
-
- if (NUM_ON_SCREEN >= num_parts)
- for (i = 0; i < num_parts; i++)
- draw_partition(i);
- else
- for (i = (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN;
- i < NUM_ON_SCREEN + (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN &&
- i < num_parts;
- i++)
- draw_partition(i);
-
- free(line);
-}
+ do {
+ int key = getch();
-static void
-draw_cursor(int move) {
- if (move != 0 && (cur_part + move < 0 || cur_part + move >= num_parts)) {
- print_warning(_("No more partitions"));
- return;
- }
-
- if (arrow_cursor)
- mvaddstr(DISK_TABLE_START + cur_part + 2
- - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, " ");
- else
- draw_partition(cur_part);
-
- cur_part += move;
-
- if (((cur_part - move)/NUM_ON_SCREEN)*NUM_ON_SCREEN !=
- (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN)
- draw_screen();
-
- if (arrow_cursor)
- mvaddstr(DISK_TABLE_START + cur_part + 2
- - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, "-->");
- else {
- standout();
- draw_partition(cur_part);
- standend();
- }
-}
+ if (key == 'q')
+ break;
-static void
-do_curses_fdisk(void) {
- int done = FALSE;
- int command;
- int is_first_run = TRUE;
-
- static struct MenuItem menuMain[] = {
- { 'b', N_("Bootable"), N_("Toggle bootable flag of the current partition") },
- { 'd', N_("Delete"), N_("Delete the current partition") },
- { 'g', N_("Geometry"), N_("Change disk geometry (experts only)") },
- { 'h', N_("Help"), N_("Print help screen") },
- { 'm', N_("Maximize"), N_("Maximize disk usage of the current partition (experts only)") },
- { 'n', N_("New"), N_("Create new partition from free space") },
- { 'p', N_("Print"), N_("Print partition table to the screen or to a file") },
- { 'q', N_("Quit"), N_("Quit program without writing partition table") },
- { 't', N_("Type"), N_("Change the filesystem type (DOS, Linux, OS/2 and so on)") },
- { 'u', N_("Units"), N_("Change units of the partition size display (MB, sect, cyl)") },
- { 'W', N_("Write"), N_("Write partition table to disk (this might destroy data)") },
- { 0, NULL, NULL }
- };
- curses_started = 1;
- initscr();
- init_const();
-
- old_SIGINT = signal(SIGINT, die);
- old_SIGTERM = signal(SIGTERM, die);
-#ifdef DEBUG
- signal(SIGINT, old_SIGINT);
- signal(SIGTERM, old_SIGTERM);
+ switch (key) {
+ case KEY_DOWN:
+ case '\016': /* ^N */
+ case 'j': /* Vi-like alternative */
+ ui_table_goto(cf, cf->lines_idx + 1);
+ break;
+ case KEY_UP:
+ case '\020': /* ^P */
+ case 'k': /* Vi-like alternative */
+ ui_table_goto(cf, cf->lines_idx - 1);
+ break;
+ case KEY_HOME:
+ ui_table_goto(cf, 0);
+ break;
+ case KEY_END:
+ ui_table_goto(cf, cf->nlines - 1);
+ break;
+ ui_menu_action(cf, 0);
+ break;
+ case KEY_LEFT:
+#ifdef KEY_BTAB
+ case KEY_BTAB:
#endif
+ ui_menu_goto(cf, cf->menu_idx - 1);
+ break;
+ case KEY_RIGHT:
+ case '\t':
+ ui_menu_goto(cf, cf->menu_idx + 1);
+ break;
+ case KEY_ENTER:
+ case '\n':
+ case '\r':
+ ui_menu_action(cf, 0);
+ break;
+ default:
+ if (ui_menu_action(cf, key) != 0)
+ beep();
+ break;
+ }
+ } while (1);
- cbreak();
- noecho();
- nonl();
+ menu_pop(cf);
- fill_p_info();
+ DBG(FRONTEND, dbgprint("ui: end"));
+
+ return 0;
+}
- draw_screen();
+int main(int argc, char *argv[])
+{
+ struct cfdisk _cf = { .lines_idx = 0 },
+ *cf = &_cf;
- while (!done) {
- char *s;
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+ atexit(close_stdout);
- draw_cursor(0);
+ fdisk_init_debug(0);
+ cf->cxt = fdisk_new_context();
+ if (!cf->cxt)
+ err(EXIT_FAILURE, _("failed to allocate libfdisk context"));
- if (p_info[cur_part].id == FREE_SPACE) {
- s = ((opentype == O_RDWR) ? "hnpquW" : "hnpqu");
- command = menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuMain, 10,
- s, MENU_BUTTON | MENU_ACCEPT_OTHERS, 5);
- } else if (p_info[cur_part].id > 0) {
- s = ((opentype == O_RDWR) ? "bdhmpqtuW" : "bdhmpqtu");
- command = menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuMain, 10,
- s, MENU_BUTTON | MENU_ACCEPT_OTHERS, is_first_run ? 7 : 0);
- } else {
- s = ((opentype == O_RDWR) ? "hpquW" : "hpqu");
- command = menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuMain, 10,
- s, MENU_BUTTON | MENU_ACCEPT_OTHERS, 0);
- }
- is_first_run = FALSE;
- switch ( command ) {
- case 'B':
- case 'b':
- if (p_info[cur_part].id > 0)
- p_info[cur_part].flags ^= 0x80;
- else
- print_warning(_("Cannot make this partition bootable"));
- break;
- case 'D':
- case 'd':
- if (p_info[cur_part].id > 0) {
- del_part(cur_part);
- if (cur_part >= num_parts)
- cur_part = num_parts - 1;
- draw_screen();
- } else
- print_warning(_("Cannot delete an empty partition"));
- break;
- case 'G':
- case 'g':
- if (change_geometry())
- draw_screen();
- break;
- case 'M':
- case 'm':
- if (p_info[cur_part].id > 0) {
- if (p_info[cur_part].first_sector == 0 ||
- IS_LOGICAL(p_info[cur_part].num)) {
- if (p_info[cur_part].offset == sectors)
- p_info[cur_part].offset = 1;
- else
- p_info[cur_part].offset = sectors;
- draw_screen();
- } else if (p_info[cur_part].offset != 0)
- p_info[cur_part].offset = 0;
- else
- print_warning(_("Cannot maximize this partition"));
- } else
- print_warning(_("Cannot maximize this partition"));
- break;
- case 'N':
- case 'n':
- if (p_info[cur_part].id == FREE_SPACE) {
- new_part(cur_part);
- draw_screen();
- } else if (p_info[cur_part].id == UNUSABLE)
- print_warning(_("This partition is unusable"));
- else
- print_warning(_("This partition is already in use"));
- break;
- case 'P':
- case 'p':
- print_tables();
- draw_screen();
- break;
- case 'Q':
- case 'q':
- done = TRUE;
- break;
- case 'T':
- case 't':
- if (p_info[cur_part].id > 0) {
- change_id(cur_part);
- draw_screen();
- } else
- print_warning(_("Cannot change the type of an empty partition"));
- break;
- case 'U':
- case 'u':
- if (display_units == GIGABYTES)
- display_units = MEGABYTES;
- else if (display_units == MEGABYTES)
- display_units = SECTORS;
- else if (display_units == SECTORS)
- display_units = CYLINDERS;
- else if (display_units == CYLINDERS)
- display_units = MEGABYTES; /* not yet GIGA */
- draw_screen();
- break;
- case 'W':
- write_part_table();
- break;
- case 'H':
- case 'h':
- case '?':
- display_help();
- draw_screen();
- break;
- case KEY_UP: /* Up arrow key */
- case '\020': /* ^P */
- case 'k': /* Vi-like alternative */
- draw_cursor(-1);
- break;
- case KEY_DOWN: /* Down arrow key */
- case '\016': /* ^N */
- case 'j': /* Vi-like alternative */
- draw_cursor(1);
- break;
- case REDRAWKEY:
- clear();
- draw_screen();
- break;
- case KEY_HOME:
- draw_cursor(-cur_part);
- break;
- case KEY_END:
- draw_cursor(num_parts - cur_part - 1);
- break;
- default:
- print_warning(_("Illegal command"));
- putchar(BELL); /* CTRL-G */
- }
- }
+ fdisk_context_set_ask(cf->cxt, ask_callback, (void *) cf);
+ fdisk_context_enable_freespace(cf->cxt, 1);
- die_x(0);
-}
+ if (argc != 2)
+ err(EXIT_FAILURE, "usage: %s <device>", argv[0]);
-static void
-copyright(void) {
- fprintf(stderr, _("Copyright (C) 1994-2002 Kevin E. Martin & aeb\n"));
-}
+ if (fdisk_context_assign_device(cf->cxt, argv[optind], 0) != 0)
+ err(EXIT_FAILURE, _("cannot open %s"), argv[optind]);
+ cols_init(cf);
-static void __attribute__ ((__noreturn__)) usage(FILE *out)
-{
- fputs(USAGE_HEADER, out);
- fprintf(out, _(" %s [options] <device>\n"), program_invocation_short_name);
- fputs(USAGE_OPTIONS, out);
- fputs(_(" -c, --cylinders <number> set the number of cylinders to use\n"), out);
- fputs(_(" -h, --heads <number> set the number of heads to use\n"), out);
- fputs(_(" -s, --sectors <number> set the number of sectors to use\n"), out);
- fputs(_(" -g, --guess guess a geometry from partition table\n"), out);
- fputs(_(" -P, --print <r|s|t> print partition table in specified format\n"), out);
- fputs(_(" -z, --zero start with zeroed partition table\n"), out);
- fputs(_(" -a, --arrow use arrow for highlighting the current partition\n"), out);
- fputs(USAGE_SEPARATOR, out);
- fputs(_(" --help display this help and exit\n"), out);
- fputs(USAGE_VERSION, out);
- fprintf(out, USAGE_MAN_TAIL("cfdisk(8)"));
- copyright();
- exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
-}
+ if (lines_refresh_buffer(cf))
+ errx(EXIT_FAILURE, _("failed to read partitions"));
-int
-main(int argc, char **argv)
-{
- int c;
- int i, len;
-
- enum {
- OPT_HELP = CHAR_MAX + 1,
- };
-
- static const struct option longopts[] = {
- {"cylinders", required_argument, 0, 'c'},
- {"heads", required_argument, 0, 'h'},
- {"sectors", required_argument, 0, 's'},
- {"guess", no_argument, 0, 'g'},
- {"print", required_argument, 0, 'P'},
- {"zero", no_argument, 0, 'z'},
- {"arrow", no_argument, 0, 'a'},
- {"help", no_argument, 0, OPT_HELP},
- {"version", no_argument, 0, 'V'},
- {NULL, no_argument, 0, '0'},
- };
-
- setlocale(LC_ALL, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
- atexit(close_stdout);
-
- while ((c = getopt_long(argc, argv, "ac:gh:s:vVzP:", longopts, NULL)) != -1)
- switch (c) {
- case 'a':
- arrow_cursor = TRUE;
- break;
- case 'c':
- user_cylinders = cylinders = strtos64_or_err(optarg, _("cannot parse number of cylinders"));
- if (cylinders <= 0) {
- fprintf(stderr, "%s: %s\n", argv[0], _("Illegal cylinders value"));
- exit(1);
- }
- break;
- case 'g':
- use_partition_table_geometry = TRUE;
- break;
- case 'h':
- user_heads = heads = strtol_or_err(optarg, _("cannot parse number of heads"));
- if (heads <= 0 || heads > MAX_HEADS) {
- fprintf(stderr, "%s: %s\n", argv[0], _("Illegal heads value"));
- exit(1);
- }
- break;
- case 's':
- user_sectors = sectors = strtol_or_err(optarg, _("cannot parse number of sectors"));
- if (sectors <= 0 || sectors > MAX_SECTORS) {
- fprintf(stderr, "%s: %s\n", argv[0], _("Illegal sectors value"));
- exit(1);
- }
- break;
- case 'v':
- case 'V':
- printf(UTIL_LINUX_VERSION);
- copyright();
- return EXIT_SUCCESS;
- case 'z':
- zero_table = TRUE;
- break;
- case 'P':
- len = strlen(optarg);
- for (i = 0; i < len; i++) {
- switch (optarg[i]) {
- case 'r':
- print_only |= PRINT_RAW_TABLE;
- break;
- case 's':
- print_only |= PRINT_SECTOR_TABLE;
- break;
- case 't':
- print_only |= PRINT_PARTITION_TABLE;
- break;
- default:
- usage(stderr);
- }
- }
- break;
- case OPT_HELP:
- usage(stdout);
- default:
- usage(stderr);
- }
+ /* Don't use err(), warn() from this point */
+ ui_init(cf);
+ ui_run(cf);
+ ui_end(cf);
- if (argc-optind == 1)
- disk_device = argv[optind];
- else if (argc-optind != 0) {
- usage(stderr);
- } else if ((fd = open(DEFAULT_DEVICE, O_RDONLY)) < 0)
- disk_device = ALTERNATE_DEVICE;
- else close(fd);
-
- if (print_only) {
- fill_p_info();
- if (print_only & PRINT_RAW_TABLE)
- print_raw_table();
- if (print_only & PRINT_SECTOR_TABLE)
- print_p_info();
- if (print_only & PRINT_PARTITION_TABLE)
- print_part_table();
- } else
- do_curses_fdisk();
-
- return 0;
+ free(cf->lines);
+ free(cf->linesbuf);
+ fdisk_unref_table(cf->table);
+ fdisk_free_context(cf->cxt);
+ return EXIT_SUCCESS;
}