diff options
author | Karel Zak | 2006-12-07 00:25:35 +0100 |
---|---|---|
committer | Karel Zak | 2006-12-07 00:25:35 +0100 |
commit | 2b6fc908bc368b540845a313c3b8a867c5ad9a42 (patch) | |
tree | 6fad48a239bc90515a5dc4084d6e3c3ee1f41e29 /disk-utils | |
parent | Imported from util-linux-2.7.1 tarball. (diff) | |
download | kernel-qcow2-util-linux-2b6fc908bc368b540845a313c3b8a867c5ad9a42.tar.gz kernel-qcow2-util-linux-2b6fc908bc368b540845a313c3b8a867c5ad9a42.tar.xz kernel-qcow2-util-linux-2b6fc908bc368b540845a313c3b8a867c5ad9a42.zip |
Imported from util-linux-2.8 tarball.
Diffstat (limited to 'disk-utils')
-rw-r--r-- | disk-utils/Makefile | 53 | ||||
-rw-r--r-- | disk-utils/cfdisk.8 | 8 | ||||
-rw-r--r-- | disk-utils/cfdisk.c | 251 | ||||
-rw-r--r-- | disk-utils/fdisk.8 | 221 | ||||
-rw-r--r-- | disk-utils/fdisk.c | 1136 | ||||
-rw-r--r-- | disk-utils/fdisk.h | 32 | ||||
-rw-r--r-- | disk-utils/fdisklabel.c | 79 | ||||
-rw-r--r-- | disk-utils/fdisklabel.h | 16 | ||||
-rw-r--r-- | disk-utils/fdisksunlabel.c | 661 | ||||
-rw-r--r-- | disk-utils/fdisksunlabel.h | 73 | ||||
-rw-r--r-- | disk-utils/fsck.minix.c | 44 | ||||
-rw-r--r-- | disk-utils/llseek.c | 54 | ||||
-rw-r--r-- | disk-utils/mkfs.8 | 8 | ||||
-rw-r--r-- | disk-utils/mkfs.c | 15 | ||||
-rw-r--r-- | disk-utils/mkfs.minix.8 | 36 | ||||
-rw-r--r-- | disk-utils/mkfs.minix.c | 42 | ||||
-rw-r--r-- | disk-utils/mkswap.c | 12 | ||||
-rw-r--r-- | disk-utils/sfdisk.8 | 2 | ||||
-rw-r--r-- | disk-utils/sfdisk.c | 183 |
19 files changed, 2258 insertions, 668 deletions
diff --git a/disk-utils/Makefile b/disk-utils/Makefile index fac3134ba..d21cedb9e 100644 --- a/disk-utils/Makefile +++ b/disk-utils/Makefile @@ -10,29 +10,53 @@ include ../MCONFIG MAN8= fdformat.8 mkswap.8 setfdprm.8 -ifneq "$(CPU)" "sparc" -MAN8:=$(MAN8) fdisk.8 cfdisk.8 sfdisk.8 fsck.minix.8 mkfs.8 mkfs.minix.8 -endif - # Where to put binaries? # See the "install" rule for the links. . . SBIN= mkfs mkswap +USRBIN= fdformat setfdprm + +ETC= fdprm + ifneq "$(CPU)" "sparc" -SBIN:=$(SBIN) fdisk cfdisk sfdisk fsck.minix mkfs.minix +# fsck and mkfs will compile, but there is no kernel support on sparc +MAN8:=$(MAN8) fsck.minix.8 mkfs.8 mkfs.minix.8 +SBIN:=$(SBIN) fsck.minix mkfs.minix +ifneq "$(CPU)" "m68k" +MAN8:=$(MAN8) fdisk.8 cfdisk.8 sfdisk.8 +SBIN:=$(SBIN) fdisk cfdisk sfdisk +endif +else +MAN8:=$(MAN8) fdisk.8 +SBIN:=$(SBIN) fdisk endif - -USRBIN= fdformat setfdprm # Where to put datebase files? -ETC= fdprm +all: $(SBIN) $(USRBIN) -all: $(SBIN) $(USRBIN) +cfdisk.o: cfdisk.c +ifeq "$(HAVE_SLANG)" "yes" + $(CC) -c $(CFLAGS) -DSLCURSES=1 $< -o $@ +else +ifeq "$(HAVE_NCURSES)" "yes" + $(CC) -c $(CFLAGS) $< -o $@ +else + : +endif +endif cfdisk: cfdisk.o llseek.o +ifeq "$(HAVE_SLANG)" "yes" + $(CC) $(LDFLAGS) $^ -o $@ $(LIBSLANG) +else +ifeq "$(HAVE_NCURSES)" "yes" $(CC) $(LDFLAGS) $^ -o $@ $(LIBCURSES) -lm +else + @echo $@ not made since it requires ncurses or slang +endif +endif # not installed by default activate: sfdisk @@ -42,8 +66,6 @@ activate: sfdisk # Rules for everything else fdformat: fdformat.o -fdisk: fdisk.o fdisklabel.o llseek.o -sfdisk: sfdisk.o fsck.minix: fsck.minix.o fsck.minix.o: fsck.minix.c bitops.h mkfs: mkfs.o @@ -51,6 +73,15 @@ mkfs.minix: mkfs.minix.o mkfs.minix.o: mkfs.minix.c bitops.h mkswap: mkswap.o setfdprm: setfdprm.o +sfdisk: sfdisk.o + +ifeq "$(CPU)" "sparc" +fdisk: fdisk.o fdisklabel.o fdisksunlabel.o llseek.o +fdisksunlabel.o: fdisksunlabel.c fdisksunlabel.h fdisk.h +else +fdisk: fdisk.o fdisklabel.o llseek.o +endif + fdisk.o: fdisk.c fdisk.h fdisklabel.o: fdisklabel.c fdisk.h fdisklabel.h diff --git a/disk-utils/cfdisk.8 b/disk-utils/cfdisk.8 index 010c370dd..c7ac94171 100644 --- a/disk-utils/cfdisk.8 +++ b/disk-utils/cfdisk.8 @@ -120,18 +120,14 @@ format the partition. For example, if you were using cfdisk to make a DOS partition table entry for /dev/hda1, then (after exiting fdisk or cfdisk and rebooting Linux so that the partition table information is valid) you would use the command "dd if=/dev/zero of=/dev/hda1 bs=512 count=1" to zero -the first 512 bytes of the partition. -.B BE EXTREMELY CAREFUL -if you use the -.B dd -command, since a small typo can make all of the data on your disk useless. +the first 512 bytes of the partition. Note: .B BE EXTREMELY CAREFUL if you use the .B dd command, since a small typo can make all of the data on your disk useless. -For best resutls, you should always use an OS-specific partition table +For best results, you should always use an OS-specific partition table program. For example, you should make DOS partitions with the DOS FDISK program and Linux partitions with the Linux fdisk or Linux cfdisk program. diff --git a/disk-utils/cfdisk.c b/disk-utils/cfdisk.c index 1b87aae79..f0b5482f1 100644 --- a/disk-utils/cfdisk.c +++ b/disk-utils/cfdisk.c @@ -29,7 +29,9 @@ * >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-h: aeb@cwi.nl + * Versions 0.8e-l: aeb@cwi.nl + * Recognition of NTFS / HPFS difference inspired by patches + * from Marty Leisner <leisner@sdsp.mc.xerox.com> * ****************************************************************************/ @@ -41,12 +43,22 @@ #include <errno.h> #include <getopt.h> #include <fcntl.h> -#include <curses.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 <locale.h> #include <string.h> #include <sys/stat.h> #include <sys/ioctl.h> +#include <linux/types.h> #include <linux/genhd.h> #include <linux/hdreg.h> #include <linux/fs.h> /* for BLKRRPART */ @@ -60,7 +72,7 @@ typedef long ext2_loff_t; extern ext2_loff_t ext2_llseek(unsigned int fd, ext2_loff_t offset, unsigned int origin); -#define VERSION "0.8i" +#define VERSION "0.8l" #define DEFAULT_DEVICE "/dev/hda" #define ALTERNATE_DEVICE "/dev/sda" @@ -78,12 +90,14 @@ extern ext2_loff_t ext2_llseek(unsigned int fd, ext2_loff_t offset, #define PART_TABLE_FLAG 0xAA55 #define UNUSABLE -1 -#define FREE_SPACE 0x00 -#define DOS_EXTENDED 0x05 +#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 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" @@ -157,10 +171,13 @@ extern ext2_loff_t ext2_llseek(unsigned int fd, ext2_loff_t offset, s |= (sector >> 2) & 0xC0;\ } -#define is_extended(x) ((x) == DOS_EXTENDED || (x) == LINUX_EXTENDED) +#define is_extended(x) ((x) == DOS_EXTENDED || (x) == WIN98_EXTENDED || \ + (x) == LINUX_EXTENDED) -/* we might also want to recognise 0xe and 0xf */ #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 2 typedef union { @@ -183,8 +200,12 @@ typedef struct { int flags; /* active == 0x80 */ int id; /* filesystem type */ int num; /* number of partition -- primary vs. logical */ -#define LABELSZ 11 - char dos_label[LABELSZ+1]; +#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; @@ -227,8 +248,9 @@ int COMMAND_LINE_Y = 21; /* X coordinates */ int NAME_START = 4; int FLAGS_START = 16; -int PTYPE_START = 30; -int FSTYPE_START = 45; +int PTYPE_START = 28; +int FSTYPE_START = 38; +int LABEL_START = 54; int SIZE_START = 70; int COMMAND_LINE_X = 5; @@ -241,9 +263,13 @@ char *partition_type[NUM_PART_TYPES] = { [DOS_EXTENDED]= "Extended", [LINUX_EXTENDED] = "Linux extended", [0x01] = "DOS FAT12", + [0x02] = "XENIX root", + [0x03] = "XENIX usr", [0x04] = "DOS FAT16", [0x06] = "DOS FAT16 (big)", - [0x07] = "OS/2 HPFS or NTFS", + [OS2_OR_NTFS] = "OS/2 HPFS or NTFS", + [0x08] = "AIX", + [0x09] = "AIX bootable", [0x0A] = "OS/2 Boot Manager", [0x0B] = "Win95 FAT32", [0x0C] = "Win95 FAT32 (LBA)", @@ -252,17 +278,7 @@ char *partition_type[NUM_PART_TYPES] = { [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", + [0x17] = "Hidden OS/2 HPFS or NTFS", [0x40] = "Venix 80286", [0x51] = "Novell?", [0x52] = "Microport", @@ -273,6 +289,9 @@ char *partition_type[NUM_PART_TYPES] = { [0x80] = "Old MINIX", [0x93] = "Amoeba", [0x94] = "Amoeba BBT", + [0xA5] = "BSD/386", + [0xA6] = "OpenBSD", + [0xA7] = "NEXTSTEP", [0xB7] = "BSDI fs", [0xB8] = "BSDI swap", [0xC7] = "Syrinx", @@ -283,6 +302,37 @@ char *partition_type[NUM_PART_TYPES] = { [0xFF] = "BBT" }; +/* Some libc's have their own basename() */ +char *my_basename(char *devname) +{ + char *s = rindex(devname, '/'); + return s ? s+1 : devname; +} + +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) @@ -416,7 +466,12 @@ void die_x(int ret) { signal(SIGINT, old_SIGINT); signal(SIGTERM, old_SIGTERM); +#ifdef SLCURSES + SLsmg_gotorc(LINES-1, 0); + SLsmg_refresh(); +#else mvcur(0, COLS-1, LINES-1, 0); +#endif nl(); endwin(); printf("\n"); @@ -439,21 +494,65 @@ void write_sector(char *buffer, int sect_num) 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; +} + void get_dos_label(int i) { - char label[LABELSZ+1]; + char sector[128]; +#define DOS_OSTYPE_OFFSET 3 +#define DOS_LABEL_OFFSET 43 +#define DOS_FSTYPE_OFFSET 54 +#define DOS_OSTYPE_SZ 8 +#define DOS_LABEL_SZ 11 +#define DOS_FSTYPE_SZ 8 + ext2_loff_t offset; + + offset = ((ext2_loff_t) p_info[i].first_sector + p_info[i].offset) + * SECTOR_SIZE; + if (ext2_llseek(fd, offset, SEEK_SET) == offset + && read(fd, §or, sizeof(sector)) == sizeof(sector)) { + dos_copy_to_info(p_info[i].ostype, OSTYPESZ, + sector+DOS_OSTYPE_OFFSET, DOS_OSTYPE_SZ); + dos_copy_to_info(p_info[i].volume_label, LABELSZ, + sector+DOS_LABEL_OFFSET, DOS_LABEL_SZ); + dos_copy_to_info(p_info[i].fstype, FSTYPESZ, + sector+DOS_FSTYPE_OFFSET, DOS_FSTYPE_SZ); + } +} + +void get_ext2_label(int i) +{ +#define EXT2_SUPER_MAGIC 0xEF53 +#define EXT2LABELSZ 16 + struct ext2_super_block { + char s_dummy0[56]; + unsigned char s_magic[2]; + char s_dummy1[62]; + char s_volume_name[EXT2LABELSZ]; + char s_last_mounted[64]; + char s_dummy2[824]; + } sb; + char *label = sb.s_volume_name; ext2_loff_t offset; int j; offset = ((ext2_loff_t) p_info[i].first_sector + p_info[i].offset) - * SECTOR_SIZE + 43; + * SECTOR_SIZE + 1024; if (ext2_llseek(fd, offset, SEEK_SET) == offset - && read(fd, &label, LABELSZ) == LABELSZ) { - for(j=0; j<LABELSZ; j++) - if(!isascii(label[j])) + && read(fd, &sb, sizeof(sb)) == sizeof(sb) + && sb.s_magic[0] + 256*sb.s_magic[1] == EXT2_SUPER_MAGIC) { + for(j=0; j<EXT2LABELSZ; j++) + if(!isprint(label[j])) label[j] = 0; - label[LABELSZ] = 0; - strcpy(p_info[i].dos_label, label); + label[EXT2LABELSZ] = 0; + strncpy(p_info[i].volume_label, label, LABELSZ); + strncpy(p_info[i].fstype, "ext2", FSTYPESZ); } } @@ -560,7 +659,9 @@ void insert_empty_part(int i, int first, int last) p_info[i].flags = 0; p_info[i].id = FREE_SPACE; p_info[i].num = PRI_OR_LOG; - p_info[i].dos_label[0] = 0; + p_info[i].volume_label[0] = 0; + p_info[i].fstype[0] = 0; + p_info[i].ostype[0] = 0; num_parts++; } @@ -665,7 +766,9 @@ int add_part(int num, int id, int flags, int first, int last, int offset, ext_info.flags = flags; ext_info.id = id; ext_info.num = num; - ext_info.dos_label[0] = 0; + ext_info.volume_label[0] = 0; + ext_info.fstype[0] = 0; + ext_info.ostype[0] = 0; return 0; } else { return -1; /* explicit extended logical */ @@ -721,9 +824,15 @@ int add_part(int num, int id, int flags, int first, int last, int offset, p_info[i].flags = flags; p_info[i].id = id; p_info[i].num = num; - p_info[i].dos_label[0] = 0; - if (want_label && is_dos_partition(id)) - get_dos_label(i); + p_info[i].volume_label[0] = 0; + p_info[i].fstype[0] = 0; + p_info[i].ostype[0] = 0; + if (want_label) { + if (may_have_dos_label(id)) + get_dos_label(i); + else if (id == LINUX) + get_ext2_label(i); + } check_part_info(); @@ -881,7 +990,8 @@ int menuSelect( int y, int x, struct MenuItem *menuItems, int itemLength, char * while( !key ) { /* Display the menu */ - ylast = menuUpdate( y, x, menuItems, itemLength, available, menuType, current ); + ylast = menuUpdate( y, x, menuItems, itemLength, available, + menuType, current ); refresh(); key = getch(); /* Clear out all prompts and such */ @@ -996,8 +1106,9 @@ int menuSelect( int y, int x, struct MenuItem *menuItems, int itemLength, char * return key; } -/* 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? */ +/* 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? */ void menuContinue(void) { @@ -1176,7 +1287,15 @@ void fill_p_info(void) opentype = O_RDWR; opened = TRUE; - read_sector(buffer.c.b, 0); + /* 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 */ if (!ioctl(fd, HDIO_GETGEO, &geometry)) { if (!heads) @@ -1188,7 +1307,9 @@ void fill_p_info(void) } if (!heads || !sectors || !cylinders) - fatal(BAD_GEOMETRY); + fatal(BAD_GEOMETRY); /* probably a file or cdrom */ + + read_sector(buffer.c.b, 0); clear_p_info(); @@ -1651,7 +1772,7 @@ void print_part_entry(FILE *fp, int num, partition_info *pi) ec = end / heads; } - fp_printf(fp, "%2d 0x%02X %4d %4d %4d 0x%02X %4d %4d %4d %7d %9d\n", + fp_printf(fp, "%2d 0x%02X %4d %4d %4d 0x%02X %4d %4d %4d %8d %9d\n", num+1, flags, sh, ss, sc, id, eh, es, ec, first, size); } @@ -1688,9 +1809,9 @@ void print_part_table(void) fp_printf(fp, "Partition Table for %s\n", disk_device); fp_printf(fp, "\n"); - 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"); + 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; @@ -1761,7 +1882,7 @@ void display_help() "allows you to create, delete and modify partitions on your hard", "disk drive.", "", - "Copyright (C) 1994-1997 Kevin E. Martin & aeb", + "Copyright (C) 1994-1998 Kevin E. Martin & aeb", "", "Command Meaning", "------- -------", @@ -1984,6 +2105,7 @@ void draw_partition(int i) { int size, j; int y = i + DISK_TABLE_START + 2 - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN; + char *t; if (!arrow_cursor) { move(y, 0); @@ -1993,7 +2115,7 @@ void draw_partition(int i) if (p_info[i].id > 0) { mvprintw(y, NAME_START, - "%s%d", disk_device, p_info[i].num+1); + "%s%d", my_basename(disk_device), p_info[i].num+1); if (p_info[i].flags) { if (p_info[i].flags == ACTIVE_FLAG) mvaddstr(y, FLAGS_START, "Boot"); @@ -2022,18 +2144,18 @@ void draw_partition(int i) (p_info[i].num >= 0 ? "Primary" : (p_info[i].num == PRI_OR_LOG ? "Pri/Log" : (p_info[i].num == PRIMARY ? "Primary" : "Logical")))))); - if (p_info[i].id == UNUSABLE) - mvaddstr(y, FSTYPE_START, "Unusable"); - else if (p_info[i].id == FREE_SPACE) - mvaddstr(y, FSTYPE_START, "Free Space"); - else if (partition_type[p_info[i].id]) - mvaddstr(y, FSTYPE_START, partition_type[p_info[i].id]); + + t = partition_type_text(i); + if (t) + mvaddstr(y, FSTYPE_START, t); else - mvprintw(y, FSTYPE_START, "Unknown (%02X)", p_info[i].id); + mvprintw(y, FSTYPE_START, "Unknown (%02X)", p_info[i].id); - if (p_info[i].dos_label[0]) { - int l = strlen(p_info[i].dos_label); - mvprintw(y, SIZE_START-5-l, " [%s] ", p_info[i].dos_label); + 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; @@ -2056,6 +2178,7 @@ void init_const(void) 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; @@ -2101,8 +2224,9 @@ void draw_screen(void) mvaddstr(DISK_TABLE_START, NAME_START, "Name"); mvaddstr(DISK_TABLE_START, FLAGS_START, "Flags"); - mvaddstr(DISK_TABLE_START, PTYPE_START, "Part Type"); + 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) @@ -2178,6 +2302,8 @@ void do_curses_fdisk(void) }; curses_started = 1; initscr(); + init_const(); + old_SIGINT = signal(SIGINT, die); old_SIGTERM = signal(SIGTERM, die); #ifdef DEBUG @@ -2189,8 +2315,6 @@ void do_curses_fdisk(void) noecho(); nonl(); - init_const(); - fill_p_info(); draw_screen(); @@ -2353,6 +2477,8 @@ int main(int argc, char **argv) char c; int i, len; + setlocale(LC_CTYPE, ""); + while ((c = getopt(argc, argv, "ac:h:s:vzP:")) != EOF) switch (c) { case 'a': @@ -2429,5 +2555,6 @@ int main(int argc, char **argv) print_part_table(); } else do_curses_fdisk(); + return 0; } diff --git a/disk-utils/fdisk.8 b/disk-utils/fdisk.8 index 29d56c40b..576bce2ec 100644 --- a/disk-utils/fdisk.8 +++ b/disk-utils/fdisk.8 @@ -1,20 +1,50 @@ .\" Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu) +.\" Copyright 1998 Andries E. Brouwer (aeb@cwi.nl) .\" May be distributed under the GNU General Public License -.TH FDISK 8 "3 June 1995" "Linux 1.0" "Linux Programmer's Manual" +.TH FDISK 8 "11 June 1998" "Linux 2.0" "Linux Programmer's Manual" .SH NAME fdisk \- Partition table manipulator for Linux .SH SYNOPSIS -.B fdisk -.B "[ \-l ] [ \-v ] [ \-s partition] [" -device -.B ] +.BI "fdisk [\-b] [\-u] [" device ] +.sp +.BI "fdisk \-l [\-b] [\-u] [" "device ..." ] +.sp +.BI "fdisk \-s " "partition ..." +.sp +.BI "fdisk \-v .SH DESCRIPTION +Hard disks can be divided into one or more logical disks called +.IR partitions . +This division is described in the +.I "partition table" +found in sector 0 of the disk. + +In the BSD world one talks about `disk slices' and a `disklabel'. + +Linux needs at least one partition, namely for its root file system. +It can use swap files and/or swap partitions, but the latter are more +efficient. So, usually one will want a second Linux partition +dedicated as swap partition. +On Intel compatible hardware, the BIOS that boots the system +can often only access the first 1024 cylinders of the disk. +For this reason people with large disks often create a third partition, +just a few MB large, typically mounted on +.IR /boot , +to store the kernel image and a few auxiliary files needed at boot time, +so as to make sure that this stuff is accessible to the BIOS. +There may be reasons of security, ease of administration and backup, +or testing, to use more than the minimum number of partitions. + .B fdisk -is a menu driven program for manipulation of the hard disk partition table. +(in the first form of invocation) +is a menu driven program for creation and manipulation of +partition tables. +It understands DOS type partition tables and BSD or SUN type disklabels. + The .I device is usually one of the following: -.sp +.br .nf .RS /dev/hda @@ -23,54 +53,79 @@ is usually one of the following: /dev/sdb .RE .fi +(/dev/hd[a-h] for IDE disks, /dev/sd[a-p] for SCSI disks, +/dev/ed[a-d] for ESDI disks, /dev/xd[ab] for XT disks). +A device name refers to the entire disk. + The .I partition is a .I device name followed by a partition number. For example, .B /dev/hda1 -is the first partition on the first hard disk in the system. +is the first partition on the first IDE hard disk in the system. +IDE disks can have up to 63 partitions, SCSI disks up to 15. +See also +.IR /usr/src/linux/Documentation/devices.txt . + +A BSD/SUN type disklabel can describe 8 partitions, +the third of which should be a `whole disk' partition. +Do not start a partition that actually uses its first sector +(like a swap partition) at cylinder 0, since that will +destroy the disklabel. + +A DOS type partition table can describe an unlimited number +of partitions. In sector 0 there is room for the description +of 4 partitions (called `primary'). One of these may be an +extended partition; this is a box holding logical partitions, +with descriptors found in a linked list of sectors, each +preceding the corresponding logical partitions. +The four primary partitions, present or not, get numbers 1-4. +Logical partitions start numbering from 5. + +In a DOS type partition table the starting offset and the size +of each partition is stored in two ways: as an absolute number +of sectors (given in 32 bits) and as a Cylinders/Heads/Sectors +triple (given in 10+8+6 bits). The former is OK - with 512-byte +sectors this will work up to 2 TB. The latter has two different +problems. First of all, these C/H/S fields can be filled only +when the number of heads and the number of sectors per track +are known. Secondly, even if we know what these numbers should be, +the 24 bits that are available do not suffice. +DOS uses C/H/S only, Windows uses both, Linux never uses C/H/S. If possible, .B fdisk -will obtain the disk geometry automatically. This is -.I not -necessarily the -.I physical -disk geometry, but is the disk geometry that MS-DOS uses for the partition -table. If -.B fdisk -warns you that you need to set the disk geometry, please believe this -statement, and set the geometry. This should only be necessary with -certain SCSI host adapters (the drivers for which are rapidly being -modified to provide geometry information automatically). +will obtain the disk geometry automatically. This is not +necessarily the physical disk geometry (indeed, modern disks do not +really have anything like a physical geometry, certainly not something +that can be described in simplistic Cylinders/Heads/Sectors form), +but is the disk geometry that MS-DOS uses for the partition table. + +Usually all goes well by default, and there are no problems if +Linux is the only system on the disk. However, if the disk has +to be shared with other operating systems, it is often a good idea +to let an fdisk from another operating system make at least one +partition. When Linux boots it looks at the partition table, and +tries to deduce what (fake) geometry is required for good +cooperation with other systems. Whenever a partition table is printed out, a consistency check is performed on the partition table entries. This check verifies that the physical and logical start and end points are identical, and that the partition starts and ends on a cylinder boundary (except for the first partition). -Old versions of fdisk (all versions prior to 1.1r [including 0.93]) -incorrectly mapped the cylinder/head/sector specification onto absolute -sectors. This may result in the first partition on a drive failing the -consistency check. If you use LILO to boot, this situation can be ignored. -However, there are reports that the OS/2 boot manager will not boot a -partition with inconsistent data. - Some versions of MS-DOS create a first partition which does not begin on a cylinder boundary, but on sector 2 of the first cylinder. Partitions beginning in cylinder 1 cannot begin on a cylinder boundary, but this is unlikely to cause difficulty unless you have OS/2 on your machine. -In version 1.1r, a BLKRRPART ioctl() is performed before exiting when the -partition table is updated. This is primarily to ensure that removable -SCSI disks have their partition table information updated. If the kernel -does not update its partition table information, fdisk warns you to -reboot. If you do not reboot your system after receiving such a warning, -you may lose or corrupt the data on the disk. Sometimes BLKRRPART fails -silently, when installing Linux, you should -.I always -reboot after editing the partition table. +A sync() and a BLKRRPART ioctl() (reread partition table from disk) +are performed before exiting when the partition table has been updated. +Long ago it used to be necessary to reboot after the use of fdisk. +I do not think this is the case anymore - indeed, rebooting too quickly +might cause loss of not-yet-written data. Note that both the kernel +and the disk hardware may buffer data. .SH "DOS 6.x WARNING" @@ -91,10 +146,6 @@ partition table entry for /dev/hda1, then (after exiting fdisk or cfdisk and rebooting Linux so that the partition table information is valid) you would use the command "dd if=/dev/zero of=/dev/hda1 bs=512 count=1" to zero the first 512 bytes of the partition. -.B BE EXTREMELY CAREFUL -if you use the -.B dd -command, since a small typo can make all of the data on your disk useless. .B BE EXTREMELY CAREFUL if you use the @@ -108,59 +159,55 @@ program and Linux partitions with the Linux fdisk or Linux cfdisk program. .SH OPTIONS .TP .B \-v -Prints version number of +Print version number of .B fdisk -program. +program and exit. .TP .B \-l -Lists the partition tables for -.BR /dev/hda , -.BR /dev/hdb , -.BR /dev/sda , -.BR /dev/sdb , -.BR /dev/sdc , -.BR /dev/sdd , -.BR /dev/sde , -.BR /dev/sdf , -.BR /dev/sdg , -.BR /dev/sdh , -and then exits. +List the partition tables for +.BR /dev/hd[a-d] , +.BR /dev/sd[a-h] , +.BR /dev/ed[a-d] , +and then exit. .TP -.BI \-s partition -If the -.I partition -is not a DOS partition (i.e., the partition id is greater than 10), then -the +.B \-b +When listing partition tables, also output a `Begin' column, +as earlier versions of fdisk did by default. +(Note: the values in this column, when given in cylinder units, +cannot be larger than 1023. There is nothing wrong if Begin and Start +differ, at least not as far as Linux is concerned.) +.TP +.B \-u +When listing partition tables, give sizes in sectors instead +of cylinders. +.TP +.BI "\-s " partition +The .I size -of that partition is printed on the standard output. This value is -normally used as an argument to the +of the partition (in blocks) is printed on the standard output. +This value is normally used as an argument to the .BR mkfs (8) program to specify the size of the partition which will be formatted. -.SH BUGS -Although this man page (written by faith@cs.unc.edu) is poor, there is -.I excellent -documentation in the README.fdisk file (written by LeBlanc@mcc.ac.uk) that -should always be with the fdisk distribution. If you cannot find this file -in the -.I util-linux-* -directory or with the -.I fdisk.c -source file, then you should write to the distributor of your version of +(Older versions of fdisk would do this only if the partition id is +greater than 10, in an attempt to refuse DOS partitions; +this test has been deleted.) +Note that +.B "sfdisk -s" +gives different (namely, correct) answers. +Reasons for the difference are that the kernel and .B fdisk -and complain that you do not have all of the available documentation. -.SH AUTHOR -A. V. Le Blanc (LeBlanc@mcc.ac.uk) -.br -v1.0r: SCSI and extfs support added by Rik Faith (faith@cs.unc.edu) -.br -v1.1r: Bug fixes and enhancements by Rik Faith (faith@cs.unc.edu), with -special thanks to Michael Bischoff (i1041905@ws.rz.tu-bs.de or -mbi@mo.math.nat.tu-bs.de). -.br -v1.3: Latest enhancements and bug fixes by A. V. Le Blanc, including the -addition of the -.B \-s -option. -.bt -v2.0: Disks larger than 2GB are now fully supported, thanks to Remy Card's -llseek support. +need not have the same idea about partition numbering +(e.g., in case you have BSD slices), and have different +ideas about the size of an extended partition. +.SH BUGS +There are several *fdisk programs around. +Each has its problems and strengths. +Try them in the order +.BR cfdisk , +.BR fdisk , +.BR sfdisk . +.\" .SH AUTHORS +.\" A. V. Le Blanc (LeBlanc@mcc.ac.uk) +.\" Bernhard Fastenrath (fasten@informatik.uni-bonn.de) +.\" Jakub Jelinek (jj@sunsite.mff.cuni.cz) +.\" and many others. diff --git a/disk-utils/fdisk.c b/disk-utils/fdisk.c index 95b958d82..d99a8b452 100644 --- a/disk-utils/fdisk.c +++ b/disk-utils/fdisk.c @@ -49,7 +49,18 @@ * Tue Sep 26 17:07:54 1995: More patches from aeb. Fix segfaults, all >4GB. * Don't destroy random data if extd partition starts past 4GB, aeb, 950818. * Don't segfault on bad partition created by previous fdisk. - * + * Modified, Fri Jul 14 11:13:35 MET DST 1996, jj@sunsite.mff.cuni.cz: + * editor for Sun disklabels. + * Modified, Wed Jul 3 10:14:17 MET DST 1996, jj@sunsite.mff.cuni.cz: + * support for Sun floppies + * Modified, Thu Jul 24 16:42:33 MET DST 1997, fasten@shw.com: + * LINUX_EXTENDED support + * Added Windows 95 partition types, aeb. + * Fixed a bug described by johnf@whitsunday.net.au, aeb, 980408. + * [There are lots of other bugs - nobody should use this program] + * [cfdisk on the other hand is nice and correct] + * Try to avoid reading a CD-ROM. + * Do not print Begin column -- it confuses too many people -- aeb, 980610. */ @@ -61,14 +72,18 @@ #include <ctype.h> #include <setjmp.h> #include <errno.h> +#include <getopt.h> +#include <sys/stat.h> #include <sys/ioctl.h> -#include <linux/genhd.h> -#include <linux/hdreg.h> -#include <linux/fs.h> +#include <linux/hdreg.h> /* for HDIO_GETGEO */ +#include <linux/fs.h> /* for BLKRRPART, BLKGETSIZE */ #include "fdisk.h" +#if defined(sparc) +#include "fdisksunlabel.h" +#endif #define hex_val(c) ({ \ char _c = (c); \ @@ -77,14 +92,11 @@ }) -#define VERSION "2.1 (>4GB)" +#define VERSION "2.8" /* util-linux version */ #define DEFAULT_DEVICE "/dev/hda" #define ALTERNATE_DEVICE "/dev/sda" #define LINE_LENGTH 80 -#define MAXIMUM_PARTS 60 -#define PART_TABLE_FLAG 0xaa55 -#define table_check(b) ((unsigned short *)((b) + 0x1fe)) #define offset(b, n) ((struct partition *)((b) + 0x1be + \ (n) * sizeof(struct partition))) #define sector(s) ((s) & 0x3f) @@ -101,12 +113,70 @@ s |= (sector >> 2) & 0xc0; \ } +/* A valid partition table sector ends in 0x55 0xaa */ +unsigned int +part_table_flag(char *b) { + return ((uint) b[510]) + (((uint) b[511]) << 8); +} + +int +valid_part_table_flag(unsigned char *b) { + return (b[510] == 0x55 && b[511] == 0xaa); +} + +void +write_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 */ +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); +} + +unsigned int +read4_little_endian(unsigned char *cp) { + return (uint)(cp[0]) + ((uint)(cp[1]) << 8) + + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24); +} + +void +set_start_sect(struct partition *p, unsigned int start_sect) { + store4_little_endian(p->start4, start_sect); +} + +unsigned int +get_start_sect(struct partition *p) { + return read4_little_endian(p->start4); +} + +void +set_nr_sects(struct partition *p, unsigned int nr_sects) { + store4_little_endian(p->size4, nr_sects); +} + +unsigned int +get_nr_sects(struct partition *p) { + return read4_little_endian(p->size4); +} + #define ACTIVE_FLAG 0x80 -#define EXTENDED 5 +#define EXTENDED 0x05 +#define WIN98_EXTENDED 0x0f #define LINUX_PARTITION 0x81 #define LINUX_SWAP 0x82 #define LINUX_NATIVE 0x83 +#define LINUX_EXTENDED 0x85 + +#define IS_EXTENDED(i) \ + ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED) /* normally O_RDWR, -l option gives O_RDONLY */ static int type_open = O_RDWR; @@ -122,6 +192,8 @@ char *disk_device = DEFAULT_DEVICE, /* hda, unless specified */ 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 */ + show_begin = 0, dos_compatible_flag = ~0, partitions = 4; /* maximum partition + 1 */ @@ -135,51 +207,59 @@ uint heads, extended_offset = 0, /* offset of link pointers */ offsets[MAXIMUM_PARTS] = {0, 0, 0, 0}; +int sun_label = 0; /* looking at sun disklabel */ + struct partition *part_table[MAXIMUM_PARTS] /* partitions */ = {offset(buffer, 0), offset(buffer, 1), offset(buffer, 2), offset(buffer, 3)}, *ext_pointers[MAXIMUM_PARTS] /* link pointers */ = {NULL, NULL, NULL, NULL}; -struct systypes sys_types[] = { /* struct systypes in fdisk.h *//* bf */ - {0, "Empty"}, - {1, "DOS 12-bit FAT"}, - {2, "XENIX root"}, - {3, "XENIX usr"}, - {4, "DOS 16-bit <32M"}, - {EXTENDED, "Extended"}, - {6, "DOS 16-bit >=32M"}, - {7, "OS/2 HPFS"}, /* or QNX? */ - {8, "AIX"}, - {9, "AIX bootable"}, - {10, "OS/2 Boot Manager"}, - {0x40, "Venix 80286"}, - {0x51, "Novell?"}, - {0x52, "Microport"}, /* or CPM? */ - {0x63, "GNU HURD"}, /* or System V/386? */ - {0x64, "Novell Netware 286"}, - {0x65, "Novell Netware 386"}, - {0x75, "PC/IX"}, - {0x80, "Old MINIX"}, /* Minix 1.4a and earlier */ - - {LINUX_PARTITION, "Linux/MINIX"}, /* Minix 1.4b and later */ - {LINUX_SWAP, "Linux swap"}, - {LINUX_NATIVE, "Linux native"}, - - {0x93, "Amoeba"}, - {0x94, "Amoeba BBT"}, /* (bad block table) */ - {0xa5, "BSD/386"}, - {0xb7, "BSDI fs"}, - {0xb8, "BSDI swap"}, - {0xc7, "Syrinx"}, - {0xdb, "CP/M"}, /* or Concurrent DOS? */ - {0xe1, "DOS access"}, - {0xe3, "DOS R/O"}, - {0xf2, "DOS secondary"}, - {0xff, "BBT"} /* (bad track table) */ - }; - -int nsys_types = sizeof (sys_types) / sizeof (struct systypes); /* bf */ +struct systypes sys_types[] = { + {0x00, "Empty"}, + {0x01, "DOS 12-bit FAT"}, + {0x02, "XENIX root"}, + {0x03, "XENIX usr"}, + {0x04, "DOS 16-bit <32M"}, + {0x05, "Extended"}, + {0x06, "DOS 16-bit >=32M"}, + {0x07, "OS/2 HPFS"}, /* or QNX? */ + {0x08, "AIX"}, + {0x09, "AIX bootable"}, + {0x0a, "OS/2 Boot Manager"}, + {0x0b, "Win95 FAT32"}, + {0x0c, "Win95 FAT32 (LBA)"}, + {0x0e, "Win95 FAT16 (LBA)"}, + {0x0f, "Win95 Extended (LBA)"}, + {0x40, "Venix 80286"}, + {0x51, "Novell?"}, + {0x52, "Microport"}, /* or CPM? */ + {0x63, "GNU HURD"}, /* or System V/386? */ + {0x64, "Novell Netware 286"}, + {0x65, "Novell Netware 386"}, + {0x75, "PC/IX"}, + {0x80, "Old MINIX"}, /* Minix 1.4a and earlier */ + + {LINUX_PARTITION, "Linux/MINIX"}, /* Minix 1.4b and later */ + {LINUX_SWAP, "Linux swap"}, + {LINUX_NATIVE, "Linux native"}, + {LINUX_EXTENDED, "Linux extended"}, + + {0x93, "Amoeba"}, + {0x94, "Amoeba BBT"}, /* (bad block table) */ + {0xa5, "BSD/386"}, + {0xa6, "OpenBSD"}, + {0xa7, "NEXTSTEP"}, + {0xb7, "BSDI fs"}, + {0xb8, "BSDI swap"}, + {0xc7, "Syrinx"}, + {0xdb, "CP/M"}, /* or Concurrent DOS? */ + {0xe1, "DOS access"}, + {0xe3, "DOS R/O"}, + {0xf2, "DOS secondary"}, + {0xff, "BBT"}, /* (bad track table) */ + { 0, NULL } +}; jmp_buf listingbuf; @@ -195,7 +275,10 @@ void fatal(enum failure why) switch (why) { case usage: message = - "Usage: fdisk [-l] [-v] [-s /dev/hdxn] [/dev/hdx]\n"; +"Usage: fdisk [-b] [-u] [/dev/hdx] Change partition table\n" +" fdisk -l [-b] [-u] [/dev/hdx] List partition table(s)\n" +" fdisk -s /dev/hdxn Give partition size(s)\n" +" fdisk -v Give fdisk version\n"; break; case unable_to_open: sprintf(error, "Unable to open %s\n", disk_device); @@ -222,14 +305,35 @@ void fatal(enum failure why) void menu(void) { - puts("Command action\n" + if (sun_label) + puts("Command action\n" + " a toggle a read only flag\n" /* sun */ + " b edit bsd disklabel\n" + " c toggle the mountable flag\n" /* sun */ + " d delete a partition\n" + " l list known partition types\n" + " m print this menu\n" + " n add a new partition\n" + " o create a new empty DOS partition table\n" + " p print the partition table\n" + " q quit without saving changes\n" + " s create a new empty Sun disklabel\n" /* sun */ + " t change a partition's system id\n" + " u change display/entry units\n" + " v verify the partition table\n" + " w write table to disk and exit\n" + " x extra functionality (experts only)" + ); + else + puts("Command action\n" " a toggle a bootable flag\n" - " b edit bsd disklabel\n" /* bf */ + " b edit bsd disklabel\n" " c toggle the dos compatibility flag\n" " d delete a partition\n" " l list known partition types\n" " m print this menu\n" " n add a new partition\n" + " o create a new empty DOS partition table\n" " p print the partition table\n" " q quit without saving changes\n" " t change a partition's system id\n" @@ -237,16 +341,35 @@ void menu(void) " v verify the partition table\n" " w write table to disk and exit\n" " x extra functionality (experts only)" - ); + ); } void xmenu(void) { - puts("Command action\n" - " b move beginning of data in a partition\n" + if (sun_label) + puts("Command action\n" + " a change number of alternate cylinders\n" /* sun */ + " c change number of cylinders\n" + " d print the raw data in the partition table\n" + " e change number of extra sectors per cylinder\n" /*sun*/ + " h change number of heads\n" + " i change interleave factor\n" /* sun */ + " o change rotation speed (rpm)\n" /* sun */ + " m print this menu\n" + " p print the partition table\n" + " q quit without saving changes\n" + " r return to main menu\n" + " s change number of sectors\n" + " v verify the partition table\n" + " w write table to disk and exit\n" + " y change number of physical cylinders" /* sun */ + ); + else + puts("Command action\n" + " b move beginning of data in a partition\n" /* !sun */ " c change number of cylinders\n" " d print the raw data in the partition table\n" - " e list extended partitions\n" + " e list extended partitions\n" /* sun */ " h change number of heads\n" " m print this menu\n" " p print the partition table\n" @@ -255,34 +378,36 @@ void xmenu(void) " s change number of sectors\n" " v verify the partition table\n" " w write table to disk and exit" - ); + ); } char *partition_type(unsigned char type) { - int high = sizeof(sys_types) / sizeof(struct systypes), - low = 0, mid; - uint tmp; - - while (high >= low) { - mid = (high + low) >> 1; - if ((tmp = sys_types[mid].index) == type) - return sys_types[mid].name; - else if (tmp < type) - low = mid + 1; - else high = mid - 1; - } + int i; + struct systypes *types; + +#if defined(sparc) + if (sun_label) + types = sun_sys_types; + else +#endif + types = sys_types; + + for (i=0; types[i].name; i++) + if (types[i].index == type) + return types[i].name; + return NULL; } -/* added parameters to list_types() so fdisklabel - can pass another list of types. -*//* bf */ -void list_types(struct systypes *sys, int size) +void list_types(struct systypes *sys) { - uint last[4], done = 0, next = 0; + uint 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; @@ -309,17 +434,17 @@ void clear_partition(struct partition *p) p->end_head = 0; p->end_sector = 0; p->end_cyl = 0; - p->start_sect = 0; - p->nr_sects = 0; + set_start_sect(p,0); + set_nr_sects(p,0); } void set_partition(int i, struct partition *p, uint start, uint stop, - int sys, uint offset) + int sysid, uint offset) { p->boot_ind = 0; - p->sys_ind = sys; - p->start_sect = start - offset; - p->nr_sects = stop - start + 1; + p->sys_ind = sysid; + set_start_sect(p, start - offset); + set_nr_sects(p, stop - start + 1); if (dos_compatible_flag && (start/(sectors*heads) > 1023)) start = heads*sectors*1024 - 1; set_hsc(p->head, p->sector, p->cyl, start); @@ -380,13 +505,13 @@ void update_units(void) void warn_cylinders(void) { - update_units(); - if (cylinders > 1024) - fprintf(stderr, "The number of cylinders for this disk is " - "set to %d.\nThis is larger than 1024, and may cause " + if (!sun_label && cylinders > 1024 && !nowarn) + fprintf(stderr, + "The number of cylinders for this disk is set to %d.\n" + "This is larger than 1024, and may cause " "problems with:\n" "1) software that runs at boot time (e.g., LILO)\n" - "2) booting and partitioning software form other OSs\n" + "2) booting and partitioning software from other OSs\n" " (e.g., DOS FDISK, OS/2 FDISK)\n", cylinders); } @@ -397,9 +522,9 @@ void read_extended(struct partition *p) struct partition *q; ext_pointers[ext_index] = part_table[ext_index]; - if (!p->start_sect) + if (!get_start_sect(p)) fprintf(stderr, "Bad offset in primary extended partition\n"); - else while (p->sys_ind == EXTENDED) { + else while (IS_EXTENDED (p->sys_ind)) { if (partitions >= MAXIMUM_PARTS) { fprintf(stderr, "Warning: deleting partitions after %d\n", @@ -408,9 +533,9 @@ void read_extended(struct partition *p) changed[partitions - 1] = 1; return; } - offsets[partitions] = extended_offset + p->start_sect; + offsets[partitions] = extended_offset + get_start_sect(p); if (!extended_offset) - extended_offset = p->start_sect; + extended_offset = get_start_sect(p); if (ext2_llseek(fd, (ext2_loff_t)offsets[partitions] * SECTOR_SIZE, SEEK_SET) < 0) fatal(unable_to_seek); @@ -421,7 +546,7 @@ void read_extended(struct partition *p) part_table[partitions] = ext_pointers[partitions] = NULL; q = p = offset(buffers[partitions], 0); for (i = 0; i < 4; i++, p++) { - if (p->sys_ind == EXTENDED) + if (IS_EXTENDED (p->sys_ind)) if (ext_pointers[partitions]) fprintf(stderr, "Warning: extra link " "pointer in partition table " @@ -449,19 +574,50 @@ void read_extended(struct partition *p) } } -int get_boot(void) +void create_doslabel(void) +{ + int i; + + fprintf(stderr, + "Building a new DOS disklabel. Changes will remain in memory only,\n" + "until you decide to write them. After that, of course, the previous\n" + "content won't be recoverable.\n\n"); + + write_part_table_flag(buffer); + for (i = 0; i < 4; i++) + clear_partition(part_table[i]); + for (i = 1; i < MAXIMUM_PARTS; i++) + changed[i] = 0; + changed[0] = 1; + get_boot(create_empty); +} + +/* + * Read MBR. Returns: + * -1: no 0xaa55 flag present (possibly entire disk BSD) + * 0: found or created label + */ +int get_boot(enum action what) { int i; struct hd_geometry geometry; partitions = 4; - if ((fd = open(disk_device, type_open)) < 0) - { + + if (what == create_empty) + goto got_table; /* skip reading disk */ + + if ((fd = open(disk_device, type_open)) < 0) { if ((fd = open(disk_device, O_RDONLY)) < 0) fatal(unable_to_open); else printf("You will not be able to write the partition table.\n"); } + +#if defined(sparc) + guess_device_type(fd); +#endif + if (SECTOR_SIZE != read(fd, buffer, SECTOR_SIZE)) fatal(unable_to_read); @@ -475,31 +631,67 @@ int get_boot(void) cylinders = geometry.cylinders; if (dos_compatible_flag) sector_offset = sectors; - warn_cylinders(); + } else { + if (!ioctl(fd, BLKGETSIZE, §ors)) { + heads = 1; + cylinders = 1; + } else { + heads = cylinders = sectors = 0; + } } - else update_units(); - warn_geometry(); + update_units(); + +got_table: - if (*(unsigned short *) (0x1fe + buffer) != 0xAA55) { - return 0; /* not a valid partition table */ +#if defined(sparc) + if (check_sun_label()) + return 0; +#endif + + if (!valid_part_table_flag(buffer)) { + switch(what) { + case fdisk: + fprintf(stderr, + "Device contains neither a valid DOS partition" + " table, nor Sun disklabel\n"); +#ifdef __sparc__ + create_sunlabel(); +#else + create_doslabel(); +#endif + return 0; + case require: + return -1; + case try_only: + return -1; + case create_empty: + break; + } + + fprintf(stderr, "Internal error\n"); + exit(1); } + warn_cylinders(); + warn_geometry(); + for (i = 0; i < 4; i++) - if(part_table[i]->sys_ind == EXTENDED) + if(IS_EXTENDED (part_table[i]->sys_ind)) if (partitions != 4) fprintf(stderr, "Ignoring extra extended " "partition %d\n", i + 1); else read_extended(part_table[ext_index = i]); for (i = 3; i < partitions; i++) - if (*table_check(buffers[i]) != PART_TABLE_FLAG) { - fprintf(stderr, "Warning: invalid flag %04x of parti" - "tion table %d will be corrected by w(rite)\n", - *table_check(buffers[i]), i + 1); + if (!valid_part_table_flag(buffers[i])) { + fprintf(stderr, + "Warning: invalid flag 0x%04x of partition " + "table %d will be corrected by w(rite)\n", + part_table_flag(buffers[i]), i + 1); changed[i] = 1; } - return 1; + return 0; } int read_line(void) @@ -514,14 +706,23 @@ int read_line(void) char read_char(char *mesg) { - do + do { fputs(mesg, stdout); - while (!read_line()); + } while (!read_line()); return *line_ptr; } -/* new function *//* bf */ -int read_hex(struct systypes *sys, int size) +char read_chars(char *mesg) +{ + fputs(mesg, stdout); + if (!read_line()) { + *line_ptr = '\n'; + return '\n'; + } else + return *line_ptr; +} + +int read_hex(struct systypes *sys) { int hex; @@ -529,7 +730,7 @@ int read_hex(struct systypes *sys, int size) { read_char("Hex code (type L to list codes): "); if (tolower(*line_ptr) == 'l') - list_types(sys, size); + list_types(sys); else if (isxdigit (*line_ptr)) { hex = 0; @@ -563,9 +764,17 @@ uint read_int(uint low, uint dflt, uint high, enum offset base, char *mesg) } while (1) { - while (!isdigit(read_char(ms)) - && (*line_ptr != '-' && *line_ptr != '+')) - continue; + if (base == deflt) { + while (read_chars(ms) != '\n' && !isdigit(*line_ptr) + && *line_ptr != '-' && *line_ptr != '+') + continue; + if (*line_ptr == '\n') + return dflt; + } else { + while (!isdigit(read_char(ms)) + && *line_ptr != '-' && *line_ptr != '+') + continue; + } if (*line_ptr == '+' || *line_ptr == '-') { if (*line_ptr == '+') ++line_ptr; @@ -624,9 +833,14 @@ int get_partition(int warn, int max) */ int i = read_int(1, max, max, ignore, "Partition number") - 1; - if (warn && !part_table[i]->sys_ind) - fprintf(stderr, "Warning: partition %d has empty type\n", - i + 1); + if (warn && ( + (!sun_label && !part_table[i]->sys_ind) +#if defined(sparc) + || (sun_label && + (!sunlabel->partitions[i].num_sectors || + !sunlabel->infos[i].id)) +#endif + )) fprintf(stderr, "Warning: partition %d has empty type\n", i+1); return i; } @@ -649,7 +863,7 @@ void toggle_active(int i) { struct partition *p = part_table[i]; - if (p->sys_ind == EXTENDED && !p->boot_ind) + if (IS_EXTENDED (p->sys_ind) && !p->boot_ind) fprintf(stderr, "WARNING: Partition %d is an extended partition\n", i + 1); @@ -683,8 +897,14 @@ void delete_partition(int i) if (warn_geometry()) return; changed[i] = 1; +#if defined(sparc) + if (sun_label) { + sun_delete_partition(i); + return; + } +#endif if (i < 4) { - if (p->sys_ind == EXTENDED && i == ext_index) { + if (IS_EXTENDED (p->sys_ind) && i == ext_index) { while (partitions > 4) free(buffers[--partitions]); ext_pointers[ext_index] = NULL; @@ -707,14 +927,14 @@ void delete_partition(int i) p->end_head = q->end_head; p->end_sector = q->end_sector; p->end_cyl = q->end_cyl; - p->start_sect = q->start_sect; - p->nr_sects = q->nr_sects; + set_start_sect(p, get_start_sect(q)); + set_nr_sects(p, get_nr_sects(q)); changed[i - 1] = 1; - } - else { - if(part_table[5]) /* prevent SEGFAULT */ - part_table[5]->start_sect += - offsets[5] - extended_offset; + } else { + if(part_table[5]) /* prevent SEGFAULT */ + set_start_sect(part_table[5], + get_start_sect(part_table[5]) + + offsets[5] - extended_offset); offsets[5] = extended_offset; changed[5] = 1; } @@ -738,53 +958,65 @@ void delete_partition(int i) void change_sysid(void) { char *temp; - int i = get_partition(0, partitions), sys; + int i = get_partition(0, partitions), sys, origsys; struct partition *p = part_table[i]; - if ((sys = p->sys_ind) == EXTENDED) - printf("Partition %d is extended. Delete it\n", i + 1); - else if (!sys) - printf("Partition %d does not exist yet!\n", i + 1); - else while (1) { -#if 0 - read_char("Hex code (type L to list codes): "); - if (tolower(*line_ptr) == 'l') - list_types(); - else if (isxdigit(*line_ptr)) { - sys = 0; - do - sys = sys << 4 | hex_val(*line_ptr++); - while (isxdigit(*line_ptr)); +#if defined(sparc) + if (sun_label) + sys = sunlabel->infos[i].id; + else +#endif + sys = p->sys_ind; + origsys = sys; + + if (!sys) + printf("Partition %d does not exist yet!\n", i + 1); + else while (1) { + if (!sun_label) + sys = read_hex (sys_types); +#if defined(sparc) + else + sys = read_hex (sun_sys_types); #endif - /* The above code has been moved to read_hex () - to avoid having the same code in fdisklabel. - *//* bf */ - sys = read_hex (sys_types, nsys_types); /* bf */ - if (!sys) { - delete_partition(i); - break; - } - else if (sys == EXTENDED) { - printf("You may not change a partition " - "to be an extended partition\n"); - break; - } - else if (sys < 256) { - if (sys == p->sys_ind) - break; - part_table[i]->sys_ind = sys; - printf ("Changed system type of partition %d " - "to %x (%s)\n", i + 1, sys, - (temp = partition_type(sys)) ? temp : - "Unknown"); - changed[i] = 1; + if (!sys) { + delete_partition(i); + break; + } + + if (!sun_label) { + if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) { + printf("You cannot change a partition into" + " an extended one or vice versa\n" + "Delete it first.\n"); break; } -#if 0 /* see above *//* bf */ } + + if (sys < 256) { +#if defined(sparc) + if (sun_label && i == 2 && sys != WHOLE_DISK) + printf("Consider leaving partition 3 " + "as Whole disk (5),\n" + "as SunOS/Solaris expects it and " + "even Linux likes it.\n"); #endif - } + if (sys == origsys) + break; +#if defined(sparc) + if (sunlabel) { + sun_change_sysid(i, sys); + } else +#endif + part_table[i]->sys_ind = sys; + printf ("Changed system type of partition %d " + "to %x (%s)\n", i + 1, sys, + (temp = partition_type(sys)) ? temp : + "Unknown"); + changed[i] = 1; + break; + } + } } /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993, @@ -823,10 +1055,10 @@ static void check_consistency(struct partition *p, int partition) pes = p->end_sector & 0x3f; /* compute logical beginning (c, h, s) */ - long2chs(p->start_sect, &lbc, &lbh, &lbs); + long2chs(get_start_sect(p), &lbc, &lbh, &lbs); /* compute logical ending (c, h, s) */ - long2chs(p->start_sect + p->nr_sects - 1, &lec, &leh, &les); + long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les); /* Same physical / logical beginning? */ if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) { @@ -864,37 +1096,52 @@ static void check_consistency(struct partition *p, int partition) } } -void list_table(void) +void list_table(int xtra) { struct partition *p; char *type; - int i, w = strlen(disk_device); + int i, w; + +#if defined(sparc) + if (sun_label) + sun_list_table(xtra); + return; +#endif + + w = strlen(disk_device); printf("\nDisk %s: %d heads, %d sectors, %d cylinders\nUnits = " "%ss of %d * 512 bytes\n\n", disk_device, heads, sectors, cylinders, str_units(), display_factor); if (w < 5) w = 5; - printf("%*s Boot Begin Start End Blocks Id System\n", - w + 1, "Device"); - for (i = 0 ; i < partitions; i++) + printf("%*s Boot %s Start End Blocks Id System\n", + w + 1, "Device", show_begin ? " Begin " : " "); + + for (i = 0 ; i < partitions; i++) { if ((p = part_table[i])->sys_ind) { - printf("%*s%-2d %c%9d%9d%9d%9d%c %2x %s\n", w, -/* device */ disk_device, i + 1, + unsigned int psects = get_nr_sects(p); + printf( + show_begin + ? "%*s%-2d %c%9d%9d%9d%9d%c %2x %s\n" + : "%*s%-2d %c%c%9d%9d%9d%c %2x %s\n", +/* device */ w, disk_device, i+1, /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG ? '*' : '?', + show_begin ? /* begin */ cround(rounded( calculate(p->head, p->sector, p->cyl), - p->start_sect + offsets[i])), -/* start */ cround(p->start_sect + offsets[i]), -/* end */ cround(p->start_sect + offsets[i] + p->nr_sects - - (p->nr_sects ? 1: 0)), -/* odd flag on end */ p->nr_sects / 2, p->nr_sects & 1 ? '+' : ' ', + get_start_sect(p) + offsets[i])) + : ' ', +/* start */ cround(get_start_sect(p) + offsets[i]), +/* end */ cround(get_start_sect(p) + offsets[i] + psects + - (psects ? 1 : 0)), +/* odd flag on end */ psects / 2, (psects & 1) ? '+' : ' ', /* type id */ p->sys_ind, /* type name */ (type = partition_type(p->sys_ind)) ? type : "Unknown"); check_consistency(p, i); } - + } } void x_list_table(int extend) @@ -917,7 +1164,7 @@ void x_list_table(int extend) cylinder(p->sector, p->cyl), p->end_head, sector(p->end_sector), cylinder(p->end_sector, p->end_cyl), - p->start_sect, p->nr_sects, p->sys_ind); + get_start_sect(p), get_nr_sects(p), p->sys_ind); if (p->sys_ind) check_consistency(p, i); } @@ -931,16 +1178,17 @@ void check_bounds(uint *first, uint *last) partition crossing cylinder 8064 */ struct partition *p = part_table[0]; - for (i = 0; i < partitions; p = part_table[++i]) - if (!p->sys_ind || p->sys_ind == EXTENDED) { + for (i = 0; i < partitions; p = part_table[++i]) { + if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) { first[i] = max; last[i] = 0; - } - else { + } else { first[i] = rounded(calculate(p->head, p->sector, - p->cyl), p->start_sect + offsets[i]); - last[i] = p->start_sect + offsets[i] + p->nr_sects - 1; + p->cyl), get_start_sect(p) + offsets[i]); + last[i] = get_start_sect(p) + offsets[i] + + get_nr_sects(p) - 1; } + } } void check(int n, uint h, uint s, uint c, uint start) @@ -984,11 +1232,17 @@ void verify(void) if (warn_geometry()) return; +#if defined(sparc) + if (sun_label) + verify_sun(); + return; +#endif + check_bounds(first, last); for (i = 0; i < partitions; p = part_table[++i]) - if (p->sys_ind && (p->sys_ind != EXTENDED)) { + if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) { check_consistency(p, i); - if (p->start_sect + offsets[i] < first[i]) + if (get_start_sect(p) + offsets[i] < first[i]) printf("Warning: bad start-of-data in " "partition %d\n", i + 1); check(i + 1, p->end_head, p->end_sector, p->end_cyl, @@ -1007,8 +1261,8 @@ void verify(void) } if (extended_offset) { - uint e_last = part_table[ext_index]->start_sect + - part_table[ext_index]->nr_sects - 1; + uint e_last = get_start_sect(part_table[ext_index]) + + get_nr_sects(part_table[ext_index]) - 1; for (p = part_table[i = 4]; i < partitions; p = part_table[++i]) { @@ -1051,12 +1305,12 @@ void add_partition(int n, int sys) limit = heads * sectors * cylinders - 1; if (extended_offset) { first[ext_index] = extended_offset; - last[ext_index] = q->start_sect + q->nr_sects - 1; + last[ext_index] = get_start_sect(q) + + get_nr_sects(q) - 1; } - } - else { + } else { start = extended_offset + sector_offset; - limit = q->start_sect + q->nr_sects - 1; + limit = get_start_sect(q) + get_nr_sects(q) - 1; } if (unit_flag) for (i = 0; i < partitions; i++) @@ -1066,30 +1320,30 @@ void add_partition(int n, int sys) do { temp = start; for (i = 0; i < partitions; i++) { + int lastplusoff; + if (start == offsets[i]) start += sector_offset; - if (start >= first[i] && start <= last[i]) - if (n < 4) - start = last[i] + 1; - else - start = last[i] + sector_offset; + lastplusoff = last[i] + ((n<4) ? 0 : sector_offset); + if (start >= first[i] && start <= lastplusoff) + start = lastplusoff + 1; } if (start > limit) break; - if (start != temp && read) { + if (start >= temp+display_factor && read) { printf("Sector %d is already allocated\n", temp); - temp = start = stop; + temp = start; read = 0; } if (!read && start == temp) { uint i; - i = (stop = start) + (n > 4); + i = start; start = read_int(cround(i), cround(i), cround(limit), ignore, mesg); if (unit_flag) { start = (start - 1) * display_factor; if (start < i) start = i; - } + } read = 1; } } while (start != temp || !read); @@ -1126,7 +1380,7 @@ void add_partition(int n, int sys) set_partition(n, p, start, stop, sys, offsets[n]); - if (sys == EXTENDED) { + if (IS_EXTENDED (sys)) { ext_index = n; offsets[4] = extended_offset = start; ext_pointers[n] = p; @@ -1143,7 +1397,7 @@ void add_partition(int n, int sys) start - sector_offset, stop, EXTENDED, extended_offset); #if 0 - if ((limit = p->nr_sects) & 1) + if ((limit = get_nr_sects(p)) & 1) printf("Warning: partition %d has an odd " "number of sectors.\n", n + 1); #endif @@ -1169,6 +1423,13 @@ void new_partition(void) if (warn_geometry()) return; + +#if defined(sparc) + if (sun_label) + add_sun_partition(get_partition(0, partitions), LINUX_NATIVE); + return; +#endif + if (partitions >= MAXIMUM_PARTS) { printf("The maximum number of partitions has been created\n"); return; @@ -1214,14 +1475,24 @@ void write_table(void) int i, error = 0; changed[3] = changed[0] || changed[1] || changed[2] || changed[3]; - for (i = 3; i < partitions; i++) + if (!sun_label) { + for (i = 3; i < partitions; i++) { if (changed[i]) { - *table_check(buffers[i]) = PART_TABLE_FLAG; + write_part_table_flag(buffers[i]); if (ext2_llseek(fd, (ext2_loff_t)offsets[i] * SECTOR_SIZE, SEEK_SET) < 0) fatal(unable_to_seek); if (write(fd, buffers[i], SECTOR_SIZE) != SECTOR_SIZE) fatal(unable_to_write); + } + } + } else { +#if defined(sparc) + if (changed[3] || changed[4] || changed[5] || + changed[6] || changed[7]) { + sun_write_table(); + } +#endif } printf("The partition table has been altered!\n\n"); @@ -1252,9 +1523,11 @@ void write_table(void) "system to ensure the partition table is updated.\n", error, strerror(error)); - printf( "\nWARNING: If you have created or modified any DOS 6.x\n" + if (!sun_label) + printf( + "\nWARNING: If you have created or modified any DOS 6.x\n" "partitions, please see the fdisk manual page for additional\n" - "information.\n" ); + "information.\n"); exit(0); } @@ -1284,7 +1557,9 @@ void print_raw(void) int i; printf("Device: %s\n", disk_device); - for (i = 3; i < partitions; i++) + if (sun_label) + print_buffer(buffer); + else for (i = 3; i < partitions; i++) print_buffer(buffers[i]); } @@ -1295,20 +1570,20 @@ void move_begin(int i) if (warn_geometry()) return; - if (!p->sys_ind || !p->nr_sects || p->sys_ind == EXTENDED) { + if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) { printf("Partition %d has no data area\n", i + 1); return; } - first = rounded(calculate(p->head, p->sector, p->cyl), p->start_sect + - offsets[i]); + first = rounded(calculate(p->head, p->sector, p->cyl), + get_start_sect(p) + offsets[i]); new = read_int(first, first, - p->start_sect + p->nr_sects + offsets[i] - 1, + get_start_sect(p) + get_nr_sects(p) + offsets[i] - 1, lower, "New beginning of data") - offsets[i]; - if (new != p->nr_sects) { - first = p->nr_sects + p->start_sect - new; - p->nr_sects = first; - p->start_sect = new; + if (new != get_nr_sects(p)) { + first = get_nr_sects(p) + get_start_sect(p) - new; + set_nr_sects(p, first); + set_start_sect(p, new); changed[i] = 1; } } @@ -1318,56 +1593,138 @@ void xselect(void) while(1) { putchar('\n'); switch (tolower(read_char("Expert command (m for help): "))) { - case 'b': move_begin(get_partition(0, partitions)); - break; - case 'c': cylinders = read_int(1, cylinders, 65535, - deflt, "Number of cylinders"); - warn_cylinders(); - break; - case 'd': print_raw(); - break; - case 'e': x_list_table(1); - break; - case 'h': heads = read_int(1, heads, 256, deflt, - "Number of heads"); - update_units(); - break; - case 'p': x_list_table(0); - break; - case 'q': close(fd); - exit(0); - case 'r': return; - case 's': sectors = read_int(1, sectors, 63, deflt, - "Number of sectors"); - if (dos_compatible_flag) { - sector_offset = sectors; - fprintf(stderr, "Warning: setting " - "sector offset for DOS " - "compatiblity\n"); - } - update_units(); - break; - case 'v': verify(); - break; - case 'w': write_table(); - default: xmenu(); +#if defined(sparc) + case 'a': + if (sun_label) + sun_set_alt_cyl(); + break; +#endif + case 'b': + if (!sun_label) + move_begin(get_partition(0, partitions)); + break; + case 'c': + cylinders = read_int(1, cylinders, 65535, + deflt, "Number of cylinders"); +#if defined(sparc) + if (sun_label) + sun_set_ncyl(cylinders); +#endif + warn_cylinders(); + break; + case 'd': + print_raw(); + break; + case 'e': + if (!sun_label) + x_list_table(1); +#if defined(sparc) + else + sun_set_xcyl(); +#endif + break; + case 'h': + heads = read_int(1, heads, 256, deflt, + "Number of heads"); + update_units(); + break; +#if defined(sparc) + case 'i': + if (sun_label) + sun_set_ilfact(); + break; + case 'o': + if (sun_label) + sun_set_rspeed(); + break; +#endif + case 'p': +#if defined(sparc) + if (sun_label) + list_table(1); + else +#endif + x_list_table(0); + break; + case 'q': + close(fd); + exit(0); + case 'r': + return; + case 's': + sectors = read_int(1, sectors, 63, deflt, + "Number of sectors"); + if (dos_compatible_flag) { + sector_offset = sectors; + fprintf(stderr, "Warning: setting " + "sector offset for DOS " + "compatiblity\n"); + } + update_units(); + break; + case 'v': + verify(); + break; + case 'w': + write_table(); /* does not return */ + break; +#if defined(sparc) + case 'y': + if (sun_label) + sun_set_pcylcount(); + break; +#endif + default: + xmenu(); } } } -void try(char *device) +int +is_ide_cdrom(char *device) { + /* No device was given explicitly, and we are trying some + likely things. But opening /dev/hdc may produce errors like + "hdc: tray open or drive not ready" + if it happens to be a CD-ROM drive. It even happens that + the process hangs on the attempt to read a music CD. + So try to be careful. This only works since 2.1.73. */ + + FILE *procf; + char buf[100]; + struct stat statbuf; + + sprintf(buf, "/proc/ide/%s/media", device+5); + procf = fopen(buf, "r"); + if (procf != NULL && fgets(buf, sizeof(buf), procf)) + return !strncmp(buf, "cdrom", 5); + + /* Now when this proc file does not exist, skip the + device when it is read-only. */ + if (stat(device, &statbuf) == 0) + return (statbuf.st_mode & 0222) == 0; + + return 0; +} + +void try(char *device, int user_specified) { disk_device = device; if (!setjmp(listingbuf)) { + if (!user_specified) + if (is_ide_cdrom(device)) + return; if ((fd = open(disk_device, type_open)) >= 0) { - if (get_boot()) { - close(fd); - list_table(); - if (partitions > 4) - delete_partition(ext_index); + if (get_boot(try_only) < 0) { + if (btrydev(device) < 0) + fprintf(stderr, + "Disk doesn't contain a valid " + "partition table\n"); + close(fd); } else { - btrydev(device); - close(fd); + close(fd); + list_table(0); + if (!sun_label && partitions > 4) + delete_partition(ext_index); } } else { /* Ignore other errors, since we try IDE @@ -1375,106 +1732,209 @@ void try(char *device) installed on the system. */ if(errno == EACCES) { fprintf(stderr, "Cannot open %s\n", device); - exit(1); + return; } } } } +void +dummy(int *kk) {} + void main(int argc, char **argv) { - if (argc > 3) - fatal(usage); - if (argc > 1 && *argv[1] == '-') { - switch (*(argv[1] + 1)) { - case 'v': - printf("fdisk v" VERSION "\n"); - exit(0); - case 'l': - listing = 1; - type_open = O_RDONLY; - try("/dev/hda"); - try("/dev/hdb"); - try("/dev/hdc"); - try("/dev/hdd"); - try("/dev/sda"); - try("/dev/sdb"); - try("/dev/sdc"); - try("/dev/sdd"); - try("/dev/sde"); - try("/dev/sdf"); - try("/dev/sdg"); - try("/dev/sdh"); - exit(0); - case 's': { - int i; - if (argc < 3) - fatal(usage); - if (!(i = atoi(argv[2] + 8))) - fatal(usage); - disk_device = (char *) malloc(9); - strncpy(disk_device, argv[2], 8); - if ((fd = open(disk_device, O_RDWR)) >= 0) { - close(fd); - get_boot(); - if (i > partitions) exit(1); - if (part_table[--i]->sys_ind > 10) - printf("%d\n", - part_table[i]->nr_sects / 2); - else exit(1); - exit(0); - } + int i, j, s, c; + int optl = 0, opts = 0; + char *part; + + + /* + * Calls: + * fdisk -v + * fdisk -l [-b] [-u] [device] ... + * fdisk -s [partition] ... + * fdisk [-b] [-u] [device] + */ + while ((c = getopt(argc, argv, "blsuv")) != EOF) { + switch (c) { + case 'b': + show_begin = 1; + break; + case 'l': + optl = 1; + break; + case 's': + opts = 1; + break; + case 'u': + unit_flag = 0; + break; + case 'v': + printf("fdisk v" VERSION "\n"); + exit(0); + default: + fatal(usage); + } } - default: + + if (optl) { + listing = 1; + nowarn = 1; + type_open = O_RDONLY; + if (argc > optind) { + int k; + /* avoid gcc warning: + variable `k' might be clobbered by `longjmp' */ + dummy(&k); + for(k=optind; k<argc; k++) + try(argv[k], 1); + } else { + try("/dev/hda", 0); + try("/dev/hdb", 0); + try("/dev/hdc", 0); /* often a CDROM */ + try("/dev/hdd", 0); + try("/dev/sda", 0); + try("/dev/sdb", 0); + try("/dev/sdc", 0); + try("/dev/sdd", 0); + try("/dev/sde", 0); + try("/dev/sdf", 0); + try("/dev/sdg", 0); + try("/dev/sdh", 0); + try("/dev/eda", 0); + try("/dev/edb", 0); + try("/dev/edc", 0); + try("/dev/edd", 0); + } + exit(0); + } + + if (opts) { + /* Silly assumptions here about device naming */ + nowarn = 1; + disk_device = (char *) malloc(9); + type_open = O_RDONLY; + + opts = argc - optind; + if (opts <= 0) + fatal(usage); + + for (j = optind; j < argc; j++) { + part = argv[j]; + if (strlen(part) < 9) + fatal(usage); + if (!(i = atoi(part + 8))) fatal(usage); + i--; /* count from 0 */ + strncpy(disk_device, part, 8); + disk_device[8] = 0; + if ((fd = open(disk_device, type_open)) < 0) + fatal(unable_to_open); + close(fd); + if (get_boot(require) < 0) + exit(1); + if (i >= partitions) + exit(1); +#if defined(sparc) + if (!sun_label) { + int id = sunlabel->infos[i].id; + + if (!(id > 1 && id != WHOLE_DISK)) + exit(1); + s = get_num_sectors(sunlabel->partitions[i]); + } else +#endif + s = get_nr_sects(part_table[i]); + if (opts == 1) + printf("%d\n", s/2); + else + printf("%s: %d\n", argv[j], s/2); } + exit(0); } - if (argc > 1) - disk_device = argv[argc - 1]; - else if ((fd = open(DEFAULT_DEVICE, O_RDWR)) < 0) - disk_device = ALTERNATE_DEVICE; - else close(fd); - if (argc == 1) + if (argc-optind == 1) + disk_device = argv[optind]; + else if (argc-optind != 0) + fatal(usage); + else { + if ((fd = open(DEFAULT_DEVICE, O_RDWR)) < 0) + disk_device = ALTERNATE_DEVICE; + else close(fd); printf("Using %s as default device!\n", disk_device); - get_boot(); + } + get_boot(fdisk); while (1) { putchar('\n'); switch (tolower(read_char("Command (m for help): "))) { - case 'a': toggle_active(get_partition(1, partitions)); - break; -/* There should be a define which allows to turn off disklabel support so as - not to make fdisk larger than necessary on installation boot disks. -*/ -#if 1 /* #ifndef NO_DISKLABEL_SUPPORT */ - case 'b': bselect(); /* bf */ - break; + case 'a': +#if defined(sparc) + if (sun_label) + toggle_sunflags(get_partition(1, partitions), + 0x01); + else +#endif + toggle_active(get_partition(1, partitions)); + break; + case 'b': + bselect(); + break; + case 'c': +#if defined(sparc) + if (sun_label) + toggle_sunflags(get_partition(1, partitions), + 0x10); + else #endif - case 'c': toggle_dos(); - break; - case 'd': delete_partition( - get_partition(1, partitions)); - break; - case 'l': list_types(sys_types, nsys_types); /* bf */ - break; - case 'n': new_partition(); - break; - case 'p': list_table(); - break; - case 'q': close(fd); - exit(0); - case 't': change_sysid(); - break; - case 'u': change_units(); - break; - case 'v': verify(); - break; - case 'w': write_table(); - case 'x': xselect(); - break; - default: menu(); + break; + case 'd': + delete_partition( + get_partition(1, partitions)); + break; + case 'l': +#if defined(sparc) + if (sun_label) + list_types(sun_sys_types); + else +#endif + list_types(sys_types); + break; + case 'n': + new_partition(); + break; + case 'o': + create_doslabel(); + break; + case 'p': + list_table(0); + break; + case 'q': + close(fd); + exit(0); +#if defined(sparc) + case 's': + create_sunlabel(); + break; +#endif + case 't': + change_sysid(); + break; + case 'u': + change_units(); + break; + case 'v': + verify(); + break; + case 'w': + write_table(); /* does not return */ + break; + case 'x': + xselect(); + break; + default: menu(); } } } + diff --git a/disk-utils/fdisk.h b/disk-utils/fdisk.h index 89510031a..11f529d48 100644 --- a/disk-utils/fdisk.h +++ b/disk-utils/fdisk.h @@ -3,7 +3,10 @@ */ #define SECTOR_SIZE 512 -#define NETBSD_PARTITION 0xa5 +#define MAXIMUM_PARTS 60 + +#define SIZE(a) (sizeof(a)/sizeof((a)[0])) + #define cround(n) (((n) + display_factor * unit_flag) / display_factor) #if defined(__GNUC__) || defined(HAS_LONG_LONG) @@ -16,11 +19,26 @@ extern ext2_loff_t ext2_llseek(unsigned int fd, ext2_loff_t offset, unsigned int origin); +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 failure {usage, unable_to_open, unable_to_read, unable_to_seek, unable_to_write, out_of_memory}; enum offset {ignore, lower, deflt, upper}; +enum action {fdisk, require, try_only, create_empty}; + struct systypes { unsigned char index; char *name; @@ -35,14 +53,20 @@ extern uint unit_flag, display_factor; extern struct partition *part_table[]; extern void fatal(enum failure why); +extern int get_boot(enum action what); extern int get_partition(int warn, int max); -extern void list_types(struct systypes *sys, int size); +extern void list_types(struct systypes *sys); extern int read_line (void); extern char read_char(char *mesg); -extern int read_hex(struct systypes *sys, int size); +extern int read_hex(struct systypes *sys); uint read_int(uint low, uint dflt, uint high, enum offset base, char *mesg); extern char *const str_units(void); +extern unsigned int get_start_sect(struct partition *p); +extern unsigned int get_nr_sects(struct partition *p); + /* prototypes for fdisklabel.c */ extern void bselect(void); -extern void btrydev (char * dev); +extern int btrydev (char * dev); + +/* prototypes for fdisksunlabel.c */ diff --git a/disk-utils/fdisklabel.c b/disk-utils/fdisklabel.c index a6b5ecc4d..d98d49d0d 100644 --- a/disk-utils/fdisklabel.c +++ b/disk-utils/fdisklabel.c @@ -47,11 +47,10 @@ #include <sys/ioctl.h> #include <sys/param.h> -#include <linux/genhd.h> -#include <linux/hdreg.h> -#include <linux/fs.h> +#include <linux/hdreg.h> /* for HDIO_GETGEO */ #include "fdisk.h" +#define NETBSD_PARTITION 0xa5 #define DKTYPENAMES #include "fdisklabel.h" @@ -71,7 +70,7 @@ static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int p static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d); static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d); static void sync_disks (void); -#if defined (i386) +#if defined (i386) || defined (sparc) static int xbsd_translate_fstype (int linux_type); static void xbsd_link_part (void); #endif @@ -81,17 +80,18 @@ void alpha_bootblock_checksum (char *boot); static struct xbsd_disklabel xbsd_dlabel; static char buffer[BSD_BBSIZE]; -#if defined (i386) +#if defined (i386) || defined (sparc) static struct partition *xbsd_part; static int xbsd_part_index; #endif -void +int btrydev (char * dev) { if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0) - return; + return -1; printf("\nBSD label for device: %s\n", dev); xbsd_print_disklabel (0); + return 0; } void @@ -106,13 +106,13 @@ bmenu (void) " n add a new BSD partition\n" " p print BSD partition table\n" " q quit without saving changes\n" -#if defined (i386) +#if defined (i386) || defined (sparc) " r return to main menu\n" #endif " s show complete disklabel\n" " t change a partition's filesystem id\n" " w write disklabel to disk\n" -#if defined (i386) +#if defined (i386) || defined (sparc) " x link BSD partition to non-BSD partition" #endif ); @@ -121,22 +121,23 @@ bmenu (void) void bselect (void) { -#if defined (i386) - int t; +#if defined (i386) || defined (sparc) + int t, ss; for (t=0; t<4; t++) if (part_table[t] -> sys_ind == NETBSD_PARTITION) { xbsd_part = part_table[t]; xbsd_part_index = t; - if (xbsd_part -> start_sect == 0) + ss = get_start_sect(xbsd_part); + if (ss == 0) { fprintf (stderr, "Partition %s%d has invalid starting sector 0.\n", disk_device, t+1); return; } printf ("Reading disklabel of %s%d at sector %d.\n", - disk_device, t+1, xbsd_part -> start_sect + BSD_LABELSECTOR); + disk_device, t+1, ss + BSD_LABELSECTOR); if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0) if (xbsd_create_disklabel () == 0) return; @@ -192,7 +193,7 @@ bselect (void) case 'w': xbsd_write_disklabel (); break; -#if defined (i386) +#if defined (i386) || defined (sparc) case 'r': return; case 'x': @@ -230,9 +231,9 @@ xbsd_new_part (void) if (!xbsd_check_new_partition (&i)) return; -#if defined (i386) - begin = xbsd_part -> start_sect; - end = begin + xbsd_part -> nr_sects - 1; +#if defined (i386) || defined (sparc) + begin = get_start_sect(xbsd_part); + end = begin + get_nr_sects(xbsd_part) - 1; #elif defined (__alpha__) begin = 0; end = xbsd_dlabel.d_secperunit; @@ -264,7 +265,7 @@ xbsd_print_disklabel (int show_all) if (show_all) { -#if defined (i386) +#if defined (i386) || defined (sparc) fprintf(f, "# %s%d:\n", disk_device, xbsd_part_index+1); #elif defined (__alpha__) fprintf(f, "# %s:\n", disk_device); @@ -361,7 +362,7 @@ xbsd_print_disklabel (int show_all) static void xbsd_write_disklabel (void) { -#if defined (i386) +#if defined (i386) || defined (sparc) printf ("Writing disklabel to %s%d.\n", disk_device, xbsd_part_index+1); xbsd_writelabel (xbsd_part, &xbsd_dlabel); #elif defined (__alpha__) @@ -375,7 +376,7 @@ xbsd_create_disklabel (void) { char c; -#if defined (i386) +#if defined (i386) || defined (sparc) fprintf (stderr, "%s%d contains no disklabel.\n", disk_device, xbsd_part_index+1); #elif defined (__alpha__) @@ -385,7 +386,7 @@ xbsd_create_disklabel (void) while (1) if ((c = tolower (read_char ("Do you want to create a disklabel? (y/n) "))) == 'y') { -#if defined (i386) +#if defined (i386) || defined (sparc) if (xbsd_initlabel (xbsd_part, &xbsd_dlabel, xbsd_part_index) == 1) #elif defined (__alpha__) if (xbsd_initlabel (NULL, &xbsd_dlabel, 0) == 1) @@ -516,8 +517,8 @@ xbsd_write_bootstrap (void) bcopy (&dl, d, sizeof (struct xbsd_disklabel)); -#if defined (i386) - sector = xbsd_part -> start_sect; +#if defined (i386) || defined (sparc) + sector = get_start_sect(xbsd_part); #elif defined (__alpha__) sector = 0; alpha_bootblock_checksum (buffer); @@ -528,7 +529,7 @@ xbsd_write_bootstrap (void) if (BSD_BBSIZE != write (fd, buffer, BSD_BBSIZE)) fatal (unable_to_write); -#if defined (i386) +#if defined (i386) || defined (sparc) printf ("Bootstrap installed on %s%d.\n", disk_device, xbsd_part_index+1); #elif defined (__alpha__) printf ("Bootstrap installed on %s.\n", disk_device); @@ -543,7 +544,7 @@ xbsd_change_fstype (void) int i; i = xbsd_get_part_index (xbsd_dlabel.d_npartitions); - xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes, BSD_FSMAXTYPES); + xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes); } static int @@ -592,7 +593,7 @@ xbsd_check_new_partition (int *i) static void xbsd_list_types (void) { - list_types (xbsd_fstypes, BSD_FSMAXTYPES); + list_types (xbsd_fstypes); } static u_short @@ -632,7 +633,7 @@ xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex; #endif -#if defined (i386) +#if defined (i386) || defined (sparc) d -> d_flags = BSD_D_DOSPART; #else d -> d_flags = 0; @@ -655,11 +656,11 @@ xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) d -> d_bbsize = BSD_BBSIZE; d -> d_sbsize = BSD_SBSIZE; -#if defined (i386) +#if defined (i386) || defined (sparc) d -> d_npartitions = 4; pp = &d -> d_partitions[2]; /* Partition C should be the NetBSD partition */ - pp -> p_offset = p -> start_sect; - pp -> p_size = p -> nr_sects; + pp -> p_offset = get_start_sect(p); + pp -> p_size = get_nr_sects(p); pp -> p_fstype = BSD_FS_UNUSED; pp = &d -> d_partitions[3]; /* Partition D should be the whole disk */ pp -> p_offset = 0; @@ -681,8 +682,8 @@ xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d) { int t, sector; -#if defined (i386) - sector = p -> start_sect; +#if defined (i386) || defined (sparc) + sector = (p ? get_start_sect(p) : 0); #elif defined (__alpha__) sector = 0; #endif @@ -715,8 +716,8 @@ xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d) { int sector; -#if defined (i386) - sector = p -> start_sect + BSD_LABELSECTOR; +#if defined (i386) || defined (sparc) + sector = get_start_sect(p) + BSD_LABELSECTOR; #elif defined (__alpha__) sector = BSD_LABELSECTOR; #endif @@ -756,7 +757,7 @@ sync_disks (void) sleep (4); } -#if defined (i386) +#if defined (i386) || defined (sparc) static int xbsd_translate_fstype (int linux_type) { @@ -786,8 +787,8 @@ xbsd_link_part (void) if (!xbsd_check_new_partition (&i)) return; - xbsd_dlabel.d_partitions[i].p_size = part_table[k] -> nr_sects; - xbsd_dlabel.d_partitions[i].p_offset = part_table[k] -> start_sect; + xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(part_table[k]); + xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(part_table[k]); xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype (part_table[k] -> sys_ind); } @@ -795,6 +796,10 @@ xbsd_link_part (void) #if defined (__alpha__) +#if 0 +typedef unsigned long long u_int64_t; +#endif + void alpha_bootblock_checksum (char *boot) { diff --git a/disk-utils/fdisklabel.h b/disk-utils/fdisklabel.h index d007b34b2..06435f4d1 100644 --- a/disk-utils/fdisklabel.h +++ b/disk-utils/fdisklabel.h @@ -31,6 +31,8 @@ * SUCH DAMAGE. */ +#include <linux/types.h> /* for __u32 etc */ + #ifndef BSD_DISKMAGIC /* perhaps from <linux/genhd.h> */ #define BSD_DISKMAGIC ((__u32) 0x82564557) #endif @@ -41,20 +43,19 @@ #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec" -#if defined (i386) +#if defined (i386) || defined (sparc) #define BSD_LABELSECTOR 1 #define BSD_LABELOFFSET 0 -#define BSD_BBSIZE 8192 /* size of boot area, with label */ -#define BSD_SBSIZE 8192 /* max size of fs superblock */ #elif defined (__alpha__) #define BSD_LABELSECTOR 0 #define BSD_LABELOFFSET 64 -#define BSD_BBSIZE 8192 -#define BSD_SBSIZE 8192 #else #error unknown architecture #endif +#define BSD_BBSIZE 8192 /* size of boot area, with label */ +#define BSD_SBSIZE 8192 /* max size of fs superblock */ + struct xbsd_disklabel { __u32 d_magic; /* the magic number */ __s16 d_type; /* drive type */ @@ -210,10 +211,11 @@ static struct systypes xbsd_fstypes[] = { {BSD_FS_ISO9660,"ISO-9660"}, {BSD_FS_BOOT, "boot"}, {BSD_FS_ADOS, "ADOS"}, - {BSD_FS_HFS, "HFS"} + {BSD_FS_HFS, "HFS"}, + { 0, NULL } }; +#define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1) -#define BSD_FSMAXTYPES (sizeof(xbsd_fstypes) / sizeof(struct systypes)) #endif /* diff --git a/disk-utils/fdisksunlabel.c b/disk-utils/fdisksunlabel.c new file mode 100644 index 000000000..a5a87b8d4 --- /dev/null +++ b/disk-utils/fdisksunlabel.c @@ -0,0 +1,661 @@ +/* + * fdisksunlabel.c + * + * I think this is mostly, or entirely, due to + * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996 + * + * Merged with fdisk for other architectures, aeb, June 1998. + */ +#if defined (sparc) + +#include <stdio.h> /* stderr */ +#include <stdlib.h> /* uint */ +#include <string.h> /* strstr */ +#include <unistd.h> /* write */ +#include <sys/ioctl.h> /* ioctl */ +#include <sys/stat.h> /* stat */ + +#include <endian.h> +#include <scsi/scsi.h> +#include <linux/major.h> /* FLOPPY_MAJOR */ +#include <linux/hdreg.h> /* HDIO_GETGEO */ + +#include "fdisk.h" +#include "fdisksunlabel.h" + +int other_endian = 0; +int scsi_disk = 0; +int floppy = 0; + +#define LINUX_SWAP 0x82 +#define LINUX_NATIVE 0x83 + +struct systypes sun_sys_types[] = { + {0, "Empty"}, + {1, "Boot"}, + {2, "SunOS root"}, + {SUNOS_SWAP, "SunOS swap"}, + {4, "SunOS usr"}, + {WHOLE_DISK, "Whole disk"}, + {6, "SunOS stand"}, + {7, "SunOS var"}, + {8, "SunOS home"}, + {LINUX_SWAP, "Linux swap"}, + {LINUX_NATIVE, "Linux native"}, + { 0, NULL } +}; + +inline unsigned short __swap16(unsigned short x) { + return (((__u16)(x) & 0xFF) << 8) | (((__u16)(x) & 0xFF00) >> 8); +} +inline __u32 __swap32(__u32 x) { + return (((__u32)(x) & 0xFF) << 24) | (((__u32)(x) & 0xFF00) << 8) | (((__u32)(x) & 0xFF0000) >> 8) | (((__u32)(x) & 0xFF000000) >> 24); +} + +int +get_num_sectors(struct sun_partition p) { + return SSWAP32(p.num_sectors); +} + +void guess_device_type(int fd) { + struct stat bootstat; + + if (fstat (fd, &bootstat) < 0) { + scsi_disk = 0; + floppy = 0; + } else if (S_ISBLK(bootstat.st_mode) + && ((bootstat.st_rdev >> 8) == IDE0_MAJOR || + (bootstat.st_rdev >> 8) == IDE1_MAJOR)) { + scsi_disk = 0; + floppy = 0; + } else if (S_ISBLK(bootstat.st_mode) + && (bootstat.st_rdev >> 8) == FLOPPY_MAJOR) { + scsi_disk = 0; + floppy = 1; + } else { + scsi_disk = 1; + floppy = 0; + } +} + +void set_sun_partition(int i, uint start, uint stop, int sysid) +{ + sunlabel->infos[i].id = sysid; + sunlabel->partitions[i].start_cylinder = + SSWAP32(start / (heads * sectors)); + sunlabel->partitions[i].num_sectors = + SSWAP32(stop - start); + changed[i] = 1; +} + +int check_sun_label(void) +{ + unsigned short *ush; + int csum; + + if (sunlabel->magic != SUN_LABEL_MAGIC && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) { + sun_label = 0; + other_endian = 0; + return 0; + } + other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED); + ush = ((unsigned short *) (sunlabel + 1)) - 1; + for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--; + if (csum) { + fprintf(stderr, "Detected sun disklabel with wrong checksum.\n" + "Probably you'll have to set all the values,\n" + "e.g. heads, sectors, cylinders and partitions\n" + "or force a fresh label (s command in main menu)\n"); + } else { + heads = SSWAP16(sunlabel->ntrks); + cylinders = SSWAP16(sunlabel->ncyl); + sectors = SSWAP16(sunlabel->nsect); + } + update_units(); + sun_label = 1; + partitions = 8; + return 1; +} + +struct sun_predefined_drives { + char *vendor; + char *model; + unsigned short sparecyl; + unsigned short ncyl; + unsigned short nacyl; + unsigned short pcylcount; + unsigned short ntrks; + unsigned short nsect; + unsigned short rspeed; +} sun_drives[] = { +{"Quantum","ProDrive 80S",1,832,2,834,6,34,3662}, +{"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662}, +{"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600}, +{"","SUN0104",1,974,2,1019,6,35,3662}, +{"","SUN0207",4,1254,2,1272,9,36,3600}, +{"","SUN0327",3,1545,2,1549,9,46,3600}, +{"","SUN0340",0,1538,2,1544,6,72,4200}, +{"","SUN0424",2,1151,2,2500,9,80,4400}, +{"","SUN0535",0,1866,2,2500,7,80,5400}, +{"","SUN0669",5,1614,2,1632,15,54,3600}, +{"","SUN1.0G",5,1703,2,1931,15,80,3597}, +{"","SUN1.05",0,2036,2,2038,14,72,5400}, +{"","SUN1.3G",6,1965,2,3500,17,80,5400}, +{"","SUN2.1G",0,2733,2,3500,19,80,5400}, +{"IOMEGA","Jaz",0,1019,2,1021,64,32,5394}, +}; + +void create_sunlabel(void) +{ + struct hd_geometry geometry; + unsigned int ndiv; + int i; + unsigned char c; + struct sun_predefined_drives *p = NULL; + + fprintf(stderr, "Building a new sun disklabel. Changes will remain in memory only,\n" + "until you decide to write them. After that, of course, the previous\n" + "content won't be recoverable.\n\n"); +#if BYTE_ORDER == LITTLE_ENDIAN + other_endian = 1; +#else + other_endian = 0; +#endif + memset(buffer, 0, SECTOR_SIZE); + sunlabel->magic = SSWAP16(SUN_LABEL_MAGIC); + if (!floppy) { + puts("Drive type\n" + " ? auto configure\n" + " 0 custom (with hardware detected defaults)"); + for (i = 0; i < SIZE(sun_drives); i++) { + printf(" %c %s%s%s\n", + i + 'a', sun_drives[i].vendor, + (*sun_drives[i].vendor) ? " " : "", + sun_drives[i].model); + } + for (;;) { + c = read_char("Select type (? for auto, 0 for custom): "); + if (c >= 'a' && c < 'a' + SIZE(sun_drives)) { + p = sun_drives + c - 'a'; + break; + } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) { + p = sun_drives + c - 'A'; + break; + } else if (c == '0') + break; + else if (c == '?' && scsi_disk) { + unsigned int id[2]; + char buffer[2048]; + char buffer2[2048]; + FILE *pfd; + char *vendor; + char *model; + char *q; + + if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) { + sprintf(buffer, "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n", +#if 0 + ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33, +#else + /* This is very wrong (works only if you have one HBA), but I haven't find a way how to get hostno from the current kernel */ + 0, +#endif + (id[0]>>16)&0xff, + id[0]&0xff, + (id[0]>>8)&0xff); + pfd = fopen("/proc/scsi/scsi","r"); + if (pfd) { + while (fgets(buffer2,2048,pfd)) { + if (!strcmp(buffer, buffer2)) { + if (fgets(buffer2,2048,pfd)) { + q = strstr(buffer2,"Vendor: "); + if (q) { + q += 8; + vendor = q; + q = strstr(q," Model: "); + if (q) { + *q = 0; + q += 8; + model = q; + q = strstr(q," Rev: "); + if (q) { + *q = 0; + for (i = 0; i < SIZE(sun_drives); i++) { + if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor)) + continue; + if (!strstr(model, sun_drives[i].model)) + continue; + printf("Autoconfigure found a %s%s%s\n",sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model); + p = sun_drives + i; + break; + } + } + } + } + } + break; + } + } + fclose(pfd); + } + } + if (!p) + printf("Autoconfigure failed.\n"); + else + break; + } + } + } + if (!p || floppy) { +#ifdef HDIO_REQ + if (!ioctl(fd, HDIO_REQ, &geometry)) { +#else + if (!ioctl(fd, HDIO_GETGEO, &geometry)) { +#endif + heads = geometry.heads; + sectors = geometry.sectors; + cylinders = geometry.cylinders; + } else { + heads = 0; + sectors = 0; + cylinders = 0; + } + if (floppy) { + sunlabel->nacyl = 0; + sunlabel->pcylcount = SSWAP16(cylinders); + sunlabel->rspeed = SSWAP16(300); + sunlabel->ilfact = SSWAP16(1); + sunlabel->sparecyl = 0; + } else { + if (heads) + heads = read_int(1,heads,1024,deflt,"Heads"); + else + heads = read_int(1,1,1024,ignore,"Heads"); + if (sectors) + sectors = read_int(1,sectors,1024,deflt,"Sectors/track"); + else + sectors = read_int(1,1,1024,ignore,"Sectors/track"); + if (cylinders) + cylinders = read_int(1,cylinders-2,65535,deflt,"Cylinders"); + else + cylinders = read_int(1,1,65535,ignore,"Cylinders"); + sunlabel->nacyl = SSWAP16(read_int(0,2,65535,deflt,"Alternate cylinders")); + sunlabel->pcylcount = SSWAP16(read_int(0,cylinders + SSWAP16(sunlabel->nacyl),65535,deflt,"Physical cylinders")); + sunlabel->rspeed = SSWAP16(read_int(1,5400,100000,deflt,"Rotation speed (rpm)")); + sunlabel->ilfact = SSWAP16(read_int(1,1,32,deflt,"Interleave factor")); + sunlabel->sparecyl = SSWAP16(read_int(0,0,sectors,deflt,"Extra sectors per cylinder")); + } + } else { + sunlabel->sparecyl = SSWAP16(p->sparecyl); + sunlabel->ncyl = SSWAP16(p->ncyl); + sunlabel->nacyl = SSWAP16(p->nacyl); + sunlabel->pcylcount = SSWAP16(p->pcylcount); + sunlabel->ntrks = SSWAP16(p->ntrks); + sunlabel->nsect = SSWAP16(p->nsect); + sunlabel->rspeed = SSWAP16(p->rspeed); + cylinders = p->ncyl; + heads = p->ntrks; + sectors = p->nsect; + puts("You may change all the disk params from the x menu"); + } + sprintf(buffer, "%s%s%s cyl %d alt %d hd %d sec %d", + p ? p->vendor : "", (p && *p->vendor) ? " " : "", p ? p->model : (floppy ? "3,5\" floppy" : "Linux custom"), + cylinders, SSWAP16(sunlabel->nacyl), heads, sectors); + sunlabel->ntrks = SSWAP16(heads); + sunlabel->nsect = SSWAP16(sectors); + sunlabel->ncyl = SSWAP16(cylinders); + if (floppy) + set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE); + else { + if (cylinders * heads * sectors >= 150 * 2048) { + ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */ + } else + ndiv = cylinders * 2 / 3; + set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE); + set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP); + sunlabel->infos[1].flags |= 0x01; /* Not mountable */ + } + set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK); + { + unsigned short *ush = (unsigned short *)sunlabel; + unsigned short csum = 0; + while(ush < (unsigned short *)(&sunlabel->csum)) + csum ^= *ush++; + sunlabel->csum = csum; + } + for (i = 1; i < MAXIMUM_PARTS; i++) + changed[i] = 0; + changed[0] = 1; + get_boot(create_empty); +} + +void toggle_sunflags(int i, unsigned char mask) +{ + if (sunlabel->infos[i].flags & mask) + sunlabel->infos[i].flags &= ~mask; + else sunlabel->infos[i].flags |= mask; + changed[i] = 1; +} + +void fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) +{ + int i, continuous = 1; + *start = 0; *stop = cylinders * heads * sectors; + for (i = 0; i < partitions; i++) { + if (sunlabel->partitions[i].num_sectors && sunlabel->infos[i].id && sunlabel->infos[i].id != WHOLE_DISK) { + starts[i] = SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors; + lens[i] = SSWAP32(sunlabel->partitions[i].num_sectors); + if (continuous) { + if (starts[i] == *start) + *start += lens[i]; + else if (starts[i] + lens[i] >= *stop) + *stop = starts[i]; + else + continuous = 0; /* There will be probably more gaps than one, so lets check afterwards */ + } + } else { + starts[i] = 0; + lens[i] = 0; + } + } +} + +static uint *verify_sun_starts; +int verify_sun_cmp(int *a, int *b) +{ + if (*a == -1) return 1; + if (*b == -1) return -1; + if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1; + return -1; +} + +void verify_sun(void) +{ + uint starts[8], lens[8], start, stop; + int i,j,k,starto,endo; + int array[8]; + + verify_sun_starts = starts; + fetch_sun(starts,lens,&start,&stop); + for (k = 0; k < 7; k++) { + for (i = 0; i < 8; i++) { + if (k && (lens[i] % (heads * sectors))) { + printf("Partition %d doesn't end on cylinder boundary\n", i+1); + } + if (lens[i]) { + for (j = 0; j < i; j++) + if (lens[j]) { + if (starts[j] == starts[i]+lens[i]) { + starts[j] = starts[i]; lens[j] += lens[i]; + lens[i] = 0; + } else if (starts[i] == starts[j]+lens[j]){ + lens[j] += lens[i]; + lens[i] = 0; + } else if (!k) { + if (starts[i] < starts[j]+lens[j] && + starts[j] < starts[i]+lens[i]) { + starto = starts[i]; + if (starts[j] > starto) + starto = starts[j]; + endo = starts[i]+lens[i]; + if (starts[j]+lens[j] < endo) + endo = starts[j]+lens[j]; + printf("Partition %d overlaps with others in " + "sectors %d-%d\n", i+1, starto, endo); + } + } + } + } + } + } + for (i = 0; i < 8; i++) { + if (lens[i]) + array[i] = i; + else + array[i] = -1; + } + qsort(array,SIZE(array),sizeof(array[0]), + (int (*)(const void *,const void *)) verify_sun_cmp); + if (array[0] == -1) { + printf("No partitions defined\n"); + return; + } + stop = cylinders * heads * sectors; + if (starts[array[0]]) + printf("Unused gap - sectors 0-%d\n",starts[array[0]]); + for (i = 0; i < 7 && array[i+1] != -1; i++) { + printf("Unused gap - sectors %d-%d\n",starts[array[i]]+lens[array[i]],starts[array[i+1]]); + } + start = starts[array[i]]+lens[array[i]]; + if (start < stop) + printf("Unused gap - sectors %d-%d\n",start,stop); +} + +void add_sun_partition(int n, int sys) +{ + uint start, stop, stop2; + uint starts[8], lens[8]; + int whole_disk = 0; + + char mesg[48]; + int i, first, last; + + if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) { + printf("Partition %d is already defined. Delete " + "it before re-adding it.\n", n + 1); + return; + } + + fetch_sun(starts,lens,&start,&stop); + if (stop <= start) { + if (n == 2) + whole_disk = 1; + else { + printf("Other partitions already cover the whole disk.\nDelete " + "some/shrink them before retry.\n"); + return; + } + } + sprintf(mesg, "First %s", str_units()); + for (;;) { + if (whole_disk) + first = read_int(0, 0, 0, deflt, mesg); + else + first = read_int(scround(start), scround(start), scround(stop), + ignore, mesg); + if (unit_flag) + first *= display_factor; + else + first = (first + heads * sectors - 1) / (heads * sectors); /* Starting sector has to be properly aligned */ + if (n == 2 && first != 0) printf ("It is highly recommended that third partition covers the whole disk\n" + "and is of type `Whole disk'\n"); + for (i = 0; i < partitions; i++) + if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first) + break; + if (i < partitions && !whole_disk) { + if (n == 2 && !first) { + whole_disk = 1; + break; + } + printf("Sector %d is already allocated\n", first); + } else + break; + } + stop = cylinders * heads * sectors; + stop2 = stop; + for (i = 0; i < partitions; i++) { + if (starts[i] > first && starts[i] < stop) + stop = starts[i]; + } + sprintf(mesg, "Last %s or +size or +sizeM or +sizeK", str_units()); + if (whole_disk) + last = read_int(scround(stop2), scround(stop2), scround(stop2), + deflt, mesg); + else if (n == 2 && !first) + last = read_int(scround(first), scround(stop2), scround(stop2), + upper, mesg); + else + last = read_int(scround(first), scround(stop), scround(stop), + lower, mesg); + if (unit_flag) + last *= display_factor; + if (n == 2 && !first) { + if (last >= stop2) { + whole_disk = 1; + last = stop2; + } else if (last > stop) { + printf ("You haven't covered whole disk with 3rd partition, but your value\n" + "%d %s coveres some other partition. Your entry have been changed\n" + "to %d %s\n", scround(last), str_units(), scround(stop), str_units()); + last = stop; + } + } else if (!whole_disk && last > stop) + last = stop; + + if (whole_disk) sys = WHOLE_DISK; + set_sun_partition(n, first, last, sys); +} + +void +sun_delete_partition(int i) { + if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK && + !sunlabel->partitions[i].start_cylinder && + SSWAP32(sunlabel->partitions[i].num_sectors) == heads * sectors * cylinders) + printf("If you want to maintain SunOS/Solaris compatibility, consider leaving this\n" + "partition as Whole disk (5), starting at 0, with %d sectors\n", + SSWAP32(sunlabel->partitions[i].num_sectors)); + sunlabel->infos[i].id = 0; + sunlabel->partitions[i].num_sectors = 0; +} + +void +sun_change_sysid(int i, int sys) { + if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) { + read_chars( + "It is highly recommended that the partition at offset 0\n" + "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n" + "there may destroy your partition table and bootblock.\n" + "Type YES if you're very sure you would like that partition\n" + "tagged with 82 (Linux swap): "); + if (strcmp (line_ptr, "YES\n")) + return; + } + switch (sys) { + case SUNOS_SWAP: + case LINUX_SWAP: + /* swaps are not mountable by default */ + sunlabel->infos[i].flags |= 0x01; + break; + default: + /* assume other types are mountable; + user can change it anyway */ + sunlabel->infos[i].flags &= ~0x01; + break; + } + sunlabel->infos[i].id = sys; +} + +void +sun_list_table(int xtra) { + int i, w; + char *type; + + w = strlen(disk_device); + if (xtra) + printf("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n" + "%d cylinders, %d alternate cylinders, %d physical cylinders\n" + "%d extra sects/cyl, interleave %d:1\n" + "%s\n" + "Units = %ss of %d * 512 bytes\n\n", + disk_device, heads, sectors, SSWAP16(sunlabel->rspeed), + cylinders, SSWAP16(sunlabel->nacyl), + SSWAP16(sunlabel->pcylcount), + SSWAP16(sunlabel->sparecyl), + SSWAP16(sunlabel->ilfact), + (char *)sunlabel, + str_units(), display_factor); + else + printf("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n" + "Units = %ss of %d * 512 bytes\n\n", + disk_device, heads, sectors, cylinders, + str_units(), display_factor); + + printf("%*s Flag %s Start End Blocks Id System\n", + w + 1, "Device", show_begin ? " Begin " : " "); + for (i = 0 ; i < partitions; i++) { + if (sunlabel->partitions[i].num_sectors) { + __u32 start = SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors; + __u32 len = SSWAP32(sunlabel->partitions[i].num_sectors); + printf( + show_begin + ? "%*s%-2d %c%c%9d%9d%9d%9d%c %2x %s\n" + : "%*s%-2d %c%c%c%9d%9d%9d%c %2x %s\n", +/* device */ w, disk_device, i + 1, +/* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', + (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ', +/* begin */ show_begin ? scround(start) : ' ', +/* start */ scround(start), +/* end */ scround(start+len), +/* odd flag on end */ len / 2, len & 1 ? '+' : ' ', +/* type id */ sunlabel->infos[i].id, +/* type name */ (type = partition_type(sunlabel->infos[i].id)) + ? type : "Unknown"); + } + } +} + +void +sun_set_alt_cyl(void) { + sunlabel->nacyl = SSWAP16(read_int(0,SSWAP16(sunlabel->nacyl), + 65535, deflt, + "Number of alternate cylinders")); +} + +void +sun_set_ncyl(int cyl) { + sunlabel->ncyl = SSWAP16(cyl); +} + +void +sun_set_xcyl(void) { + sunlabel->sparecyl = SSWAP16(read_int(0, SSWAP16(sunlabel->sparecyl), + sectors, deflt, + "Extra sectors per cylinder")); +} + +void +sun_set_ilfact(void) { + sunlabel->ilfact = SSWAP16(read_int(1, SSWAP16(sunlabel->ilfact), + 32, deflt, + "Interleave factor")); +} + +void +sun_set_rspeed(void) { + sunlabel->rspeed = SSWAP16(read_int(1, SSWAP16(sunlabel->rspeed), + 100000, deflt, + "Rotation speed (rpm)")); +} + +void +sun_set_pcylcount(void) { + sunlabel->pcylcount=SSWAP16(read_int(0, SSWAP16(sunlabel->pcylcount), + 65535, deflt, + "Number of physical cylinders")); +} + +void +sun_write_table(void) { + unsigned short *ush = (unsigned short *)sunlabel; + unsigned short csum = 0; + + while(ush < (unsigned short *)(&sunlabel->csum)) + csum ^= *ush++; + sunlabel->csum = csum; + if (lseek(fd, 0, SEEK_SET) < 0) + fatal(unable_to_seek); + if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE) + fatal(unable_to_write); +} + +#endif /* sparc */ diff --git a/disk-utils/fdisksunlabel.h b/disk-utils/fdisksunlabel.h new file mode 100644 index 000000000..037e437c6 --- /dev/null +++ b/disk-utils/fdisksunlabel.h @@ -0,0 +1,73 @@ +#include <linux/types.h> /* for __u32 etc */ + +typedef struct { + unsigned char info[128]; /* Informative text string */ + unsigned char spare0[14]; + struct sun_info { + unsigned char spare1; + unsigned char id; + unsigned char spare2; + unsigned char flags; + } infos[8]; + unsigned char spare1[246]; /* Boot information etc. */ + unsigned short rspeed; /* Disk rotational speed */ + unsigned short pcylcount; /* Physical cylinder count */ + unsigned short sparecyl; /* extra sects per cylinder */ + unsigned char spare2[4]; /* More magic... */ + unsigned short ilfact; /* Interleave factor */ + unsigned short ncyl; /* Data cylinder count */ + unsigned short nacyl; /* Alt. cylinder count */ + unsigned short ntrks; /* Tracks per cylinder */ + unsigned short nsect; /* Sectors per track */ + unsigned char spare3[4]; /* Even more magic... */ + struct sun_partition { + __u32 start_cylinder; + __u32 num_sectors; + } partitions[8]; + unsigned short magic; /* Magic number */ + unsigned short csum; /* Label xor'd checksum */ +} sun_partition; + +#define SUN_LABEL_MAGIC 0xDABE +#define SUN_LABEL_MAGIC_SWAPPED 0xBEDA +#define sunlabel ((sun_partition *)buffer) +#define SSWAP16(x) (other_endian ? __swap16(x) \ + : (__u16)(x)) +#define SSWAP32(x) (other_endian ? __swap32(x) \ + : (__u32)(x)) + +#define scround(x) ((x+(display_factor-1)*unit_flag)/display_factor) + +/* fdisk.c */ +extern char changed[MAXIMUM_PARTS]; +extern char buffer[SECTOR_SIZE]; +extern uint heads, sectors, cylinders; +extern int show_begin; +extern int sun_label; +extern char *partition_type(unsigned char type); +extern void update_units(void); +extern char read_chars(char *mesg); + +/* fdisksunlabel.c */ +#define SUNOS_SWAP 3 +#define WHOLE_DISK 5 + +extern struct systypes sun_sys_types[]; +extern int get_num_sectors(struct sun_partition p); +extern void guess_device_type(int fd); +extern int check_sun_label(void); +extern void create_sunlabel(void); +extern void sun_delete_partition(int i); +extern void sun_change_sysid(int i, int sys); +extern void sun_list_table(int xtra); +extern void verify_sun(void); +extern void add_sun_partition(int n, int sys); +extern void sun_write_table(void); +extern void sun_set_alt_cyl(void); +extern void sun_set_ncyl(int cyl); +extern void sun_set_xcyl(void); +extern void sun_set_ilfact(void); +extern void sun_set_rspeed(void); +extern void sun_set_pcylcount(void); +extern void toggle_sunflags(int i, unsigned char mask); + diff --git a/disk-utils/fsck.minix.c b/disk-utils/fsck.minix.c index 0e8dc64e0..ae1d7b1a8 100644 --- a/disk-utils/fsck.minix.c +++ b/disk-utils/fsck.minix.c @@ -50,7 +50,7 @@ * * 02.07.96 - Added C bit fiddling routines from rmk@ecs.soton.ac.uk * (Russell King). He made them for ARM. It would seem - * that the ARM is powerfull enough to do this in C whereas + * that the ARM is powerful enough to do this in C whereas * i386 and m64k must use assembly to get it fast >:-) * This should make minix fsck systemindependent. * (janl@math.uio.no, Nicolai Langfeldt) @@ -160,8 +160,8 @@ static char super_block_buffer[BLOCK_SIZE]; #define MAGIC (Super.s_magic) #define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS) -static char inode_map[BLOCK_SIZE * MINIX_I_MAP_SLOTS]; -static char zone_map[BLOCK_SIZE * MINIX_Z_MAP_SLOTS]; +static char *inode_map; +static char *zone_map; static unsigned char * inode_count = NULL; static unsigned char * zone_count = NULL; @@ -566,20 +566,26 @@ void read_superblock(void) die("bad magic number in super-block"); if (ZONESIZE != 0 || BLOCK_SIZE != 1024) die("Only 1k blocks/zones supported"); - if (!IMAPS || IMAPS > MINIX_I_MAP_SLOTS) + if (IMAPS * BLOCK_SIZE * 8 < INODES + 1) die("bad s_imap_blocks field in super-block"); - if (!ZMAPS || ZMAPS > MINIX_Z_MAP_SLOTS) + if (ZMAPS * BLOCK_SIZE * 8 < ZONES - FIRSTZONE + 1) die("bad s_zmap_blocks field in super-block"); } void read_tables(void) { + inode_map = malloc(IMAPS * BLOCK_SIZE); + if (!inode_map) + die("Unable to allocate buffer for inode map"); + zone_map = malloc(ZMAPS * BLOCK_SIZE); + if (!inode_map) + die("Unable to allocate buffer for zone map"); memset(inode_map,0,sizeof(inode_map)); memset(zone_map,0,sizeof(zone_map)); inode_buffer = malloc(INODE_BUFFER_SIZE); if (!inode_buffer) die("Unable to allocate buffer for inodes"); - inode_count = malloc(INODES); + inode_count = malloc(INODES + 1); if (!inode_count) die("Unable to allocate buffer for inode count"); zone_count = malloc(ZONES); @@ -611,7 +617,7 @@ struct minix_inode * get_inode(unsigned int nr) { struct minix_inode * inode; - if (!nr || nr >= INODES) + if (!nr || nr > INODES) return NULL; total++; inode = Inode + nr; @@ -662,7 +668,7 @@ get_inode2 (unsigned int nr) { struct minix2_inode *inode; - if (!nr || nr >= INODES) + if (!nr || nr > INODES) return NULL; total++; inode = Inode2 + nr; @@ -876,7 +882,7 @@ void check_zones(unsigned int i) { struct minix_inode * inode; - if (!i || i >= INODES) + if (!i || i > INODES) return; if (inode_count[i] > 1) /* have we counted this file already? */ return; @@ -896,7 +902,7 @@ check_zones2 (unsigned int i) { struct minix2_inode *inode; - if (!i || i >= INODES) + if (!i || i > INODES) return; if (inode_count[i] > 1) /* have we counted this file already? */ return; @@ -924,7 +930,7 @@ void check_file(struct minix_inode * dir, unsigned int offset) read_block(block, blk); name = blk + (offset % BLOCK_SIZE) + 2; ino = * (unsigned short *) (name-2); - if (ino >= INODES) { + if (ino > INODES) { print_current_name(); printf(" contains a bad inode number for file '"); printf("%.*s'.",namelen,name); @@ -986,7 +992,7 @@ check_file2 (struct minix2_inode *dir, unsigned int offset) read_block (block, blk); name = blk + (offset % BLOCK_SIZE) + 2; ino = *(unsigned short *) (name - 2); - if (ino >= INODES) { + if (ino > INODES) { print_current_name (); printf (" contains a bad inode number for file '"); printf ("%.*s'.", namelen, name); @@ -1087,7 +1093,7 @@ void check_counts(void) { int i; - for (i=1 ; i < INODES ; i++) { + for (i=1 ; i <= INODES ; i++) { if (!inode_in_use(i) && Inode[i].i_mode && warn_mode) { printf("Inode %d mode not cleared.",i); if (ask("Clear",1)) { @@ -1140,7 +1146,7 @@ check_counts2 (void) { int i; - for (i = 1; i < INODES; i++) { + for (i = 1; i <= INODES; i++) { if (!inode_in_use (i) && Inode2[i].i_mode && warn_mode) { printf ("Inode %d mode not cleared.", i); if (ask ("Clear", 1)) { @@ -1189,7 +1195,7 @@ check_counts2 (void) void check(void) { - memset(inode_count,0,INODES*sizeof(*inode_count)); + memset(inode_count,0,(INODES + 1) * sizeof(*inode_count)); memset(zone_count,0,ZONES*sizeof(*zone_count)); check_zones(ROOT_INO); recursive_check(ROOT_INO); @@ -1200,7 +1206,7 @@ void check(void) void check2 (void) { - memset (inode_count, 0, INODES * sizeof (*inode_count)); + memset (inode_count, 0, (INODES + 1) * sizeof (*inode_count)); memset (zone_count, 0, ZONES * sizeof (*zone_count)); check_zones2 (ROOT_INO); recursive_check2 (ROOT_INO); @@ -1299,11 +1305,11 @@ int main(int argc, char ** argv) if (verbose) { int i, free; - for (i=1,free=0 ; i < INODES ; i++) + for (i=1,free=0 ; i <= INODES ; i++) if (!inode_in_use(i)) free++; - printf("\n%6ld inodes used (%ld%%)\n",(INODES-free-1), - 100*(INODES-free-1)/(INODES-1)); + printf("\n%6ld inodes used (%ld%%)\n",(INODES-free), + 100*(INODES-free)/INODES); for (i=FIRSTZONE,free=0 ; i < ZONES ; i++) if (!zone_in_use(i)) free++; diff --git a/disk-utils/llseek.c b/disk-utils/llseek.c index dcbfb2a45..a9cd5a3ac 100644 --- a/disk-utils/llseek.c +++ b/disk-utils/llseek.c @@ -5,29 +5,18 @@ * under the terms of the GNU Public License. */ -#define FOR_UTIL_LINUX - #include <sys/types.h> #include <errno.h> #include <unistd.h> -#ifndef FOR_UTIL_LINUX - -#include "et/com_err.h" -#include "ext2fs/io.h" - -#else /* FOR_UTIL_LINUX */ - #if defined(__GNUC__) || defined(HAS_LONG_LONG) typedef long long ext2_loff_t; #else typedef long ext2_loff_t; #endif -ext2_loff_t ext2_llseek (unsigned int, ext2_loff_t, unsigned int); - -#endif /* FOR_UTIL_LINUX */ +extern ext2_loff_t ext2_llseek (unsigned int, ext2_loff_t, unsigned int); #ifdef __linux__ @@ -40,13 +29,8 @@ ext2_loff_t ext2_llseek (unsigned int, ext2_loff_t, unsigned int); #define my_llseek lseek -#elif __i386__ - -#include <linux/unistd.h> - -#ifndef __NR__llseek -#define __NR__llseek 140 -#endif +#else +#include <linux/unistd.h> /* for __NR__llseek */ static int _llseek (unsigned int, unsigned long, unsigned long, ext2_loff_t *, unsigned int); @@ -67,10 +51,6 @@ static ext2_loff_t my_llseek (unsigned int fd, ext2_loff_t offset, return (retval == -1 ? (ext2_loff_t) retval : result); } -#else - -#error "llseek() is not available" - #endif /* __alpha__ */ #endif /* HAVE_LLSEEK */ @@ -81,25 +61,27 @@ ext2_loff_t ext2_llseek (unsigned int fd, ext2_loff_t offset, ext2_loff_t result; static int do_compat = 0; - if ((sizeof(off_t) >= sizeof(ext2_loff_t)) || - (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) - return lseek(fd, (off_t) offset, origin); + if (!do_compat) { + result = my_llseek (fd, offset, origin); + if (!(result == -1 && errno == ENOSYS)) + return result; - if (do_compat) { - errno = EINVAL; - return -1; - } - - result = my_llseek (fd, offset, origin); - if (result == -1 && errno == ENOSYS) { /* * Just in case this code runs on top of an old kernel * which does not support the llseek system call */ - do_compat++; - errno = EINVAL; + do_compat = 1; + /* + * Now try ordinary lseek. + */ } - return result; + + if ((sizeof(off_t) >= sizeof(ext2_loff_t)) || + (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) + return lseek(fd, (off_t) offset, origin); + + errno = EINVAL; + return -1; } #else /* !linux */ diff --git a/disk-utils/mkfs.8 b/disk-utils/mkfs.8 index e391f7141..57132a483 100644 --- a/disk-utils/mkfs.8 +++ b/disk-utils/mkfs.8 @@ -37,9 +37,11 @@ In actuality, is simply a front-end for the various file system builders (\fBmkfs\fR.\fIfstype\fR) available under Linux. -The file system-specific builder is searched for in /etc/fs first, -then in /etc and finally in the directories listed in the PATH -enviroment variable. +The file system-specific builder is searched for in a number +of directories like /sbin, /sbin/fs, /sbin/fs.d, /etc/fs, /etc +(the precise list is defined at compile time but at least +contains /sbin and /sbin/fs), and finally in the directories +listed in the PATH enviroment variable. Please see the file system-specific builder manual pages for further details. .SH OPTIONS diff --git a/disk-utils/mkfs.c b/disk-utils/mkfs.c index 8d4671915..ba293e939 100644 --- a/disk-utils/mkfs.c +++ b/disk-utils/mkfs.c @@ -16,6 +16,7 @@ #include <stdio.h> #include <stdlib.h> #include <unistd.h> +#include <string.h> #include <getopt.h> #include <limits.h> @@ -26,7 +27,7 @@ # define DEFAULT_FSTYPE "ext2" #endif -#define SEARCH_PATH "PATH=/sbin:/sbin/fs.d:/sbin/fs:/etc/fs:/etc" +#define SEARCH_PATH "PATH=/sbin:/sbin/fs:/sbin/fs.d:/etc/fs:/etc" #define PROGNAME "mkfs.%s" @@ -35,6 +36,7 @@ int main(int argc, char *argv[]) char progname[NAME_MAX]; char *fstype = NULL; int i, more = 0, verbose = 0; + char *oldpath, *newpath; /* Check commandline options. */ opterr = 0; @@ -62,7 +64,16 @@ int main(int argc, char *argv[]) fstype = DEFAULT_FSTYPE; /* Set PATH and program name */ - putenv(SEARCH_PATH); + oldpath = getenv("PATH"); + if (!oldpath) + oldpath = "/bin"; + newpath = (char *) malloc(strlen(oldpath) + sizeof(SEARCH_PATH) + 2); + if (!newpath) { + fputs("mkfs: out of memory\n", stderr); + exit(1); + } + sprintf(newpath, "%s:%s\n", SEARCH_PATH, oldpath); + putenv(newpath); sprintf(progname, PROGNAME, fstype); argv[--optind] = progname; diff --git a/disk-utils/mkfs.minix.8 b/disk-utils/mkfs.minix.8 index 8f9e70242..9ff75321a 100644 --- a/disk-utils/mkfs.minix.8 +++ b/disk-utils/mkfs.minix.8 @@ -81,21 +81,21 @@ Usage or syntax error .BR mkefs (8), .BR efsck (8), .BR reboot (8) -.SH AUTHORS -Stared by Linus Torvalds (torvalds@cs.helsinki.fi). -.br -Error code values by Rik Faith (faith@cs.unc.edu) -.br -Inode request feature by Scott Heavner (sdh@po.cwru.edu) -.br -Support for the file system valid flag by Dr. Wettstein -(greg%wind.uucp@plains.nodak.edu) -.br -Check to prevent mkfs of mounted filesystem and boot sector clearing -by Daniel Quinlan (quinlan@yggdrasil.com) -.br -Minix v2 support by Andreas Schwab -(schwab@issan.informatik.uni-dortmund.de), updated by Nicolai -Langfeldt (janl@math.uio.no) -.br -Portability patch by Russell King.
\ No newline at end of file +.\" .SH AUTHORS +.\" Linus Torvalds (torvalds@cs.helsinki.fi). +.\" .br +.\" Error code values by Rik Faith (faith@cs.unc.edu) +.\" .br +.\" Inode request feature by Scott Heavner (sdh@po.cwru.edu) +.\" .br +.\" Support for the file system valid flag by Dr. Wettstein +.\" (greg%wind.uucp@plains.nodak.edu) +.\" .br +.\" Check to prevent mkfs of mounted filesystem and boot sector clearing +.\" by Daniel Quinlan (quinlan@yggdrasil.com) +.\" .br +.\" Minix v2 support by Andreas Schwab +.\" (schwab@issan.informatik.uni-dortmund.de), updated by Nicolai +.\" Langfeldt (janl@math.uio.no) +.\" .br +.\" Portability patch by Russell King. diff --git a/disk-utils/mkfs.minix.c b/disk-utils/mkfs.minix.c index 403a278c9..db7aefaea 100644 --- a/disk-utils/mkfs.minix.c +++ b/disk-utils/mkfs.minix.c @@ -141,8 +141,8 @@ static char boot_block_buffer[512]; #define MAGIC (Super.s_magic) #define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS) -static char inode_map[BLOCK_SIZE * MINIX_I_MAP_SLOTS]; -static char zone_map[BLOCK_SIZE * MINIX_Z_MAP_SLOTS]; +static char *inode_map; +static char *zone_map; static unsigned short good_blocks_table[MAX_GOOD_BLOCKS]; static int used_good_blocks = 0; @@ -432,6 +432,9 @@ void make_root_inode(void) inode->i_size = 2*dirsize; } inode->i_mode = S_IFDIR + 0755; + inode->i_uid = getuid(); + if (inode->i_uid) + inode->i_gid = getgid(); write_block(inode->i_zone[0],root_block); } @@ -453,6 +456,9 @@ make_root_inode2 (void) inode->i_size = 2 * dirsize; } inode->i_mode = S_IFDIR + 0755; + inode->i_uid = getuid(); + if (inode->i_uid) + inode->i_gid = getgid(); write_block (inode->i_zone[0], root_block); } #endif @@ -462,8 +468,6 @@ void setup_tables(void) int i; unsigned long inodes; - memset(inode_map,0xff,sizeof(inode_map)); - memset(zone_map,0xff,sizeof(zone_map)); memset(super_block_buffer,0,BLOCK_SIZE); memset(boot_block_buffer,0,512); MAGIC = magic; @@ -475,24 +479,32 @@ void setup_tables(void) inodes = BLOCKS/3; else inodes = req_nr_inodes; + /* Round up inode count to fill block size */ +#ifdef HAVE_MINIX2 + if (version2) + inodes = ((inodes + MINIX2_INODES_PER_BLOCK - 1) & + ~(MINIX2_INODES_PER_BLOCK - 1)); + else +#endif + inodes = ((inodes + MINIX_INODES_PER_BLOCK - 1) & + ~(MINIX_INODES_PER_BLOCK - 1)); if (inodes > 65535) inodes = 65535; INODES = inodes; -/* I don't want some off-by-one errors, so this hack... */ - if ((INODES & 8191) > 8188) - INODES -= 5; - if ((INODES & 8191) < 10) - INODES -= 20; - IMAPS = UPPER(INODES,BITS_PER_BLOCK); + IMAPS = UPPER(INODES + 1,BITS_PER_BLOCK); ZMAPS = 0; - while (ZMAPS != UPPER(BLOCKS - NORM_FIRSTZONE,BITS_PER_BLOCK)) - ZMAPS = UPPER(BLOCKS - NORM_FIRSTZONE,BITS_PER_BLOCK); - if (ZMAPS > 64) - die ("Filesystem too big for Linux to handle"); + while (ZMAPS != UPPER(BLOCKS - NORM_FIRSTZONE + 1,BITS_PER_BLOCK)) + ZMAPS = UPPER(BLOCKS - NORM_FIRSTZONE + 1,BITS_PER_BLOCK); FIRSTZONE = NORM_FIRSTZONE; + inode_map = malloc(IMAPS * BLOCK_SIZE); + zone_map = malloc(ZMAPS * BLOCK_SIZE); + if (!inode_map || !zone_map) + die("unable to allocate buffers for maps"); + memset(inode_map,0xff,IMAPS * BLOCK_SIZE); + memset(zone_map,0xff,ZMAPS * BLOCK_SIZE); for (i = FIRSTZONE ; i<ZONES ; i++) unmark_zone(i); - for (i = MINIX_ROOT_INO ; i<INODES ; i++) + for (i = MINIX_ROOT_INO ; i<=INODES ; i++) unmark_inode(i); inode_buffer = malloc(INODE_BUFFER_SIZE); if (!inode_buffer) diff --git a/disk-utils/mkswap.c b/disk-utils/mkswap.c index 2a4027406..49447f2af 100644 --- a/disk-utils/mkswap.c +++ b/disk-utils/mkswap.c @@ -193,11 +193,11 @@ int main(int argc, char ** argv) if (PAGES < 10) { fprintf(stderr, "%s: error: swap area needs to be at least %ldkB\n", - program_name, 10 * PAGE_SIZE / 1024); + program_name, (long)(10 * PAGE_SIZE / 1024)); usage(); } if (PAGES > 8 * (PAGE_SIZE - 10)) { - PAGES = 8 * (PAGE_SIZE - 10); + PAGES = 8 * (PAGE_SIZE - 10); fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n", program_name, PAGES * PAGE_SIZE / 1024); } @@ -217,11 +217,17 @@ int main(int argc, char ** argv) if (goodpages <= 0) die("Unable to set up swap-space: unreadable"); printf("Setting up swapspace, size = %ld bytes\n", - goodpages*PAGE_SIZE); + (long)(goodpages*PAGE_SIZE)); strncpy((char*)signature_page+PAGE_SIZE-10, "SWAP-SPACE", 10); if (lseek(DEV, 0, SEEK_SET)) die("unable to rewind swap-device"); if (PAGE_SIZE != write(DEV, signature_page, PAGE_SIZE)) die("unable to write signature page"); + /* + * A subsequent swapon() will fail if the signature + * is not actually on disk. (This is a kernel bug.) + */ + if (fsync(DEV)) + die("fsync failed"); return 0; } diff --git a/disk-utils/sfdisk.8 b/disk-utils/sfdisk.8 index fc9308013..33f10dabd 100644 --- a/disk-utils/sfdisk.8 +++ b/disk-utils/sfdisk.8 @@ -172,7 +172,7 @@ to sfdisk. For example, .if t .ft R .fi will correct the bad last extended partition that the OS/2 -sfdisk creates. +fdisk creates. .TP .BR \-V " or " \-\-verify Test whether partitions seem correct. (See above.) diff --git a/disk-utils/sfdisk.c b/disk-utils/sfdisk.c index fcc76c41c..8fbe778fe 100644 --- a/disk-utils/sfdisk.c +++ b/disk-utils/sfdisk.c @@ -28,8 +28,8 @@ */ #define PROGNAME "sfdisk" -#define VERSION "3.06" -#define DATE "970626" +#define VERSION "3.07" +#define DATE "980518" #include <stdio.h> #include <stdlib.h> /* atoi, free */ @@ -523,13 +523,15 @@ chs_ok (chs a, char *v, char *w) { #define EMPTY_PARTITION 0 #define EXTENDED_PARTITION 5 -#define DM6_PARTITION 0x54 -#define EZD_PARTITION 0x55 +#define WIN98_EXTENDED 0x0f #define DM6_AUX1PARTITION 0x51 #define DM6_AUX3PARTITION 0x53 +#define DM6_PARTITION 0x54 +#define EZD_PARTITION 0x55 #define LINUX_SWAP 0x82 #define LINUX_NATIVE 0x83 #define LINUX_EXTENDED 0x85 +#define BSD_PARTITION 0xa5 /* * List of system Id's, adapted from fdisk 2.0d and <linux/genhd.h> @@ -596,6 +598,7 @@ struct systypes { {0x94, "Amoeba BBT"}, /* (bad block table) */ {0xa0, "IBM Thinkpad hibernation"}, /* according to dan@fch.wimsey.bc.ca */ {0xa5, "BSD/386"}, /* 386BSD */ + {0xa6, "OpenBSD"}, {0xa7, "NeXTSTEP 486"}, {0xb7, "BSDI fs"}, {0xb8, "BSDI swap"}, @@ -636,7 +639,14 @@ list_types(void) { int is_extended(unsigned char type) { - return (type == EXTENDED_PARTITION || type == LINUX_EXTENDED); + return (type == EXTENDED_PARTITION + || type == LINUX_EXTENDED + || type == WIN98_EXTENDED); +} + +int +is_bsd(unsigned char type) { + return (type == BSD_PARTITION); } /* @@ -715,6 +725,9 @@ struct part_desc { unsigned long sector, offset; /* disk location of this info */ struct partition p; struct part_desc *ep; /* extended partition containing this one */ + int ptype; +#define DOS_TYPE 0 +#define BSD_TYPE 1 } zero_part_desc; struct part_desc * @@ -966,17 +979,19 @@ out_partition(char *dev, int format, struct part_desc *p, struct disk_desc *z) { if (dump) { printf(" start=%9lu", start); printf(", size=%8lu", size); - printf(", Id=%2x", p->p.sys_type); - if (p->p.bootable == 0x80) - printf(", bootable"); + if (p->ptype == DOS_TYPE) { + printf(", Id=%2x", p->p.sys_type); + if (p->p.bootable == 0x80) + printf(", bootable"); + } printf("\n"); return; } - if(p->p.bootable == 0x80) - printf(" * "); - else if(p->p.bootable == 0) + if(p->ptype != DOS_TYPE || p->p.bootable == 0) printf(" "); + else if(p->p.bootable == 0x80) + printf(" * "); else printf(" ? "); /* garbage */ @@ -1012,11 +1027,15 @@ out_partition(char *dev, int format, struct part_desc *p, struct disk_desc *z) { out_rounddown(8, size, 2, 0); break; } - printf(" %2x %s\n", + if (p->ptype == DOS_TYPE) { + printf(" %2x %s\n", p->p.sys_type, sysname(p->p.sys_type)); + } else { + printf("\n"); + } /* Is chs as we expect? */ - if (!quiet) { + if (!quiet && p->ptype == DOS_TYPE) { chs a, b; longchs aa, bb; a = (size ? ulong_to_chs(start) : zero_chs); @@ -1113,6 +1132,7 @@ partitions_ok(struct disk_desc *z) { /* Are the logical partitions contained in their extended partitions? */ for (p = partitions+4; p < partitions+partno; p++) + if (p->ptype == DOS_TYPE) if (p->size && !is_extended(p->p.sys_type)) { q = p->ep; if (p->start < q->start || p->start + p->size > q->start + q->size) { @@ -1133,6 +1153,19 @@ partitions_ok(struct disk_desc *z) { return 0; } + /* Are the data partitions and the extended partition + table sectors disjoint? */ + for (p = partitions; p < partitions+partno; p++) + if (p->size && !is_extended(p->p.sys_type)) + for (q = partitions; q < partitions+partno; q++) + if (is_extended(q->p.sys_type)) + if (p->start <= q->start && p->start + p->size > q->start) { + warn("Warning: partition %s contains part of ", PNO(p)); + warn("the partition table (sector %lu),\n", q->start); + warn("and will destroy it when filled\n"); + return 0; + } + /* Do they start past zero and end before end-of-disk? */ { unsigned long ds = get_disksize(F_SECTOR); for (p = partitions; p < partitions+partno; p++) @@ -1217,7 +1250,8 @@ partitions_ok(struct disk_desc *z) { } /* Is chs as we expect? */ - for(p = partitions; p < partitions+partno; p++) { + for(p = partitions; p < partitions+partno; p++) + if(p->ptype == DOS_TYPE) { chs a, b; longchs aa, bb; a = p->size ? ulong_to_chs(p->start) : zero_chs; @@ -1293,7 +1327,9 @@ extended_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) partitions[pno].start = here + p.start_sect; } partitions[pno].size = p.nr_sects; - partitions[pno++].p = p; + partitions[pno].ptype = DOS_TYPE; + partitions[pno].p = p; + pno++; } here = next; } @@ -1301,6 +1337,68 @@ extended_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) z->partno = pno; } +#define BSD_DISKMAGIC (0x82564557UL) +#define BSD_MAXPARTITIONS 8 +#define BSD_FS_UNUSED 0 +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +struct bsd_disklabel { + u32 d_magic; + char d_junk1[4]; + char d_typename[16]; + char d_packname[16]; + char d_junk2[92]; + u32 d_magic2; + char d_junk3[2]; + u16 d_npartitions; /* number of partitions in following */ + char d_junk4[8]; + struct bsd_partition { /* the partition table */ + u32 p_size; /* number of sectors in partition */ + u32 p_offset; /* starting sector */ + u32 p_fsize; /* filesystem basic fragment size */ + u8 p_fstype; /* filesystem type, see below */ + u8 p_frag; /* filesystem fragments per block */ + u16 p_cpg; /* filesystem cylinders per group */ + } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */ +}; + +static void +bsd_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) { + struct bsd_disklabel *l; + struct bsd_partition *bp, *bp0; + unsigned long start = ep->start; + struct sector *s; + struct part_desc *partitions = &(z->partitions[0]); + int pno = z->partno; + + if (!(s = get_sector(dev,fd,start+1))) + return; + l = (struct bsd_disklabel *) (s->data); + if (l->d_magic != BSD_DISKMAGIC) + return; + + bp = bp0 = &l->d_partitions[0]; + while (bp - bp0 <= BSD_MAXPARTITIONS) { + if (pno+1 >= SIZE(z->partitions)) { + printf("too many partitions - ignoring those " + "past nr (%d)\n", pno-1); + break; + } + if (bp->p_fstype != BSD_FS_UNUSED) { + partitions[pno].start = bp->p_offset; + partitions[pno].size = bp->p_size; + partitions[pno].sector = start+1; + partitions[pno].offset = (char *)bp - (char *)bp0; + partitions[pno].ep = 0; + partitions[pno].ptype = BSD_TYPE; + pno++; + } + bp++; + } + z->partno = pno; +} + static int msdos_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { int i; @@ -1349,7 +1447,7 @@ msdos_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { z->partno = pno; - for (i=0; i<4; i++) + for (i=0; i<4; i++) { if (is_extended(partitions[i].p.sys_type)) { if (!partitions[i].size) { printf("strange..., an extended partition of size 0?\n"); @@ -1357,7 +1455,14 @@ msdos_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { } extended_partition(dev, fd, &partitions[i], z); } - + if (is_bsd(partitions[i].p.sys_type)) { + if (!partitions[i].size) { + printf("strange..., a BSD partition of size 0?\n"); + continue; + } + bsd_partition(dev, fd, &partitions[i], z); + } + } return 1; } @@ -1366,11 +1471,24 @@ osf_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { return 0; } +static int +sun_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { + return 0; +} + +static int +amiga_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { + return 0; +} + void get_partitions(char *dev, int fd, struct disk_desc *z) { z->partno = 0; - if (!msdos_partition(dev, fd, 0, z) && !osf_partition(dev, fd, 0, z)) { + if (!msdos_partition(dev, fd, 0, z) + && !osf_partition(dev, fd, 0, z) + && !sun_partition(dev, fd, 0, z) + && !amiga_partition(dev, fd, 0, z)) { printf(" %s: unrecognized partition\n", dev); return; } @@ -2139,6 +2257,31 @@ static struct devd { { "xd", "ab" } }; +int +is_ide_cdrom(char *device) { + /* No device was given explicitly, and we are trying some + likely things. But opening /dev/hdc may produce errors like + "hdc: tray open or drive not ready" + if it happens to be a CD-ROM drive. So try to be careful. + This only works since 2.1.73. */ + + FILE *procf; + char buf[100]; + struct stat statbuf; + + sprintf(buf, "/proc/ide/%s/media", device+5); + procf = fopen(buf, "r"); + if (procf != NULL && fgets(buf, sizeof(buf), procf)) + return !strncmp(buf, "cdrom", 5); + + /* Now when this proc file does not exist, skip the + device when it is read-only. */ + if (stat(device, &statbuf) == 0) + return (statbuf.st_mode & 0222) == 0; + + return 0; +} + void do_list(char *dev, int silent); void do_size(char *dev, int silent); void do_geom(char *dev, int silent); @@ -2277,6 +2420,8 @@ main(int argc, char **argv) { lp = dp->letters; while(*lp) { sprintf(device, "/dev/%s%c", dp->pref, *lp++); + if (!strcmp(dp->pref, "hd") && is_ide_cdrom(device)) + continue; if (opt_out_geom) do_geom(device, 1); if (opt_size) @@ -2427,7 +2572,7 @@ do_size (char *dev, int silent) { size /= 2; /* convert sectors to blocks */ if (silent) - printf("%s: %d\n", dev, size); + printf("%s: %9d\n", dev, size); else printf("%d\n", size); |