📄 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-j: aeb@cwi.nl * Recognition of NTFS / HPFS difference inspired by patches * from Marty Leisner <leisner@sdsp.mc.xerox.com> * ****************************************************************************/#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 <curses.h>#include <signal.h>#include <math.h>#include <locale.h>#include <string.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <linux/genhd.h>#include <linux/hdreg.h>#include <linux/fs.h> /* for BLKRRPART */#if defined(__GNUC__) || defined(HAS_LONG_LONG)typedef long long ext2_loff_t;#elsetypedef long ext2_loff_t;#endifextern ext2_loff_t ext2_llseek(unsigned int fd, ext2_loff_t offset, unsigned int origin);#define VERSION "0.8j"#define DEFAULT_DEVICE "/dev/hda"#define ALTERNATE_DEVICE "/dev/sda"#define LINE_LENGTH 80#define MAXIMUM_PARTS 60#define SECTOR_SIZE 512#define MAX_CYLINDERS 65535#define MAX_HEADS 255#define MAX_SECTORS 63#define ACTIVE_FLAG 0x80#define PART_TABLE_FLAG 0xAA55#define UNUSABLE -1#define FREE_SPACE 0x00#define DOS_EXTENDED 0x05#define OS2_OR_NTFS 0x07#define LINUX_EXTENDED 0x85#define LINUX_MINIX 0x81#define LINUX_SWAP 0x82#define LINUX 0x83#define ADD_EXISTS "This partition is already in use"#define ADD_UNUSABLE "This partition is unusable"#define DEL_EMPTY "Cannot delete an empty partition"#define ID_EMPTY "Cannot change FS Type to empty"#define ID_EXT "Cannot change FS Type to extended"#define NEED_EXT "No room to create the extended partition"#define NO_FLAGS "Cannot make this partition bootable"#define NO_MORE_PARTS "No more partitions"#define PRINT_OPEN_ERR "Cannot open file '%s'"#define TWO_EXTENDEDS "Cannot create logical drive here -- would create two extended partitions"#define TYPE_EMPTY "Cannot change the type of an empty partition"#define BAD_COMMAND "Illegal command"#define MAX_UNMAXABLE "Cannot maximize this partition"#define BAD_OPEN "Cannot open disk drive"#define BAD_SEEK "Cannot seek on disk drive"#define BAD_READ "Cannot read disk drive"#define BAD_WRITE "Cannot write disk drive"#define BAD_GEOMETRY "Cannot read disk drive geometry"#define BAD_PRIMARY "Bad primary partition"#define BAD_LOGICAL "Bad logical partition"#define BAD_CYLINDERS "Illegal cylinders value"#define BAD_HEADS "Illegal heads value"#define BAD_SECTORS "Illegal sectors value"#define READONLY_WARN "Opened disk read-only - you have no permission to write"#define WRITE_WARN "Warning!! This may destroy data on your disk!"#define YES_NO "Please enter `yes' or `no'"#define WRITING_PART "Writing partition table to disk..."#define YES_WRITE "Wrote partition table to disk"#define NO_WRITE "Did not write partition table to disk"#define RRPART_FAILED "Wrote partition table, but re-read table failed. Reboot to update table."#define PRI_OR_LOG -1#define PRIMARY -2#define LOGICAL -3#define COL_ID_WIDTH 20#define CR '\015'#define ESC '\033'#define DEL '\177'#define BELL '\007'/* '\014' == ^L */#define REDRAWKEY '\014'/* Display units */#define MEGABYTES 1#define SECTORS 2#define CYLINDERS 3#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)))#define set_hsc(h,s,c,sector) \{ \ s = sector % sectors + 1; \ sector /= sectors; \ h = sector % heads; \ sector /= heads; \ c = sector & 0xFF; \ s |= (sector >> 2) & 0xC0;\}#define is_extended(x) ((x) == DOS_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)#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 short flag; } p;} partition_table;typedef struct { int first_sector; /* first sector in partition */ int last_sector; /* last sector in partition */ int 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 heads = 0;int sectors = 0;int cylinders = 0;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 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 = 5;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 = 70;int COMMAND_LINE_X = 5;#define NUM_PART_TYPES 256char *partition_type[NUM_PART_TYPES] = { [LINUX_MINIX] = "Linux/MINIX", [LINUX_SWAP] = "Linux Swap", [LINUX] = "Linux", [FREE_SPACE] = "Free Space", [DOS_EXTENDED]= "Extended", [LINUX_EXTENDED] = "Linux extended", [0x01] = "DOS FAT12", [0x04] = "DOS FAT16", [0x06] = "DOS FAT16 (big)", [OS2_OR_NTFS] = "OS/2 HPFS or NTFS", [0x0A] = "OS/2 Boot Manager", [0x0B] = "Win95 FAT32", [0x0C] = "Win95 FAT32 (LBA)", [0x0E] = "Win95 FAT16 (LBA)", [0x0F] = "Win95 Extended (LBA)", [0x11] = "Hidden DOS FAT12", [0x14] = "Hidden DOS FAT16", [0x16] = "Hidden DOS FAT16 (big)", [0xA5] = "BSD/386",/* The rest of these are taken from A. V. Le Blanc's (LeBlanc@mcc.ac.uk) * fdisk program. I do not know where they came from, but I include * them for completeness. (With additions.) */ [0x02] = "XENIX root", [0x03] = "XENIX usr", [0x08] = "AIX", [0x09] = "AIX bootable", [0x40] = "Venix 80286", [0x51] = "Novell?", [0x52] = "Microport", [0x63] = "GNU HURD", [0x64] = "Novell Netware 286", [0x65] = "Novell Netware 386", [0x75] = "PC/IX", [0x80] = "Old MINIX", [0x93] = "Amoeba", [0x94] = "Amoeba BBT", [0xB7] = "BSDI fs", [0xB8] = "BSDI swap", [0xC7] = "Syrinx", [0xDB] = "CP/M", [0xE1] = "DOS access", [0xE3] = "DOS R/O", [0xF2] = "DOS secondary", [0xFF] = "BBT"};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 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[p_info[i].id];}void fdexit(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);}int get_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;}void clear_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;}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 */ warning_last_time = TRUE; }}void die_x(int ret);void fatal(char *s){ char str[LINE_LENGTH]; if (curses_started) { sprintf(str, "FATAL ERROR: %s", s); mvaddstr(WARNING_START, (COLS-strlen(str))/2, str); sprintf(str, "Press any key to exit fdisk"); mvaddstr(WARNING_START+1, (COLS-strlen(str))/2, str); putchar(BELL); /* CTRL-G */ refresh(); (void)getch(); die_x(1); } else { fprintf(stderr, "FATAL ERROR: %s\n", s); exit(1); }}void die(int dummy){ die_x(0);}void die_x(int ret){ signal(SIGINT, old_SIGINT); signal(SIGTERM, old_SIGTERM); mvcur(0, COLS-1, LINES-1, 0); nl(); endwin(); printf("\n"); fdexit(ret);}void read_sector(char *buffer, int sect_num){ if (ext2_llseek(fd, ((ext2_loff_t) sect_num)*SECTOR_SIZE, SEEK_SET) < 0) fatal(BAD_SEEK); if (read(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) fatal(BAD_READ);}void write_sector(char *buffer, int sect_num){ if (ext2_llseek(fd, ((ext2_loff_t) sect_num)*SECTOR_SIZE, SEEK_SET) < 0) fatal(BAD_SEEK); if (write(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) fatal(BAD_WRITE);}void dos_copy_to_info(char *to, int tosz, char *from, int fromsz) { int i; for(i=0; i<tosz && i<fromsz && isascii(from[i]); i++) to[i] = from[i]; to[i] = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -