📄 cfdisk.c
字号:
/**************************************************************************** * * 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 cfdisk; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, 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. * ****************************************************************************/#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <unistd.h>#include <ctype.h>#include <errno.h>#include <getopt.h>#include <fcntl.h>#ifdef SLCURSES #include <slcurses.h>#else#if NCH #include <ncurses.h>#else #include <curses.h>#endif#endif#include <signal.h>#include <math.h>#include <string.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <linux/types.h>#include "nls.h"#include "xstrncpy.h"#include "common.h"extern long long ext2_llseek(unsigned int fd, long long offset, unsigned int origin);#define VERSION UTIL_LINUX_VERSION#define DEFAULT_DEVICE "/dev/hda"#define ALTERNATE_DEVICE "/dev/sda"/* 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 255#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 CR '\015'#define ESC '\033'#define DEL '\177'#define BELL '\007'#define TAB '\011'#define REDRAWKEY '\014' /* ^L */#define UPKEY '\020' /* ^P */#define DOWNKEY '\016' /* ^N *//* 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 */};int heads = 0;int sectors = 0;long long cylinders = 0;int cylinder_size = 0; /* heads * sectors */long long total_size = 0; /* actual_size rounded down */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 voidset_hsc0(unsigned char *h, unsigned char *s, int *c, long long sector) { if (sector >= 1024*cylinder_size) sector = 1024*cylinder_size - 1; *s = sector % sectors + 1; sector /= sectors; *h = sector % heads; sector /= heads; *c = sector;}static voidset_hsc(unsigned char *h, unsigned char *s, unsigned char *c, long long sector) { int cc; set_hsc0(h, s, &cc, sector); *c = cc & 0xFF; *s |= (cc >> 2) & 0xC0;}static voidset_hsc_begin(struct partition *p, long long sector) { set_hsc(& p->head, & p->sector, & p->cyl, sector);}static voidset_hsc_end(struct partition *p, long long sector) { set_hsc(& p->end_head, & p->end_sector, & p->end_cyl, sector);}#define is_extended(x) ((x) == DOS_EXTENDED || (x) == WIN98_EXTENDED || \ (x) == LINUX_EXTENDED)#define is_dos_partition(x) ((x) == 1 || (x) == 4 || (x) == 6)#define may_have_dos_label(x) (is_dos_partition(x) \ || (x) == 7 || (x) == 0xb || (x) == 0xc || (x) == 0xe \ || (x) == 0x11 || (x) == 0x14 || (x) == 0x16 || (x) == 0x17)/* start_sect and nr_sects are stored little endian on all machines *//* moreover, they are not aligned correctly */static voidstore4_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);}static unsigned intread4_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);}static voidset_start_sect(struct partition *p, unsigned int start_sect) { store4_little_endian(p->start4, start_sect);}static unsigned intget_start_sect(struct partition *p) { return read4_little_endian(p->start4);}static voidset_nr_sects(struct partition *p, unsigned int nr_sects) { store4_little_endian(p->size4, nr_sects);}static unsigned intget_nr_sects(struct partition *p) { return read4_little_endian(p->size4);}#define ALIGNMENT 2typedef 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 8 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;int logical_sectors[MAXIMUM_PARTS];__sighandler_t old_SIGINT, old_SIGTERM;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;}/* Some libc's have their own basename() */static char *my_basename(char *devname) { char *s = rindex(devname, '/'); return s ? s+1 : devname;}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 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].id == LINUX) { if (!strcmp(p_info[i].fstype, "ext2")) return _("Linux ext2"); else if (!strcmp(p_info[i].fstype, "ext3")) return _("Linux ext3"); else if (!strcmp(p_info[i].fstype, "xfs")) return _("Linux XFS"); else if (!strcmp(p_info[i].fstype, "reiserfs")) return _("Linux ReiserFS"); else return _("Linux"); } else if (p_info[i].id == OS2_OR_NTFS) { if (!strncmp(p_info[i].fstype, "HPFS", 4)) return _("OS/2 HPFS"); else if (!strncmp(p_info[i].ostype, "OS2", 3)) return _("OS/2 IFS"); else if (!p_info[i].ostype) return p_info[i].ostype; else return _("NTFS"); } else return partition_type_name(p_info[i].id);}static voidfdexit(int ret) { if (opened) close(fd); if (changed) { fprintf(stderr, _("Disk has been changed.\n")); fprintf(stderr, _("Reboot the system to ensure the partition " "table is correctly updated.\n")); 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") ); } exit(ret);}static intget_string(char *str, int len, char *def) { char c; int i = 0; int x, y; int use_def = FALSE; getyx(stdscr, y, x); clrtoeol(); str[i] = 0; if (def != NULL) { mvaddstr(y, x, def); move(y, x); use_def = TRUE; } refresh(); while ((c = getch()) != '\n' && c != CR) { switch (c) { case ESC: move(y, x); clrtoeol(); refresh(); return GS_ESCAPE; case DEL: case '\b': if (i > 0) { str[--i] = 0; mvaddch(y, x+i, ' '); move(y, x+i); } else if (use_def) { clrtoeol(); use_def = FALSE; } else putchar(BELL); break; default: if (i < len && isprint(c)) { mvaddch(y, x+i, c); if (use_def) { clrtoeol(); use_def = FALSE; } str[i++] = c; str[i] = 0; } else putchar(BELL); } refresh(); } if (use_def) return GS_DEFAULT; else return i;}static voidclear_warning(void) { int i; if (!curses_started || !warning_last_time) return; move(WARNING_START,0); for (i = 0; i < COLS; i++) addch(' '); warning_last_time = FALSE;}static voidprint_warning(char *s) { if (!curses_started) { fprintf(stderr, "%s\n", s); } else { mvaddstr(WARNING_START, (COLS-strlen(s))/2, s);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -