📄 fdisk.c
字号:
/* fdisk.c -- Partition table manipulator for Linux. * * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk) * * This program 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 1 or * (at your option) any later version. */#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <ctype.h>#include <setjmp.h>#include <errno.h>#include <getopt.h>#include <sys/stat.h>#include "nls.h"#include "common.h"#include "fdisk.h"#include "fdisksunlabel.h"#include "fdisksgilabel.h"#include "fdiskaixlabel.h"#include "../defines.h"#ifdef HAVE_blkpg_h#include <linux/blkpg.h>#endifstatic void delete_partition(int i);#define hex_val(c) ({ \ char _c = (c); \ isdigit(_c) ? _c - '0' : \ tolower(_c) + 10 - 'a'; \ })#define LINE_LENGTH 800#define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \ (n) * sizeof(struct partition)))#define sector(s) ((s) & 0x3f)#define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))#define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \ ((h) + heads * cylinder(s,c)))#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; \ }/* A valid partition table sector ends in 0x55 0xaa */static unsigned intpart_table_flag(char *b) { return ((unsigned int) b[510]) + (((unsigned int) b[511]) << 8);}intvalid_part_table_flag(unsigned char *b) { return (b[510] == 0x55 && b[511] == 0xaa);}static voidwrite_part_table_flag(char *b) { b[510] = 0x55; b[511] = 0xaa;}/* 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);}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);}unsigned intget_nr_sects(struct partition *p) { return read4_little_endian(p->size4);}/* normally O_RDWR, -l option gives O_RDONLY */static int type_open = O_RDWR;/* * Raw disk label. For DOS-type partition tables the MBR, * with descriptions of the primary partitions. */char MBRbuffer[MAX_SECTOR_SIZE];/* * per partition table entry data * * The four primary partitions have the same sectorbuffer (MBRbuffer) * and have NULL ext_pointer. * Each logical partition table entry has two pointers, one for the * partition and one link to the next one. */struct pte { struct partition *part_table; /* points into sectorbuffer */ struct partition *ext_pointer; /* points into sectorbuffer */ char changed; /* boolean */ unsigned int offset; /* disk sector number */ char *sectorbuffer; /* disk sector contents */} ptes[MAXIMUM_PARTS];char *disk_device, /* must be specified */ *line_ptr, /* interactive input */ line_buffer[LINE_LENGTH];int fd, /* the disk */ ext_index, /* the prime extended partition */ listing = 0, /* no aborts for fdisk -l */ nowarn = 0, /* no warnings for fdisk -l/-s */ dos_compatible_flag = ~0, dos_changed = 0, partitions = 4; /* maximum partition + 1 */unsigned int user_cylinders, user_heads, user_sectors;unsigned int pt_heads, pt_sectors;unsigned int kern_heads, kern_sectors;unsigned int heads, sectors, cylinders, sector_size = DEFAULT_SECTOR_SIZE, user_set_sector_size = 0, sector_offset = 1, units_per_sector = 1, display_in_cyl_units = 1, extended_offset = 0; /* offset of link pointers */unsigned long long total_number_of_sectors;#define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)int sun_label = 0; /* looking at sun disklabel */int sgi_label = 0; /* looking at sgi disklabel */int aix_label = 0; /* looking at aix disklabel */int osf_label = 0; /* looking at OSF/1 disklabel */int possibly_osf_label = 0;jmp_buf listingbuf;void fatal(enum failure why) { char error[LINE_LENGTH], *message = error; if (listing) { close(fd); longjmp(listingbuf, 1); } switch (why) { case usage: message = _("Usage: fdisk [-b SSZ] [-u] DISK Change partition table\n"" fdisk -l [-b SSZ] [-u] DISK List partition table(s)\n"" fdisk -s PARTITION Give partition size(s) in blocks\n"" fdisk -v Give fdisk version\n""Here DISK is something like /dev/hdb or /dev/sda\n""and PARTITION is something like /dev/hda7\n""-u: give Start and End in sector (instead of cylinder) units\n""-b 2048: (for certain MO disks) use 2048-byte sectors\n"); break; case usage2: /* msg in cases where fdisk used to probe */ message = _("Usage: fdisk [-l] [-b SSZ] [-u] device\n""E.g.: fdisk /dev/hda (for the first IDE disk)\n"" or: fdisk /dev/sdc (for the third SCSI disk)\n"" or: fdisk /dev/eda (for the first PS/2 ESDI drive)\n"" or: fdisk /dev/rd/c0d0 or: fdisk /dev/ida/c0d0 (for RAID devices)\n"" ...\n"); break; case unable_to_open: snprintf(error, sizeof(error), _("Unable to open %s\n"), disk_device); break; case unable_to_read: snprintf(error, sizeof(error), _("Unable to read %s\n"), disk_device); break; case unable_to_seek: snprintf(error, sizeof(error), _("Unable to seek on %s\n"),disk_device); break; case unable_to_write: snprintf(error, sizeof(error), _("Unable to write %s\n"), disk_device); break; case ioctl_error: snprintf(error, sizeof(error), _("BLKGETSIZE ioctl failed on %s\n"), disk_device); break; case out_of_memory: message = _("Unable to allocate any more memory\n"); break; default: message = _("Fatal error\n"); } fputc('\n', stderr); fputs(message, stderr); exit(1);}static voidseek_sector(int fd, unsigned int secno) { long long offset = (long long) secno * sector_size; if (ext2_llseek(fd, offset, SEEK_SET) == (long long) -1) fatal(unable_to_seek);}static voidread_sector(int fd, unsigned int secno, char *buf) { seek_sector(fd, secno); if (read(fd, buf, sector_size) != sector_size) fatal(unable_to_read);}static voidwrite_sector(int fd, unsigned int secno, char *buf) { seek_sector(fd, secno); if (write(fd, buf, sector_size) != sector_size) fatal(unable_to_write);}/* Allocate a buffer and read a partition table sector */static voidread_pte(int fd, int pno, unsigned int offset) { struct pte *pe = &ptes[pno]; pe->offset = offset; pe->sectorbuffer = (char *) malloc(sector_size); if (!pe->sectorbuffer) fatal(out_of_memory); read_sector(fd, offset, pe->sectorbuffer); pe->changed = 0; pe->part_table = pe->ext_pointer = NULL;}static unsigned intget_partition_start(struct pte *pe) { return pe->offset + get_start_sect(pe->part_table);}struct partition *get_part_table(int i) { return ptes[i].part_table;}voidset_all_unchanged(void) { int i; for (i = 0; i < MAXIMUM_PARTS; i++) ptes[i].changed = 0;}voidset_changed(int i) { ptes[i].changed = 1;}static intis_garbage_table(void) { int i; for (i = 0; i < 4; i++) { struct pte *pe = &ptes[i]; struct partition *p = pe->part_table; if (p->boot_ind != 0 && p->boot_ind != 0x80) return 1; } return 0;}/* * Avoid warning about DOS partitions when no DOS partition was changed. * Here a heuristic "is probably dos partition". * We might also do the opposite and warn in all cases except * for "is probably nondos partition". */static intis_dos_partition(int t) { return (t == 1 || t == 4 || t == 6 || t == 0x0b || t == 0x0c || t == 0x0e || t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 || t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 || t == 0xc1 || t == 0xc4 || t == 0xc6);}static voidmenu(void) { if (sun_label) { puts(_("Command action")); puts(_(" a toggle a read only flag")); /* sun */ puts(_(" b edit bsd disklabel")); puts(_(" c toggle the mountable flag")); /* sun */ puts(_(" d delete a partition")); puts(_(" l list known partition types")); puts(_(" m print this menu")); puts(_(" n add a new partition")); puts(_(" o create a new empty DOS partition table")); puts(_(" p print the partition table")); puts(_(" q quit without saving changes")); puts(_(" s create a new empty Sun disklabel")); /* sun */ puts(_(" t change a partition's system id")); puts(_(" u change display/entry units")); puts(_(" v verify the partition table")); puts(_(" w write table to disk and exit")); puts(_(" x extra functionality (experts only)")); } else if (sgi_label) { puts(_("Command action")); puts(_(" a select bootable partition")); /* sgi flavour */ puts(_(" b edit bootfile entry")); /* sgi */ puts(_(" c select sgi swap partition")); /* sgi flavour */ puts(_(" d delete a partition")); puts(_(" l list known partition types")); puts(_(" m print this menu")); puts(_(" n add a new partition")); puts(_(" o create a new empty DOS partition table")); puts(_(" p print the partition table")); puts(_(" q quit without saving changes")); puts(_(" s create a new empty Sun disklabel")); /* sun */ puts(_(" t change a partition's system id")); puts(_(" u change display/entry units")); puts(_(" v verify the partition table")); puts(_(" w write table to disk and exit")); } else if (aix_label) { puts(_("Command action")); puts(_(" m print this menu")); puts(_(" o create a new empty DOS partition table")); puts(_(" q quit without saving changes")); puts(_(" s create a new empty Sun disklabel")); /* sun */ } else { puts(_("Command action")); puts(_(" a toggle a bootable flag")); puts(_(" b edit bsd disklabel")); puts(_(" c toggle the dos compatibility flag")); puts(_(" d delete a partition")); puts(_(" l list known partition types")); puts(_(" m print this menu")); puts(_(" n add a new partition")); puts(_(" o create a new empty DOS partition table")); puts(_(" p print the partition table")); puts(_(" q quit without saving changes")); puts(_(" s create a new empty Sun disklabel")); /* sun */ puts(_(" t change a partition's system id")); puts(_(" u change display/entry units")); puts(_(" v verify the partition table")); puts(_(" w write table to disk and exit")); puts(_(" x extra functionality (experts only)")); }}static voidxmenu(void) { if (sun_label) { puts(_("Command action")); puts(_(" a change number of alternate cylinders")); /*sun*/ puts(_(" c change number of cylinders")); puts(_(" d print the raw data in the partition table")); puts(_(" e change number of extra sectors per cylinder"));/*sun*/ puts(_(" h change number of heads")); puts(_(" i change interleave factor")); /*sun*/ puts(_(" o change rotation speed (rpm)")); /*sun*/ puts(_(" m print this menu")); puts(_(" p print the partition table")); puts(_(" q quit without saving changes")); puts(_(" r return to main menu")); puts(_(" s change number of sectors/track")); puts(_(" v verify the partition table")); puts(_(" w write table to disk and exit")); puts(_(" y change number of physical cylinders")); /*sun*/ } else if (sgi_label) { puts(_("Command action")); puts(_(" b move beginning of data in a partition")); /* !sun */ puts(_(" c change number of cylinders")); puts(_(" d print the raw data in the partition table")); puts(_(" e list extended partitions")); /* !sun */ puts(_(" g create an IRIX (SGI) partition table"));/* sgi */ puts(_(" h change number of heads")); puts(_(" m print this menu")); puts(_(" p print the partition table")); puts(_(" q quit without saving changes")); puts(_(" r return to main menu")); puts(_(" s change number of sectors/track")); puts(_(" v verify the partition table")); puts(_(" w write table to disk and exit")); } else if (aix_label) { puts(_("Command action")); puts(_(" b move beginning of data in a partition")); /* !sun */ puts(_(" c change number of cylinders")); puts(_(" d print the raw data in the partition table")); puts(_(" e list extended partitions")); /* !sun */ puts(_(" g create an IRIX (SGI) partition table"));/* sgi */ puts(_(" h change number of heads")); puts(_(" m print this menu")); puts(_(" p print the partition table")); puts(_(" q quit without saving changes")); puts(_(" r return to main menu")); puts(_(" s change number of sectors/track")); puts(_(" v verify the partition table")); puts(_(" w write table to disk and exit")); } else { puts(_("Command action")); puts(_(" b move beginning of data in a partition")); /* !sun */ puts(_(" c change number of cylinders")); puts(_(" d print the raw data in the partition table")); puts(_(" e list extended partitions")); /* !sun */ puts(_(" f fix partition order")); /* !sun, !aix, !sgi */ puts(_(" g create an IRIX (SGI) partition table"));/* sgi */ puts(_(" h change number of heads")); puts(_(" m print this menu")); puts(_(" p print the partition table")); puts(_(" q quit without saving changes")); puts(_(" r return to main menu")); puts(_(" s change number of sectors/track")); puts(_(" v verify the partition table")); puts(_(" w write table to disk and exit")); }}static intget_sysid(int i) { return ( sun_label ? sunlabel->infos[i].id : sgi_label ? sgi_get_sysid(i) : ptes[i].part_table->sys_ind);}static struct systypes *get_sys_types(void) { return ( sun_label ? sun_sys_types : sgi_label ? sgi_sys_types : i386_sys_types);}char *partition_type(unsigned char type){ int i; struct systypes *types = get_sys_types(); for (i=0; types[i].name; i++) if (types[i].type == type) return _(types[i].name); return NULL;}void list_types(struct systypes *sys){ unsigned int last[4], done = 0, next = 0, size; int i; for (i = 0; sys[i].name; i++); size = i; for (i = 3; i >= 0; i--) last[3 - i] = done += (size + i - done) / (i + 1); i = done = 0; do { printf("%c%2x %-15.15s", i ? ' ' : '\n', sys[next].type, _(sys[next].name)); next = last[i++] + done; if (i > 3 || next >= last[i]) { i = 0; next = ++done; } } while (done < last[0]); putchar('\n');}static intis_cleared_partition(struct partition *p) { return !(!p || p->boot_ind || p->head || p->sector || p->cyl || p->sys_ind || p->end_head || p->end_sector || p->end_cyl || get_start_sect(p) || get_nr_sects(p));}static voidclear_partition(struct partition *p) { if (!p) return; p->boot_ind = 0; p->head = 0; p->sector = 0; p->cyl = 0; p->sys_ind = 0; p->end_head = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -