diff options
author | Karel Zak | 2006-12-07 00:25:37 +0100 |
---|---|---|
committer | Karel Zak | 2006-12-07 00:25:37 +0100 |
commit | 5c36a0eb7cdb0360f9afd5d747c321f423b35984 (patch) | |
tree | 147599a77eaff2b5fbc0d389e89d2b51602326c0 /disk-utils | |
parent | Imported from util-linux-2.8 tarball. (diff) | |
download | kernel-qcow2-util-linux-5c36a0eb7cdb0360f9afd5d747c321f423b35984.tar.gz kernel-qcow2-util-linux-5c36a0eb7cdb0360f9afd5d747c321f423b35984.tar.xz kernel-qcow2-util-linux-5c36a0eb7cdb0360f9afd5d747c321f423b35984.zip |
Imported from util-linux-2.9i tarball.
Diffstat (limited to 'disk-utils')
-rw-r--r-- | disk-utils/Makefile | 47 | ||||
-rw-r--r-- | disk-utils/README.cfdisk | 45 | ||||
-rw-r--r-- | disk-utils/README.fdisk | 579 | ||||
-rw-r--r-- | disk-utils/cfdisk.8 | 403 | ||||
-rw-r--r-- | disk-utils/cfdisk.8.bak | 407 | ||||
-rw-r--r-- | disk-utils/cfdisk.c | 2560 | ||||
-rw-r--r-- | disk-utils/cfdisk.c.bak | 2066 | ||||
-rw-r--r-- | disk-utils/cfdisk.c.orig | 2066 | ||||
-rw-r--r-- | disk-utils/fdformat.c | 12 | ||||
-rw-r--r-- | disk-utils/fdisk.8 | 213 | ||||
-rw-r--r-- | disk-utils/fdisk.c | 1940 | ||||
-rw-r--r-- | disk-utils/fdisk.h | 72 | ||||
-rw-r--r-- | disk-utils/fdisklabel.c | 815 | ||||
-rw-r--r-- | disk-utils/fdisklabel.h | 229 | ||||
-rw-r--r-- | disk-utils/fdisksunlabel.c | 661 | ||||
-rw-r--r-- | disk-utils/fdisksunlabel.h | 73 | ||||
-rw-r--r-- | disk-utils/fdprm | 2 | ||||
-rw-r--r-- | disk-utils/frag.8 | 47 | ||||
-rw-r--r-- | disk-utils/frag.c | 311 | ||||
-rw-r--r-- | disk-utils/fsck.minix.c | 28 | ||||
-rw-r--r-- | disk-utils/llseek.c | 102 | ||||
-rw-r--r-- | disk-utils/mkfs.8 | 9 | ||||
-rw-r--r-- | disk-utils/mkfs.minix.c | 4 | ||||
-rw-r--r-- | disk-utils/mkswap.8 | 163 | ||||
-rw-r--r-- | disk-utils/mkswap.c | 271 | ||||
-rw-r--r-- | disk-utils/setfdprm.c | 3 | ||||
-rw-r--r-- | disk-utils/sfdisk.8 | 497 | ||||
-rw-r--r-- | disk-utils/sfdisk.c | 2857 | ||||
-rw-r--r-- | disk-utils/sfdisk.examples | 264 |
29 files changed, 344 insertions, 16402 deletions
diff --git a/disk-utils/Makefile b/disk-utils/Makefile index d21cedb9e..aec38630a 100644 --- a/disk-utils/Makefile +++ b/disk-utils/Makefile @@ -23,48 +23,12 @@ ifneq "$(CPU)" "sparc" # 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 # Where to put datebase files? 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 - rm -f activate - ln -s sfdisk activate - -# Rules for everything else - fdformat: fdformat.o fsck.minix: fsck.minix.o fsck.minix.o: fsck.minix.c bitops.h @@ -73,17 +37,6 @@ 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 install: all $(INSTALLDIR) $(SBINDIR) $(USRBINDIR) $(ETCDIR) diff --git a/disk-utils/README.cfdisk b/disk-utils/README.cfdisk deleted file mode 100644 index 5241ad136..000000000 --- a/disk-utils/README.cfdisk +++ /dev/null @@ -1,45 +0,0 @@ -Announcing the new curses based fdisk program... cfdisk - -cfdisk is a curses based disk drive partitioning program that can -create partitions for a wide variety of operating systems including -Linux, MS-DOS and OS/2. cfdisk was inspired by the fdisk program, by -A. V. Le Blanc (LeBlanc@mcc.ac.uk). I hope that this program will be -useful to both new and old Linux users, and I hope it will make the -installation process easier. - - - **** WARNING **** -If you write a bad partition table to disk, it may destroy data and -partitions. - - -You can FTP cfdisk from ftp.cs.unc.edu in the /pub/martin/linux -directory. - -I would also like comments (good and bad) on the user interface, logic -and ease of use. If you have any suggestions for improvements, I -would be happy to hear them. - -My e-mail address is martin@cs.unc.edu. - -------------------------------------------------------------------- - - Copyright (C) 1994 Kevin E. Martin (martin@cs.unc.edu) - -cfdisk is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2 of the License, or (at your -option) any later version. - -cfdisk is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with cfdisk; if not, write to the Free Software Foundation, -Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -___ -Kevin E. Martin University of North Carolina at Chapel Hill -martin@cs.unc.edu Department of Computer Science diff --git a/disk-utils/README.fdisk b/disk-utils/README.fdisk deleted file mode 100644 index 40f54b4b9..000000000 --- a/disk-utils/README.fdisk +++ /dev/null @@ -1,579 +0,0 @@ -`fdisk': the Linux partition table editor -========================================= - -`fdisk' is the Linux partition table editor. In this section we -examine this utility and try to describe it thoroughly enough so that -anyone can use it. - -* Contents: - -* Disks and how they are described. -* Dividing up your disk. -* The `fdisk' command. -* Deleting and adding partitions. -* Active flags and system types. -* Extra commands for experts. -* Warnings for `fdisk' users. - - -Disks and how they are described --------------------------------- - -A typical disk consists physically of one or more circular objects -called "platters", which rotate about a central axis. Devices called -"heads" move to specified places on the disk surface to read or write -information. There is usually one head on each side of every platter, -and all these heads are attached to a comb-like controller arm which -moves all of them at the same time, either closer to the centre of the -disk, or closer to the outer edge. - -Suppose the arm is in one position, putting an area of the disk -surface within reach of one or another of the heads. This total area, -everything that is accessible without moving the arm, is called a -"cylinder". (A cylinder is a barrel-shaped cross section of a disk, -consisting of a circular strip from each side of each platter.) The -part of a cylinder that one head can read or write without moving is -called a "track". - -Each track is divided into several pie-shaped slices called -"sectors", which are the smallest parts of the disk which can be read -or written at a time. The sectors on one disk are usually all the same -size. - -In fact, there are not always two heads to every platter, there are -some disks which do not have the same amount of data in every cylinder, -and there may be disks which do not have the same amount of data in -every sector. These features are usually hidden on PCs by the -controller card or the BIOS, which map the physical geometry of a disk -onto a logical geometry, which is what is actually used to access the -disk. - -The numbers which describe the "geometry" of a disk are - - 1. The number of cylinders it contains. - - 2. The number of tracks per cylinder, which is the number of heads. - - 3. The number of sectors per track. - - 4. The number of bytes per sector. - -These numbers vary from disk to disk, but a typical PC disk might -have about 1000 cylinders, half a dozen heads, and 15 or 20 sectors per -track, with each sector containing 512 bytes or characters; such a disk -contains 40 to 60 megabytes of data. A "double density" floppy disk -contains 40 cylinders, with 2 heads (2 tracks per cylinder), and with 9 -sectors per track; such a disk contains 360 kilobytes, or 360 * 1024 -characters. A "high density" 3.5 inch floppy contains 80 cylinders, -with 2 heads and 18 sectors per track, or 1.44 megabytes, or 1440 * -1024 characters. - -The exact size of a track or cylinder in bytes varies from one disk -to another. This `fdisk' for Linux deals mainly with cylinders, since -this is the best unit to use when allocating space for partitions. It -reports partition sizes in "blocks" of 1024 bytes, or 2 sectors, since -`mkswap' and the various `mkfs' programs require this number. A block -is the smallest amount of space which can be set aside for a file in -the current file systems. - -An operating system, such as Linux or DOS or OS/2, may use a disk in -any way that it wishes, but if two operating systems share the same -disk, they must agree on who owns what, or else one will interfere with -the other (that is, by damaging the other's files). A "partition" is a -section of a hard disk which is handled as a unit by all operating -systems which can access the disk. The standard way to define -partitions (for the moment) is the "partition table", a list of -information which is stored in parts of the disk that don't belong to -any of the systems using the disk. The beginning of the partition -table is stored in the disk's primary boot sector, and the rest is -stored in a chain of sectors scattered throughout the disk. - -The first sector on the disk is called the "primary boot block" or -"primary boot sector" because (1) it comes first, before other, similar -sectors; (2) it tells where the other, similar sectors are found, so -that it is logically `prior' to them; and (3) it usually contains code -which is executed when the system boots up. This sector contains a -table describing at most four partitions. These areas are called -"primary partitions". - -The partition table in the primary boot sector may also describe at -most one "extended partition". This is a large area of the disk, -usually containing all the space which is not in any primary partition. -Within this space we can set aside other areas which are called -"logical partitions", because they look almost exactly like primary -partitions. In fact, the main difference between them is that we can -boot from primary partitions, while we cannot boot from logical -partitions. This happens because the address of a primary partition is -in a fixed place, whereas the address of a secondary partition is not, -so we require a more complicated process to discover it, one which is -too difficult for most primary boot programs. - - -Dividing up your disk ---------------------- - -It is a good idea to plan ahead before you start creating partitions -on your disk. If you set aside a partition for some purpose, it is not -easy to change its size: you must backup all the data from the partition, -whether to floppies, to another partition, to another hard disk, or -somewhere else; then you must edit the table which describes this -partition, so changing its size; then you must reboot and initialise -the new partition, formatting it, for example, under DOS, or running -`mkfs' under Linux; finally you can copy all the data back. It is -possible, if you have several partitions, to copy data back and forth -between them while you change their sizes, but this is a bit risky and -time consuming. It is better to plan ahead what you will need, since -it is hard to change it afterwards. - -Many people with large disks and recent versions of DOS have their -entire file system on one large partition. They usually ask, `Isn't -there any way I can reformat my disk without copying everything off?' -There is no way to do it using standard DOS utilities, and there is no -truly safe way to do it using commercial software, because, if you make -a mistake, you will lose the entire contents of your disk. If you are -going to back up your disk anyway, you might as well copy the data back -safely. The Linux FAQ contains references to tools and procedures -which will allow you to do this, if you dare. - -DOS and Linux both allow you to access several partitions on a -single disk; on DOS these are treated as if they were separate disks or -drives, and under Linux they are treated as different "devices". - -You can have up to 64 partitions on a single IDE disk, or up to 16 -partitions on a single SCSI disk, at least as far as Linux is -concerned; in practice you will rarely want so many. The maximum size -of a Linux file system on a single partition depends on the type of -file system you use. Minix file systems are limited to 64 megabytes. -You may have all of your Linux files in a single partition, or you may -have two, three, or more Linux file systems. Similarly you may have -one or more DOS partitions. If you have several small partitions, you -run much less risk of losing all your files if your disk gets -corrupted. On the other hand, you may run out of space on a small -partition more easily. - -Under DOS, you must refer to each partition by a separate drive -letter, but all partitions are automatically accessible. Under Linux -only the root partition is automatically accessible, but once we mount -another partition, it is indistinguishable from the rest of the file -system. Disks are usually mounted by a command in one of the system -startup files, `/etc/rc', so you need not worry about having to do it -yourself whenever you boot the system. But even ordinary users may -be allowed to mount removable hard disks and floppy disks. - -Linux requires at least one partition, which is the `root' of the -file system. You may prefer to have a separate partition for `/usr', -which contains most of the executable files, or for `/home', which -contains most of your private files. You may also wish to set aside a -partition to use for swap space, depending on the amount of memory your -PC has. You will certainly need swap space if you have less than 4 Mb -of RAM and wish to compile anything substantial. You can reserve swap -space in a file, but you need a partition big enough to hold it, and -this will probably be less efficient than having a partition devoted to -swap. - -The disk space you need for Linux is discussed in README.prepare. - -Are you going to boot Linux from the hard disk, or will you boot -from a floppy? Some boot programs place severe restrictions on where -the boot partition can be. LILO is more relaxed about this, but does -require either the Master Boot Record on your first hard disk, or the -boot record on one of the first four partitions on your first hard disk. - -If you have an extended partition with logical partitions in it, you -can have only three primary partitions containing data. - - -The `fdisk' command -------------------- - -Every operating system, whether DOS, OS/2, or Linux, should provide -its own utility for editing hard disk partition tables. At least four -of these utilities have been called `fdisk', for `Fixed DISK setup -program', where `fixed' means `not removable'. I believe the first PC -program named `fdisk' came from Microsoft in about 1985; before that -time disks were too small to divide into separate sections. - -Every operating system has its own peculiarities. Normally you -should set up a partition for the use of one operating system by using -its own `fdisk' program. Do not use the Linux `fdisk' to create -partitions for DOS or for any system other than Linux; otherwise you -may have problems. - -An `fdisk' program performs two functions: it reports how the disk is -configured, and it changes that configuration by adding or deleting -partitions. Most `fdisk' programs can also change other information in -partition tables. - -This `fdisk' for Linux operates on one hard disk at a time. If you -give the command - - fdisk - -it reports on, and is able to change, `/dev/hda', the first hard -disk. (If you have no `/dev/hda', `fdisk' uses `/dev/sda' as the -default device.) To look at or change the second hard disk, `/dev/hdb', -give the command - - fdisk /dev/hdb - -To look at or change the first SCSI disk, give the command - - fdisk /dev/sda - -There are some special forms of the `fdisk' command. One of them, -suggested by Jim Winstead, simply lists all partitions on all available -disks: - - fdisk -l (where `l' is a letter, not the digit `1') - -The option `-v' is provided to list the current version of the -`fdisk' command. Finally, there is an option `-s' which is not really -intended for interactive use. It causes fdisk to print the size of a -partition in blocks of 1024 bytes as follows: - - fdisk -s /dev/hda7 - 39934 - -Because this is intended to be used by `mkfs' and `mkswap' programs, -it does not return the size of extended partitions or of partitions -whose system type code is less than 10 (hexadecimal a). If you start -`fdisk' without using one of these special options, it responds by -asking for a command: - - Command (m for help): _ - -Each `fdisk' command consists of a single letter, which must be -followed by <RETURN> before it is obeyed. Upper and lower case are not -distinguished. Anything you type after the first character is ignored. -Give the command `m', and you should see this menu: - Command action - a toggle a bootable flag - d delete a partition - l list known partition types - m print this menu - n add a new partition - p print the partition table - q quit without saving changes - t change a partition's system id - u change display/entry units - v verify the partition table - w write table to disk and exit - x extra functionality (experts only) - - Command (m for help): _ - -The simplest commands are Print, Verify, and Quit. On a small disk, the -Print command might produce a display like this one: - - Disk /dev/hda: 5 heads, 17 sectors, 977 cylinders - Units = cylinders of 85 * 512 bytes - - Device Boot Begin Start End Blocks Id System - /dev/hda1 * 1 1 236 10021+ 1 DOS 12-bit FAT - /dev/hda2 837 837 977 5992+ 5 Extended - /dev/hda3 * 237 237 836 25500 83 Linux native - /dev/hda5 837 837 936 4249+ 82 Linux swap - /dev/hda6 942 942 977 1522 1 DOS 12-bit FAT - -There are 5 partitions reported; `/dev/hda4' does not appear because -it is not allocated. Partitions 1 and 3 are flagged as bootable. The -size of each partition is reported in 1 kilobyte blocks; hence the -primary Linux partition, partition 3, is 25 1/2 megabytes in size. The -`+' after three of the sizes warns that these partitions contain an odd -number of sectors: Linux normally allocates filespace in 1 kilobyte -blocks, so the extra sector in partition 5 is wasted. Id numbers are -reported in hexadecimal and explained in English. - -The display/entry units may be either cylinders or sectors. The -default is cylinders, but changing the units makes the print command -display the following table for the system reported above: - - Disk /dev/hda: 5 heads, 17 sectors, 977 cylinders - Units = sectors of 1 * 512 bytes - - Device Boot Begin Start End Blocks Id System - /dev/hda1 * 1 17 20059 10021+ 1 DOS 12-bit FAT - /dev/hda2 71060 71060 83044 5992+ 5 Extended - /dev/hda3 * 20060 20060 71059 25500 83 Linux native - /dev/hda5 71061 71061 79559 4249+ 82 Linux swap - /dev/hda6 79985 80001 83044 1522 1 DOS 12-bit FAT - -The start of data in both DOS partitions is 16 sectors after the -beginning of the partition: this is one reason why you should use DOS's -own `FDISK' to create DOS partitions. Changing the units to sectors -also affects the way in which the new partition command asks for the -beginning and end of a new partition. - -*Warning*: it is dangerous to create a new partition when the -display/entry units are sectors. - -The Verify command is useful because - - 1. It warns you if anything is wrong. *Always* do a Verify command - to check your work before writing any changes to disk. - - 2. It reports how many unallocated sectors there are on the disk. - -The Quit command is also useful. `fdisk' does not actually change -any data on your disk unless you give a Write command. If you are -unhappy about any changes you may have made, give the Quit command, and -your disk will remain as it was before you ran `fdisk'. You can also -interrupt `fdisk' with `CTRL-C'. - - -Deleting and adding partitions ------------------------------- - -Deleting a partition is simple. Give the Delete command by typing -`d'. `fdisk' asks: - - Partition number (1-6): _ - -Once you get this far, you must either delete a partition or -interrupt the program with `CTRL-C' (or whatever your current interrupt -character is). Note: - - 1. You may delete a nonexistent partition. You will get a warning - message. - - 2. You may delete an extended partition. This has the side effect of - deleting all partitions greater than or equal to 5. - - 3. You may delete a logical partition. In that case, all partitions - above it are renumbered at once. For example, if you delete - partition 5, then partition 6 becomes known as partition 5, and - partition 7 as partition 6. - -Adding a partition is just a bit more complicated. Give the New -command by typing `n'. `fdisk' allows you to - - 1. Create a primary partition, if there is a free slot in the primary - partition table. - - 2. Create an extended partition if there is a free slot in the - primary partition table, and if there is no extended partition. - - 3. Create a logical partition if an extended partition exists. - -If more than one of these actions is possible, you will be asked to -select Primary, Extended, or Logical, depending on what is currently -permissible. Before you create a primary or an extended partition, you -are asked what slot it is to have in the table (1-4). - -You may not add a primary or an extended partition if the selected -slot in the primary partition table is already occupied: in that case -you simply return to the main menu. You are not allowed to add a new -primary partition unless there are sectors available outside the -extended partition. You are not allowed to add a new logical partition -unless there are sectors available inside the extended partition. - -If space is available, you are prompted for the first cylinder: - - First sector ([237]-977): _ - -The limits are the lowest and the highest cylinders in which sectors -are available in the appropriate part of the disk. The square-bracketed -number is what you'll get if you simply press enter. Not all numbers in -this range are necessarily available: they may fall inside an existing -partition. If you select a cylinder which is already in use, you are -told off and prompted again for the first cylinder. After selecting the -first cylinder, you are prompted again: - - Last cylinder or +size or +sizeM or +sizeK (237-[836]): _ - -The limits are the cylinder you have chosen as the first cylinder, -and the highest cylinder which contains a legitimate upper boundary for -the new partition. The square-bracketed number is what you'll get if -you simply press enter. In other words, all numbers in the given range are -legitimate, unlike those in the first range of cylinders. You may also -specify the size of a partition in megabytes, kilobytes, or in the -current units (cylinders or sectors). A plus sign `+' indicates that -your answer is a size rather than a boundary, and the suffix `m' or `k' -(upper or lower case) indicates that the size is not given in units of -sectors or cyliners, but in megabytes or kilobytes respectively. Thus -possible answers to the last cylinder request above are - -700 - Make cylinder 700 the last cylinder in the partition. - -+300 - Make cylinder 237 + 300 = 537 the last cylinder in the partition. - -+15m - Make the partition at least 15 megabytes in size. - -+12500k - Make the partition at least 12,500 kilobytes in size. - -If you specify a size which is too large or an end which is out of -range, fdisk complains and repeats the prompt. - -Adding or deleting partitions has no effect unless you subsequently -give the Write command. Please remember to give the Verify command -first, just before giving the Write command: this is a safety -precaution. After giving the Write command, you will see this message: - - The partition table has been altered! - Calling ioctl() to re-read partition table. - Syncing disks. - -If there are no further messages, the kernel has successfully copied -the information from the partition table into its own internal table. -But sometimes you will see a message like this one: - - Re-read table failed with error 16: Device or resource busy. - Reboot your system to ensure the partition table is updated. - -In this case, depending on what you have changed in the partition -table, it may be dangerous to continue working without rebooting, -since you may lose or corrupt your data. - - -Here are some important things to note: - - 1. Before you reboot, you *may* run `fdisk' again, either to manage - another disk, or to make additional changes to the same disk, or - just to check that the changes have been made as you expected. - This is true even after you receive the message warning you to - reboot. - - 2. It is not a good idea to run any of the programs `mkfs', `mkswap', - `mount', or `swapon' if you have received the warning message but - have not rebooted. In this case it is dangerous to run any program, - but these in particular may cause serious damage to the data on your - disk, including the partition tables themselves. - - -Active flags and system types ------------------------------ - -The active flag is a bit in the partition table entry which marks a -partition as bootable. This is important to some primary boot sector -programs, which will not boot from an unflagged partition. Other such -programs do not allow more than one partition to be flagged. Some, -like LILO, ignore the flags completely. I prefer to flag all bootable -partitions as active so that they stand out on the menu which `fdisk' -lists. Fdisk prints a star after the name of a partition's device file -if its active flag is set. - -The Active command changes, or toggles, a partition's active flag. -Give the Active command, and select a partition by number. If it was -marked inactive, it will be flagged as active; if it was flagged as -active, it will be marked inactive. You may set the active flag on an -extended or logical partition, though the meaning of such a flag is by -no means clear. This can be used to install LILO as a secondary boot -loader to boot a Linux which lives on a second hard disk. - -The Type command changes the ID number which describes what type a -partition is. `fdisk' currently recognises 30 system IDs, in the sense -that it prints a string for each of them, but it allows you to change -any system ID to any other, with the following exceptions: you may not -change any partition to or from the type Extended, and you may not -change a partition whose type is Empty (0) to any other type. You may, -however, change the type of any data partition to 0, which is -equivalent to deleting it. - -The new system ID or type code is a hexadecimal number. There are -two ways of listing the numbers which `fdisk' recognises: use the List -command, which prints the list, or use the Type command, which, when it -prompts you for the code, says - - Hex code (type L to list codes): _ - -where the upper case `L' is used for clarity. The codes printed are: -Some of these numbers are a trifle uncertain. By default `fdisk' uses -a type of 83. It used to use 81, the type code used by the MINIX -`fdisk'. It seemed prudent to change the default since (a) many Linux -`minix' file systems are no longer compatible with MINIX, (b) the ext2 -file system, a native Linux file system, is fairly stable, as is the -Xia file system, and (c) the number 81 causes problems with DR-DOS. -Linux does not usually care what values you use for type codes, but -other systems, in particular DOS, OS/2, and DR-DOS, may. - -The value of 82 for Linux swap partitions is my own invention, and -is intended to give some recognisable distinction to the partitions -when the values are displayed in hexadecimal. - -New active flags and new system type codes are not written to the -disk until you exit from `fdisk' with the Write command, as described -above, in the section on deleting and adding partitions. - - -Extra commands for experts --------------------------- - -The eXtra command `x' puts `fdisk' into `expert' mode, in which a -slightly different set of commands is available. The Active, Delete, -List, New, Type, Verify, and `eXpert' commands are not available in -expert mode. The commands Write and Quit are available as in ordinary -mode, the Print command is available, but produces output in a slightly -different format, and of course the Menu command prints the expert -menu. There are several new commands. - - 1. The Return command brings you back to the main menu. - - 2. The Extended command prints the list of table entries which point - to other tables. Ordinary users do not need this information. - The data is shown as it is stored. The same format is used for - the expert Print command. - - 3. The dangerous Begin command allows you to move the start of data - in a partition away from its beginning. Other systems create - partitions with this format, and it is sometimes useful to be able - to reproduce it. - - 4. The slightly dangerous Cylinders command allows you to change the - available number of cylinders. For SCSI disk owners, note that we - require not the actual number of physical cylinders, but the - number of logical cylinders used by DOS and other operating - systems. - - 5. The extremely dangerous Heads and Sectors commands allow you to - change the number of heads and sectors. It should not be - necessary to use these commands unless you have a SCSI disk, whose - geometry Linux is not always able to determine. SCSI disk owners - note that we need not the actual number of heads or of sectors per - track, but the number believed to exist by DOS and other operating - systems. *Warning*: If you set either of these numbers to a bad - value, you may lose all data on your disk. - -Always, after giving any of the commands Begin, Cylinder, Heads, or -Sectors, you should Return to the main menu and give the Verify command. - - -Warnings for `fdisk' users --------------------------- - -In general, you should not use this `fdisk' program to create -partitions for other operating systems, only for Linux. Nor should you -use `fdisk' commands from other operating systems to create partitions -for Linux. - -DR-DOS 5.0 and 6.0 are reported to have difficulties with partition -ID codes of 80 or more. The Linux `fdisk' used to set the system type -of new partitions to hexadecimal 81. DR-DOS seems to confuse this with -hexadecimal 1, a DOS code. The values 82 for swap and 83 for file -systems should not cause problems with DR-DOS. If they do, you may use -the `fdisk' command `t' to change the system code of any Linux -partitions to some number less than hexadecimal 80; I suggest 42 and 43 -for the moment. - -Partitioning a hard disk may destroy data which is on that disk if you -are not careful. Go slowly, write down a description of the partition -tables before you changed them, and always verify before you write. - -Most operating systems and utilities expect that all partitions begin and -end at cylinder boundaries. This version of `fdisk' does so by default, -but you can use it to create partitions which begin or end anywhere. -This does not normally affect Linux, but it is very dangerous, as other -operating systems (including DOS) may try to `correct' the partition -boundaries. - -It is dangerous to create a new partition when the display/entry -units are sectors. - -The Verify command warns you if anything is wrong. *Always* give a -Verify command before writing any changes to disk. - -If you set the disk geometry (tracks per cylinder, or sectors per -track) to an incorrect value, you may lose all data on your disk. diff --git a/disk-utils/cfdisk.8 b/disk-utils/cfdisk.8 deleted file mode 100644 index c7ac94171..000000000 --- a/disk-utils/cfdisk.8 +++ /dev/null @@ -1,403 +0,0 @@ -.\" cfdisk.8 -- man page for cfdisk -.\" Copyright 1994 Kevin E. Martin (martin@cs.unc.edu) -.\" -.\" Permission is granted to make and distribute verbatim copies of this -.\" manual provided the copyright notice and this permission notice are -.\" preserved on all copies. -.\" -.\" Permission is granted to copy and distribute modified versions of this -.\" manual under the conditions for verbatim copying, provided that the -.\" entire resulting derived work is distributed under the terms of a -.\" permission notice identical to this one. -.\" -.\" " for hilit mode -.TH CFDISK 8 "3 June 1995" "The BOGUS Linux Release" "Linux Programmer's Manual" -.SH NAME -cfdisk \- Curses based disk partition table manipulator for Linux -.SH SYNOPSIS -.BI "cfdisk [ \-avz ] [ \-c " cylinders " ] [ \-h " heads " ]" -.BI "[ \-s " sectors-per-track " ] [ -P " opt " ] [ " device " ]" -.SH DESCRIPTION -.B cfdisk -is a curses based program for partitioning a hard disk drive. The -.I device -can be any one of the following: -.sp -.nf -.RS -/dev/hda [default] -/dev/hdb -/dev/sda -/dev/sdb -/dev/sdc -/dev/sdd -.RE -.fi - -.B cfdisk -first tries to read the geometry of the hard disk. If it fails, an -error message is displayed and -.B cfdisk -exits. This should only happen when partitioning a SCSI drive on an -adapter without a BIOS. To correct this problem, you can set the -.IR cylinders ", " heads " and " sectors-per-track -on the command line. Next, -.B cfdisk -tries to read the current partition table from the disk drive. If it -is unable to figure out the partition table, an error is displayed and -the program will exit. This might also be caused by incorrect -geometry information, and can be overridden on the command line. -Another way around this problem is with the -.B \-z -option. This will ignore the partition table on the disk. - -The main display is composed of four sections, from top to bottom: the -header, the partitions, the command line and a warning line. The -header contains the program name and version number followed by the -disk drive and its geometry. The partitions section always displays -the current partition table. The command line is the place where -commands and text are entered. The available commands are usually -displayed in brackets. The warning line is usually empty except when -there is important information to be displayed. The current partition -is highlighted with reverse video (or an arrow if the -.B \-a -option is given). All partition specific commands apply to the -current partition. - -The format of the partition table in the partitions section is, from -left to right: Name, Flags, Partition Type, Filesystem Type and Size. -The name is the partition device name. The flags can be -.IR Boot , -which designates a bootable partition or -.IR NC , -which stands for "Not Compatible with DOS or OS/2". DOS, OS/2 and -possibly other operating systems require the first sector of the first -partition on the disk and all logical partitions to begin on the -second head. This wastes the second through the last sector of the -first track of the first head (the first sector is taken by the -partition table itself). -.B cfdisk -allows you to recover these "lost" sectors with the maximize command -.RB ( m ). -.I Note: -.BR fdisk (8) -and some early versions of DOS create all partitions with the number -of sectors already maximized. For more information, see the maximize -command below. The partition type can be one of -.IR Primary " or " Logical . -For unallocated space on the drive, the partition type can also be -.IR Pri/Log , -or empty (if the space is unusable). The filesystem type section -displays the name of the filesystem used on the partition, if known. -If it is unknown, then -.I Unknown -and the hex value of the filesystem type are displayed. A special -case occurs when there are sections of the disk drive that cannot be -used (because all of the primary partitions are used). When this is -detected, the filesystem type is displayed as -.IR Unusable . -The size field displays the size of the partition in megabytes (by -default). It can also display the size in sectors and cylinders (see -the change units command below). If an asterisks -.RB ( * ) -appears after the size, this means that the partition is not aligned -on cylinder boundaries. -.SH "DOS 6.x WARNING" - -The DOS 6.x FORMAT command looks for some information in the first -sector of the data area of the partition, and treats this information -as more reliable than the information in the partition table. DOS -FORMAT expects DOS FDISK to clear the first 512 bytes of the data area -of a partition whenever a size change occurs. DOS FORMAT will look at -this extra information even if the /U flag is given -- we consider -this a bug in DOS FORMAT and DOS FDISK. - -The bottom line is that if you use cfdisk or fdisk to change the size of a -DOS partition table entry, then you must also use -.B dd -to zero the first 512 bytes of that partition before using DOS FORMAT to -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. 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 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. - -.SH COMMANDS -.B cfdisk -commands can be entered by pressing the desired key (pressing -.I Enter -after the command is not necessary). Here is a list of the available -commands: -.TP -.B b -Toggle bootable flag of the current partition. This allows you to -select which primary partition is bootable on the drive. -.TP -.B d -Delete the current partition. This will convert the current partition -into free space and merge it with any free space immediately -surrounding the current partition. A partition already marked as free -space or marked as unusable cannot be deleted. -.TP -.B g -Change the disk geometry (cylinders, heads, or sectors-per-track). -.B WARNING: -This option should only be used by people who know what they are -doing. A command line option is also available to change the disk -geometry. While at the change disk geometry command line, you can -choose to change cylinders -.RB ( c ), -heads -.RB ( h ), -and sectors per track -.RB ( s ). -The default value will be printed at the prompt which you can accept -by simply pressing the -.I Enter -key, or you can exit without changes by pressing the -.I ESC -key. If you want to change the default value, simply enter the -desired value and press -.IR Enter . -The altered disk parameter values do not take effect until you return -the main menu (by pressing -.IR Enter " or " ESC -at the change disk geometry command line. If you change the geometry -such that the disk appears larger, the extra sectors are added at the -end of the disk as free space. If the disk appears smaller, the -partitions that are beyond the new last sector are deleted and the -last partition on the drive (or the free space at the end of the -drive) is made to end at the new last sector. -.TP -.B h -Print the help screen. -.TP -.B m -Maximize disk usage of the current partition. This command will -recover the the unused space between the partition table and the -beginning of the partition, but at the cost of making the partition -incompatible with DOS, OS/2 and possibly other operating systems. -This option will toggle between maximal disk usage and DOS, OS/2, -etc. compatible disk usage. The default when creating a partition is -to create DOS, OS/2, etc. compatible partitions. -.TP -.B n -Create new partition from free space. If the partition type is -.IR Primary " or " Logical , -a partition of that type will be created, but if the partition type is -.IR Pri/Log , -you will be prompted for the type you want to create. Be aware that -(1) there are only four slots available for primary partitions and (2) -since there can be only one extended partition, which contains all of -the logical drives, all of the logical drives must be contiguous (with -no intervening primary partition). -.B cfdisk -next prompts you for the size of the partition you want to create. -The default size, equal to the entire free space of the current -partition, is display in megabytes. You can either press the -.I Enter -key to accept the default size or enter a different size at the -prompt. -.B cfdisk -accepts size entries in megabytes -.RB ( M ) -[default], kilobytes -.RB ( K ), -cylinders -.RB ( C ) -and sectors -.RB ( S ) -by entering the number immediately followed by one of -.RB ( M ", " K ", " C " or " S ). -If the partition fills the free space available, the partition is -created and you are returned to the main command line. Otherwise, the -partition can be created at the beginning or the end of the free -space, and -.B cfdisk -will ask you to choose where to place the partition. After the -partition is created, -.B cfdisk -automatically adjusts the other partition's partition types if all of -the primary partitions are used. -.TP -.B p -Print the partition table to the screen or to a file. There are -several different formats for the partition that you can choose from: -.sp -.RS -.TP -.B r -Raw data format (exactly what would be written to disk) -.TP -.B s -Partition table in sector order format -.TP -.B t -Partition table in raw format -.RE - -.RS -The -.I raw data format -will print the sectors that would be written to disk if a -.BR w rite -command is selected. First, the primary partition table is printed, -followed by the partition tables associated with each logical -partition. The data is printed in hex byte by byte with 16 bytes per -line. - -The -.I partition table in sector order format -will print the partition table ordered by sector number. The fields, -from left to right, are the number of the partition, the partition -type, the first sector, the last sector, the offset from the first -sector of the partition to the start of the data, the length of the -partition, the filesystem type (with the hex value in parenthesis), -and the flags (with the hex value in parenthesis). In addition to the -primary and logical partitions, free and unusable space is printed and -the extended partition is printed before the first logical partition. - -If a partition does not start or end on a cylinder boundary or if the -partition length is not divisible by the cylinder size, an asterisks -.RB ( * ) -is printed after the non-aligned sector number/count. This usually -indicates that a partition was created by an operating system that -either does not align partitions to cylinder boundaries or that used -different disk geometry information. If you know the disk geometry of -the other operating system, you could enter the geometry information -with the change geometry command -.RB ( g ). - -For the first partition on the disk and for all logical partitions, if -the offset from the beginning of the partition is not equal to the -number of sectors per track (i.e., the data does not start on the -first head), a number sign -.RB ( # ) -is printed after the offset. For the remaining partitions, if the -offset is not zero, a number sign will be printed after the offset. -This corresponds to the -.I NC -flag in the partitions section of the main display. - -The -.I partition table in raw format -will print the partition table ordered by partition number. It will -leave out all free and unusable space. The fields, from left to -right, are the number of the partition, the flags (in hex), the -starting head, sector and cylinder, the filesystem ID (in hex), the -ending head, sector and cylinder, the starting sector in the partition -and the number of sectors in the partition. The information in this -table can be directly translated to the -.IR "raw data format" . - -The partition table entries only have 10 bits available to represent -the starting and ending cylinders. Thus, when the absolute starting -(ending) sector number is on a cylinder greater than 1023, the maximal -values for starting (ending) head, sector and cylinder are printed. -This is the method used by OS/2, and thus fixes the problems -associated with OS/2's fdisk rewriting the partition table when it is -not in this format. Since Linux and OS/2 use absolute sector counts, -the values in the starting and ending head, sector and cylinder are -not used. -.RE -.TP -.B q -Quit program. This will exit the program without writing any data to -disk. -.TP -.B t -Change the filesystem type. By default, new partitions are created as -.I Linux -partitions, but since -.B cfdisk -can create partitions for other operating systems, change partition -type allows you to enter the hex value of the filesystem you desire. -A list of the know filesystem types is displayed. You can type in the -filesystem type at the prompt or accept the default filesystem type -.RI [ Linux ]. -.TP -.B u -Change units of the partition size display. It will rotate through -megabytes, sectors and cylinders. -.TP -.B W -Write partition table to disk (must enter an upper case W). Since -this might destroy data on the disk, you must either confirm or deny -the write by entering `yes' or `no'. If you enter `yes', -.B cfdisk -will write the partition table to disk and the tell the kernel to -re-read the partition table from the disk. The re-reading of the -partition table works is most cases, but I have seen it fail. Don't -panic. It will be correct after you reboot the system. In all cases, -I still recommend rebooting the system--just to be safe. -.TP -.I Up Arrow -.TP -.I Down Arrow -Move cursor to the previous or next partition. If there are more -partitions than can be displayed on a screen, you can display the next -(previous) set of partitions by moving down (up) at the last (first) -partition displayed on the screen. -.TP -.I CTRL-L -Redraws the screen. In case something goes wrong and you cannot read -anything, you can refresh the screen from the main command line. -.TP -.B ? -Print the help screen. - -.RE -All of the commands can be entered with either upper or lower case -letters (except for -.BR W rites). -When in a sub-menu or at a prompt to enter a filename, you can hit the -.I ESC -key to return to the main command line. -.SH OPTIONS -.TP -.B \-a -Use an arrow cursor instead of reverse video for highlighting the -current partition. -.TP -.B \-v -Print the version number and copyright. -.TP -.B \-z -Start with zeroed partition table. This option is useful when you -want to repartition your entire disk. -.I Note: -this option does not zero the partition table on the disk; rather, it -simply starts the program without reading the existing partition -table. -.TP -.BI \-c " cylinders" -.TP -.BI \-h " heads" -.TP -.BI \-s " sectors-per-track" -Override the number of cylinders, heads and sectors per track read -from the BIOS. If your BIOS or adapter does not supply this -information or if it supplies incorrect information, use these options -to set the disk geometry values. -.TP -.BI \-P " opt" -Prints the partition table in specified formats. -.I opt -can be one or more of "r", "s" or "t". See the -.BR p rint -command (above) for more information on the print formats. -.SH "SEE ALSO" -fdisk(8) -.SH BUGS -The current version does not support multiple disks (future addition). -.SH AUTHOR -Kevin E. Martin (martin@cs.unc.edu) diff --git a/disk-utils/cfdisk.8.bak b/disk-utils/cfdisk.8.bak deleted file mode 100644 index cb23149fb..000000000 --- a/disk-utils/cfdisk.8.bak +++ /dev/null @@ -1,407 +0,0 @@ -.\" cfdisk.8 -- man page for cfdisk -.\" Copyright 1994 Kevin E. Martin (martin@cs.unc.edu) -.\" -.\" Permission is granted to make and distribute verbatim copies of this -.\" manual provided the copyright notice and this permission notice are -.\" preserved on all copies. -.\" -.\" Permission is granted to copy and distribute modified versions of this -.\" manual under the conditions for verbatim copying, provided that the -.\" entire resulting derived work is distributed under the terms of a -.\" permission notice identical to this one. -.\" -.\" " for hilit mode -.TH CFDISK 8 "25 April 1994" "The BOGUS Linux Release" "Linux Programmer's Manual" -.SH NAME -cfdisk \- Curses based disk partition table manipulator for Linux -.SH SYNOPSIS -.BI "cfdisk [ \-avz ] [ \-c " cylinders " ] [ \-h " heads " ]" -.BI "[ \-s " sectors-per-track " ] [ -P " opt " ] [ " device " ]" -.SH DESCRIPTION -.B cfdisk -is a curses based program for partitioning a hard disk drive. The -.I device -can be any one of the following: -.sp -.nf -.RS -/dev/hda [default] -/dev/hdb -/dev/sda -/dev/sdb -/dev/sdc -/dev/sdd -.RE -.fi - -.B cfdisk -first tries to read the geometry of the hard disk. If it fails, an -error message is displayed and -.B cfdisk -exits. This should only happen when partitioning a SCSI drive on an -adapter without a BIOS. To correct this problem, you can set the -.IR cylinders ", " heads " and " sectors-per-track -on the command line. Next, -.B cfdisk -tries to read the current partition table from the disk drive. If it -is unable to figure out the partition table, an error is displayed and -the program will exit. This might also be caused by incorrect -geometry information, and can be overridden on the command line. -Another way around this problem is with the -.B \-z -option. This will ignore the partition table on the disk. - -The main display is composed of four sections, from top to bottom: the -header, the partitions, the command line and a warning line. The -header contains the program name and version number followed by the -disk drive and its geometry. The partitions section always displays -the current partition table. The command line is the place where -commands and text are entered. The available commands are usually -displayed in brackets. The warning line is usually empty except when -there is important information to be displayed. The current partition -is highlighted with reverse video (or an arrow if the -.B \-a -option is given). All partition specific commands apply to the -current partition. - -The format of the partition table in the partitions section is, from -left to right: Name, Flags, Partition Type, Filesystem Type and Size. -The name is the partition device name. The flags can be -.IR Boot , -which designates a bootable partition or -.IR NC , -which stands for "Not Compatible with DOS or OS/2". DOS, OS/2 and -possibly other operating systems require the first sector of the first -partition on the disk and all logical partitions to begin on the -second head. This wastes the second through the last sector of the -first track of the first head (the first sector is taken by the -partition table itself). -.B cfdisk -allows you to recover these "lost" sectors with the maximize command -.RB ( m ). -.I Note: -.BR fdisk (8) -and some early versions of DOS create all partitions with the number -of sectors already maximized. For more information, see the maximize -command below. The partition type can be one of -.IR Primary " or " Logical . -For unallocated space on the drive, the partition type can also be -.IR Pri/Log , -or empty (if the space is unusable). The filesystem type section -displays the name of the filesystem used on the partition, if known. -If it is unknown, then -.I Unknown -and the hex value of the filesystem type are displayed. A special -case occurs when there are sections of the disk drive that cannot be -used (because all of the primary partitions are used). When this is -detected, the filesystem type is displayed as -.IR Unusable . -The size field displays the size of the partition in megabytes (by -default). It can also display the size in sectors and cylinders (see -the change units command below). If an asterisks -.RB ( * ) -appears after the size, this means that the partition is not aligned -on cylinder boundaries. -.SH "DOS 6.x WARNING" - -The DOS 6.x FORMAT command looks for some information in the first -sector of the data area of the partition, and treats this information -as more reliable than the information in the partition table. DOS -FORMAT expects DOS FDISK to clear the first 512 bytes of the data area -of a partition whenever a size change occurs. DOS FORMAT will look at -this extra information even if the /U flag is given -- we consider -this a bug in DOS FORMAT and DOS FDISK. - -The bottom line is that if you use cfdisk or fdisk to change the size of a -DOS partition table entry, then you must also use -.B dd -to zero the first 512 bytes of that partition before using DOS FORMAT to -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. - -.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 -program. For example, you should make DOS partitions with the DOS FDISK -program and Linux partitions with the Linux fdisk or Linux cfdisk program. - -.SH COMMANDS -.B cfdisk -commands can be entered by pressing the desired key (pressing -.I Enter -after the command is not necessary). Here is a list of the available -commands: -.TP -.B b -Toggle bootable flag of the current partition. This allows you to -select which primary partition is bootable on the drive. -.TP -.B d -Delete the current partition. This will convert the current partition -into free space and merge it with any free space immediately -surrounding the current partition. A partition already marked as free -space or marked as unusable cannot be deleted. -.TP -.B g -Change the disk geometry (cylinders, heads, or sectors-per-track). -.B WARNING: -This option should only be used by people who know what they are -doing. A command line option is also available to change the disk -geometry. While at the change disk geometry command line, you can -choose to change cylinders -.RB ( c ), -heads -.RB ( h ), -and sectors per track -.RB ( s ). -The default value will be printed at the prompt which you can accept -by simply pressing the -.I Enter -key, or you can exit without changes by pressing the -.I ESC -key. If you want to change the default value, simply enter the -desired value and press -.IR Enter . -The altered disk parameter values do not take effect until you return -the main menu (by pressing -.IR Enter " or " ESC -at the change disk geometry command line. If you change the geometry -such that the disk appears larger, the extra sectors are added at the -end of the disk as free space. If the disk appears smaller, the -partitions that are beyond the new last sector are deleted and the -last partition on the drive (or the free space at the end of the -drive) is made to end at the new last sector. -.TP -.B h -Print the help screen. -.TP -.B m -Maximize disk usage of the current partition. This command will -recover the the unused space between the partition table and the -beginning of the partition, but at the cost of making the partition -incompatible with DOS, OS/2 and possibly other operating systems. -This option will toggle between maximal disk usage and DOS, OS/2, -etc. compatible disk usage. The default when creating a partition is -to create DOS, OS/2, etc. compatible partitions. -.TP -.B n -Create new partition from free space. If the partition type is -.IR Primary " or " Logical , -a partition of that type will be created, but if the partition type is -.IR Pri/Log , -you will be prompted for the type you want to create. Be aware that -(1) there are only four slots available for primary partitions and (2) -since there can be only one extended partition, which contains all of -the logical drives, all of the logical drives must be contiguous (with -no intervening primary partition). -.B cfdisk -next prompts you for the size of the partition you want to create. -The default size, equal to the entire free space of the current -partition, is display in megabytes. You can either press the -.I Enter -key to accept the default size or enter a different size at the -prompt. -.B cfdisk -accepts size entries in megabytes -.RB ( M ) -[default], kilobytes -.RB ( K ), -cylinders -.RB ( C ) -and sectors -.RB ( S ) -by entering the number immediately followed by one of -.RB ( M ", " K ", " C " or " S ). -If the partition fills the free space available, the partition is -created and you are returned to the main command line. Otherwise, the -partition can be created at the beginning or the end of the free -space, and -.B cfdisk -will ask you to choose where to place the partition. After the -partition is created, -.B cfdisk -automatically adjusts the other partition's partition types if all of -the primary partitions are used. -.TP -.B p -Print the partition table to the screen or to a file. There are -several different formats for the partition that you can choose from: -.sp -.RS -.TP -.B r -Raw data format (exactly what would be written to disk) -.TP -.B s -Partition table in sector order format -.TP -.B t -Partition table in raw format -.RE - -.RS -The -.I raw data format -will print the sectors that would be written to disk if a -.BR w rite -command is selected. First, the primary partition table is printed, -followed by the partition tables associated with each logical -partition. The data is printed in hex byte by byte with 16 bytes per -line. - -The -.I partition table in sector order format -will print the partition table ordered by sector number. The fields, -from left to right, are the number of the partition, the partition -type, the first sector, the last sector, the offset from the first -sector of the partition to the start of the data, the length of the -partition, the filesystem type (with the hex value in parenthesis), -and the flags (with the hex value in parenthesis). In addition to the -primary and logical partitions, free and unusable space is printed and -the extended partition is printed before the first logical partition. - -If a partition does not start or end on a cylinder boundary or if the -partition length is not divisible by the cylinder size, an asterisks -.RB ( * ) -is printed after the non-aligned sector number/count. This usually -indicates that a partition was created by an operating system that -either does not align partitions to cylinder boundaries or that used -different disk geometry information. If you know the disk geometry of -the other operating system, you could enter the geometry information -with the change geometry command -.RB ( g ). - -For the first partition on the disk and for all logical partitions, if -the offset from the beginning of the partition is not equal to the -number of sectors per track (i.e., the data does not start on the -first head), a number sign -.RB ( # ) -is printed after the offset. For the remaining partitions, if the -offset is not zero, a number sign will be printed after the offset. -This corresponds to the -.I NC -flag in the partitions section of the main display. - -The -.I partition table in raw format -will print the partition table ordered by partition number. It will -leave out all free and unusable space. The fields, from left to -right, are the number of the partition, the flags (in hex), the -starting head, sector and cylinder, the filesystem ID (in hex), the -ending head, sector and cylinder, the starting sector in the partition -and the number of sectors in the partition. The information in this -table can be directly translated to the -.IR "raw data format" . - -The partition table entries only have 10 bits available to represent -the starting and ending cylinders. Thus, when the absolute starting -(ending) sector number is on a cylinder greater than 1023, the maximal -values for starting (ending) head, sector and cylinder are printed. -This is the method used by OS/2, and thus fixes the problems -associated with OS/2's fdisk rewriting the partition table when it is -not in this format. Since Linux and OS/2 use absolute sector counts, -the values in the starting and ending head, sector and cylinder are -not used. -.RE -.TP -.B q -Quit program. This will exit the program without writing any data to -disk. -.TP -.B t -Change the filesystem type. By default, new partitions are created as -.I Linux -partitions, but since -.B cfdisk -can create partitions for other operating systems, change partition -type allows you to enter the hex value of the filesystem you desire. -A list of the know filesystem types is displayed. You can type in the -filesystem type at the prompt or accept the default filesystem type -.RI [ Linux ]. -.TP -.B u -Change units of the partition size display. It will rotate through -megabytes, sectors and cylinders. -.TP -.B W -Write partition table to disk (must enter an upper case W). Since -this might destroy data on the disk, you must either confirm or deny -the write by entering `yes' or `no'. If you enter `yes', -.B cfdisk -will write the partition table to disk and the tell the kernel to -re-read the partition table from the disk. The re-reading of the -partition table works is most cases, but I have seen it fail. Don't -panic. It will be correct after you reboot the system. In all cases, -I still recommend rebooting the system--just to be safe. -.TP -.I Up Arrow -.TP -.I Down Arrow -Move cursor to the previous or next partition. If there are more -partitions than can be displayed on a screen, you can display the next -(previous) set of partitions by moving down (up) at the last (first) -partition displayed on the screen. -.TP -.I CTRL-L -Redraws the screen. In case something goes wrong and you cannot read -anything, you can refresh the screen from the main command line. -.TP -.B ? -Print the help screen. - -.RE -All of the commands can be entered with either upper or lower case -letters (except for -.BR W rites). -When in a sub-menu or at a prompt to enter a filename, you can hit the -.I ESC -key to return to the main command line. -.SH OPTIONS -.TP -.B \-a -Use an arrow cursor instead of reverse video for highlighting the -current partition. -.TP -.B \-v -Print the version number and copyright. -.TP -.B \-z -Start with zeroed partition table. This option is useful when you -want to repartition your entire disk. -.I Note: -this option does not zero the partition table on the disk; rather, it -simply starts the program without reading the existing partition -table. -.TP -.BI \-c " cylinders" -.TP -.BI \-h " heads" -.TP -.BI \-s " sectors-per-track" -Override the number of cylinders, heads and sectors per track read -from the BIOS. If your BIOS or adapter does not supply this -information or if it supplies incorrect information, use these options -to set the disk geometry values. -.TP -.BI \-P " opt" -Prints the partition table in specified formats. -.I opt -can be one or more of "r", "s" or "t". See the -.BR p rint -command (above) for more information on the print formats. -.SH "SEE ALSO" -fdisk(8) -.SH BUGS -The current version does not support multiple disks (future addition). -.SH AUTHOR -Kevin E. Martin (martin@cs.unc.edu) diff --git a/disk-utils/cfdisk.c b/disk-utils/cfdisk.c deleted file mode 100644 index f0b5482f1..000000000 --- a/disk-utils/cfdisk.c +++ /dev/null @@ -1,2560 +0,0 @@ -/**************************************************************************** - * - * CFDISK - * - * cfdisk is a curses based disk drive partitioning program that can - * create partitions for a wide variety of operating systems including - * Linux, MS-DOS and OS/2. - * - * cfdisk was inspired by the fdisk program, by A. V. Le Blanc - * (LeBlanc@mcc.ac.uk). - * - * Copyright (C) 1994 Kevin E. Martin (martin@cs.unc.edu) - * - * cfdisk is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * cfdisk is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with cfdisk; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Created: Fri Jan 28 22:46:58 1994, martin@cs.unc.edu - * >2GB patches: Sat Feb 11 09:08:10 1995, faith@cs.unc.edu - * Prettier menus: Sat Feb 11 09:08:25 1995, Janne Kukonlehto - * <jtklehto@stekt.oulu.fi> - * Versions 0.8e-l: aeb@cwi.nl - * Recognition of NTFS / HPFS difference inspired by patches - * from Marty Leisner <leisner@sdsp.mc.xerox.com> - * - ****************************************************************************/ - -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <unistd.h> -#include <ctype.h> -#include <errno.h> -#include <getopt.h> -#include <fcntl.h> -#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 */ - -#if defined(__GNUC__) || defined(HAS_LONG_LONG) -typedef long long ext2_loff_t; -#else -typedef long ext2_loff_t; -#endif - -extern ext2_loff_t ext2_llseek(unsigned int fd, ext2_loff_t offset, - unsigned int origin); - -#define VERSION "0.8l" - -#define DEFAULT_DEVICE "/dev/hda" -#define ALTERNATE_DEVICE "/dev/sda" - -#define LINE_LENGTH 80 -#define MAXIMUM_PARTS 60 - -#define SECTOR_SIZE 512 - -#define MAX_CYLINDERS 65535 -#define MAX_HEADS 255 -#define MAX_SECTORS 63 - -#define ACTIVE_FLAG 0x80 -#define PART_TABLE_FLAG 0xAA55 - -#define UNUSABLE -1 -#define FREE_SPACE 0x00 -#define DOS_EXTENDED 0x05 -#define OS2_OR_NTFS 0x07 -#define WIN98_EXTENDED 0x0f -#define LINUX_EXTENDED 0x85 -#define LINUX_MINIX 0x81 -#define LINUX_SWAP 0x82 -#define LINUX 0x83 - -#define ADD_EXISTS "This partition is already in use" -#define ADD_UNUSABLE "This partition is unusable" -#define DEL_EMPTY "Cannot delete an empty partition" -#define ID_EMPTY "Cannot change FS Type to empty" -#define ID_EXT "Cannot change FS Type to extended" -#define NEED_EXT "No room to create the extended partition" -#define NO_FLAGS "Cannot make this partition bootable" -#define NO_MORE_PARTS "No more partitions" -#define PRINT_OPEN_ERR "Cannot open file '%s'" -#define TWO_EXTENDEDS "Cannot create logical drive here -- would create two extended partitions" -#define TYPE_EMPTY "Cannot change the type of an empty partition" -#define BAD_COMMAND "Illegal command" -#define MAX_UNMAXABLE "Cannot maximize this partition" -#define BAD_OPEN "Cannot open disk drive" -#define BAD_SEEK "Cannot seek on disk drive" -#define BAD_READ "Cannot read disk drive" -#define BAD_WRITE "Cannot write disk drive" -#define BAD_GEOMETRY "Cannot read disk drive geometry" -#define BAD_PRIMARY "Bad primary partition" -#define BAD_LOGICAL "Bad logical partition" -#define BAD_CYLINDERS "Illegal cylinders value" -#define BAD_HEADS "Illegal heads value" -#define BAD_SECTORS "Illegal sectors value" -#define READONLY_WARN "Opened disk read-only - you have no permission to write" -#define WRITE_WARN "Warning!! This may destroy data on your disk!" -#define YES_NO "Please enter `yes' or `no'" -#define WRITING_PART "Writing partition table to disk..." -#define YES_WRITE "Wrote partition table to disk" -#define NO_WRITE "Did not write partition table to disk" -#define RRPART_FAILED "Wrote partition table, but re-read table failed. Reboot to update table." - -#define PRI_OR_LOG -1 -#define PRIMARY -2 -#define LOGICAL -3 - -#define COL_ID_WIDTH 20 - -#define CR '\015' -#define ESC '\033' -#define DEL '\177' -#define BELL '\007' -/* '\014' == ^L */ -#define REDRAWKEY '\014' - -/* Display units */ -#define MEGABYTES 1 -#define SECTORS 2 -#define CYLINDERS 3 - -#define GS_DEFAULT -1 -#define GS_ESCAPE -2 - -#define PRINT_RAW_TABLE 1 -#define PRINT_SECTOR_TABLE 2 -#define PRINT_PARTITION_TABLE 4 - -#define IS_PRIMARY(p) ((p) >= 0 && (p) < 4) -#define IS_LOGICAL(p) ((p) > 3) - -#define round_int(d) ((double)((int)(d+0.5))) -#define ceiling(d) ((double)(((d) != (int)(d)) ? (int)(d+1.0) : (int)(d))) - -#define set_hsc(h,s,c,sector) \ -{ \ - s = sector % sectors + 1; \ - sector /= sectors; \ - h = sector % heads; \ - sector /= heads; \ - c = sector & 0xFF; \ - s |= (sector >> 2) & 0xC0;\ -} - -#define is_extended(x) ((x) == DOS_EXTENDED || (x) == WIN98_EXTENDED || \ - (x) == LINUX_EXTENDED) - -#define is_dos_partition(x) ((x) == 1 || (x) == 4 || (x) == 6) -#define may_have_dos_label(x) (is_dos_partition(x) \ - || (x) == 7 || (x) == 0xb || (x) == 0xc || (x) == 0xe \ - || (x) == 0x11 || (x) == 0x14 || (x) == 0x16 || (x) == 0x17) - -#define ALIGNMENT 2 -typedef union { - struct { - unsigned char align[ALIGNMENT]; - unsigned char b[SECTOR_SIZE]; - } c; - struct { - unsigned char align[ALIGNMENT]; - unsigned char buffer[0x1BE]; - struct partition part[4]; - unsigned short flag; - } p; -} partition_table; - -typedef struct { - int first_sector; /* first sector in partition */ - int last_sector; /* last sector in partition */ - int offset; /* offset from first sector to start of data */ - int flags; /* active == 0x80 */ - int id; /* filesystem type */ - int num; /* number of partition -- primary vs. logical */ -#define LABELSZ 16 - char volume_label[LABELSZ+1]; -#define OSTYPESZ 8 - char ostype[OSTYPESZ+1]; -#define FSTYPESZ 8 - char fstype[FSTYPESZ+1]; -} partition_info; - -char *disk_device = DEFAULT_DEVICE; -int fd; -int heads = 0; -int sectors = 0; -int cylinders = 0; -int changed = FALSE; -int opened = FALSE; -int opentype; -int curses_started = 0; - -partition_info p_info[MAXIMUM_PARTS]; -partition_info ext_info; -int num_parts = 0; - -int logical = 0; -int logical_sectors[MAXIMUM_PARTS]; - -__sighandler_t old_SIGINT, old_SIGTERM; - -int arrow_cursor = FALSE; -int display_units = MEGABYTES; -int zero_table = FALSE; -int print_only = 0; - -/* Curses screen information */ -int cur_part = 0; -int warning_last_time = FALSE; -int defined = FALSE; -int COLUMNS = 80; -int NUM_ON_SCREEN = 1; - -/* Y coordinates */ -int HEADER_START = 0; -int DISK_TABLE_START = 5; -int WARNING_START = 23; -int COMMAND_LINE_Y = 21; - -/* X coordinates */ -int NAME_START = 4; -int FLAGS_START = 16; -int PTYPE_START = 28; -int FSTYPE_START = 38; -int LABEL_START = 54; -int SIZE_START = 70; -int COMMAND_LINE_X = 5; - -#define NUM_PART_TYPES 256 -char *partition_type[NUM_PART_TYPES] = { - [LINUX_MINIX] = "Linux/MINIX", - [LINUX_SWAP] = "Linux Swap", - [LINUX] = "Linux", - [FREE_SPACE] = "Free Space", - [DOS_EXTENDED]= "Extended", - [LINUX_EXTENDED] = "Linux extended", - [0x01] = "DOS FAT12", - [0x02] = "XENIX root", - [0x03] = "XENIX usr", - [0x04] = "DOS FAT16", - [0x06] = "DOS FAT16 (big)", - [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)", - [0x0E] = "Win95 FAT16 (LBA)", - [0x0F] = "Win95 Extended (LBA)", - [0x11] = "Hidden DOS FAT12", - [0x14] = "Hidden DOS FAT16", - [0x16] = "Hidden DOS FAT16 (big)", - [0x17] = "Hidden OS/2 HPFS or NTFS", - [0x40] = "Venix 80286", - [0x51] = "Novell?", - [0x52] = "Microport", - [0x63] = "GNU HURD", - [0x64] = "Novell Netware 286", - [0x65] = "Novell Netware 386", - [0x75] = "PC/IX", - [0x80] = "Old MINIX", - [0x93] = "Amoeba", - [0x94] = "Amoeba BBT", - [0xA5] = "BSD/386", - [0xA6] = "OpenBSD", - [0xA7] = "NEXTSTEP", - [0xB7] = "BSDI fs", - [0xB8] = "BSDI swap", - [0xC7] = "Syrinx", - [0xDB] = "CP/M", - [0xE1] = "DOS access", - [0xE3] = "DOS R/O", - [0xF2] = "DOS secondary", - [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) - close(fd); - - if (changed) { - fprintf(stderr, "Disk has been changed.\n"); - fprintf(stderr, "Reboot the system to ensure the partition " - "table is correctly updated.\n"); - - fprintf( stderr, "\nWARNING: If you have created or modified any\n" - "DOS 6.x partitions, please see the cfdisk manual\n" - "page for additional information.\n" ); - } - - exit(ret); -} - -int get_string(char *str, int len, char *def) -{ - char c; - int i = 0; - int x, y; - int use_def = FALSE; - - getyx(stdscr, y, x); - clrtoeol(); - - str[i] = 0; - - if (def != NULL) { - mvaddstr(y, x, def); - move(y, x); - use_def = TRUE; - } - - refresh(); - while ((c = getch()) != '\n' && c != CR) { - switch (c) { - case ESC: - move(y, x); - clrtoeol(); - refresh(); - return GS_ESCAPE; - case DEL: - case '\b': - if (i > 0) { - str[--i] = 0; - mvaddch(y, x+i, ' '); - move(y, x+i); - } else if (use_def) { - clrtoeol(); - use_def = FALSE; - } else - putchar(BELL); - break; - default: - if (i < len && isprint(c)) { - mvaddch(y, x+i, c); - if (use_def) { - clrtoeol(); - use_def = FALSE; - } - str[i++] = c; - str[i] = 0; - } else - putchar(BELL); - } - refresh(); - } - - if (use_def) - return GS_DEFAULT; - else - return i; -} - -void clear_warning(void) -{ - int i; - - if (!curses_started || !warning_last_time) - return; - - move(WARNING_START,0); - for (i = 0; i < COLS; i++) - addch(' '); - - warning_last_time = FALSE; -} - -void print_warning(char *s) -{ - if (!curses_started) { - fprintf(stderr, "%s\n", s); - } else { - mvaddstr(WARNING_START, (COLS-strlen(s))/2, s); - putchar(BELL); /* CTRL-G */ - - warning_last_time = TRUE; - } -} - -void die_x(int ret); - -void fatal(char *s) -{ - char str[LINE_LENGTH]; - - if (curses_started) { - sprintf(str, "FATAL ERROR: %s", s); - mvaddstr(WARNING_START, (COLS-strlen(str))/2, str); - sprintf(str, "Press any key to exit fdisk"); - mvaddstr(WARNING_START+1, (COLS-strlen(str))/2, str); - putchar(BELL); /* CTRL-G */ - refresh(); - (void)getch(); - die_x(1); - } else { - fprintf(stderr, "FATAL ERROR: %s\n", s); - exit(1); - } -} - -void die(int dummy) -{ - die_x(0); -} - -void die_x(int ret) -{ - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); -#ifdef SLCURSES - SLsmg_gotorc(LINES-1, 0); - SLsmg_refresh(); -#else - mvcur(0, COLS-1, LINES-1, 0); -#endif - nl(); - endwin(); - printf("\n"); - fdexit(ret); -} - -void read_sector(char *buffer, int sect_num) -{ - if (ext2_llseek(fd, ((ext2_loff_t) sect_num)*SECTOR_SIZE, SEEK_SET) < 0) - fatal(BAD_SEEK); - if (read(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(BAD_READ); -} - -void write_sector(char *buffer, int sect_num) -{ - if (ext2_llseek(fd, ((ext2_loff_t) sect_num)*SECTOR_SIZE, SEEK_SET) < 0) - fatal(BAD_SEEK); - if (write(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(BAD_WRITE); -} - -void dos_copy_to_info(char *to, int tosz, char *from, int fromsz) { - int i; - - for(i=0; i<tosz && i<fromsz && isascii(from[i]); i++) - to[i] = from[i]; - to[i] = 0; -} - -void get_dos_label(int i) -{ - 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 + 1024; - if (ext2_llseek(fd, offset, SEEK_SET) == offset - && 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[EXT2LABELSZ] = 0; - strncpy(p_info[i].volume_label, label, LABELSZ); - strncpy(p_info[i].fstype, "ext2", FSTYPESZ); - } -} - -void check_part_info(void) -{ - int i, pri = 0, log = 0; - - for (i = 0; i < num_parts; i++) - if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num)) - pri++; - else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num)) - log++; - if (is_extended(ext_info.id)) - if (log > 0) - pri++; - else { - ext_info.first_sector = 0; - ext_info.last_sector = 0; - ext_info.offset = 0; - ext_info.flags = 0; - ext_info.id = FREE_SPACE; - ext_info.num = PRIMARY; - } - - if (pri >= 4) { - for (i = 0; i < num_parts; i++) - if (p_info[i].id == FREE_SPACE || p_info[i].id == UNUSABLE) - if (is_extended(ext_info.id)) - if (p_info[i].first_sector >= ext_info.first_sector && - p_info[i].last_sector <= ext_info.last_sector) { - p_info[i].id = FREE_SPACE; - p_info[i].num = LOGICAL; - } else if (i > 0 && - p_info[i-1].first_sector >= - ext_info.first_sector && - p_info[i-1].last_sector <= - ext_info.last_sector) { - p_info[i].id = FREE_SPACE; - p_info[i].num = LOGICAL; - } else if (i < num_parts-1 && - p_info[i+1].first_sector >= - ext_info.first_sector && - p_info[i+1].last_sector <= - ext_info.last_sector) { - p_info[i].id = FREE_SPACE; - p_info[i].num = LOGICAL; - } else - p_info[i].id = UNUSABLE; - else /* if (!is_extended(ext_info.id)) */ - p_info[i].id = UNUSABLE; - else /* if (p_info[i].id > 0) */ - while (0); /* Leave these alone */ - } else { /* if (pri < 4) */ - for (i = 0; i < num_parts; i++) { - if (p_info[i].id == UNUSABLE) - p_info[i].id = FREE_SPACE; - if (p_info[i].id == FREE_SPACE) - if (is_extended(ext_info.id)) - if (p_info[i].first_sector >= ext_info.first_sector && - p_info[i].last_sector <= ext_info.last_sector) - p_info[i].num = LOGICAL; - else if (i > 0 && - p_info[i-1].first_sector >= - ext_info.first_sector && - p_info[i-1].last_sector <= - ext_info.last_sector) - p_info[i].num = PRI_OR_LOG; - else if (i < num_parts-1 && - p_info[i+1].first_sector >= - ext_info.first_sector && - p_info[i+1].last_sector <= - ext_info.last_sector) - p_info[i].num = PRI_OR_LOG; - else - p_info[i].num = PRIMARY; - else /* if (!is_extended(ext_info.id)) */ - p_info[i].num = PRI_OR_LOG; - else /* if (p_info[i].id > 0) */ - while (0); /* Leave these alone */ - } - } -} - -void remove_part(int i) -{ - int p; - - for (p = i; p < num_parts; p++) - p_info[p] = p_info[p+1]; - - num_parts--; -} - -void insert_empty_part(int i, int first, int last) -{ - int p; - - for (p = num_parts; p > i; p--) - p_info[p] = p_info[p-1]; - - p_info[i].first_sector = first; - p_info[i].last_sector = last; - p_info[i].offset = 0; - p_info[i].flags = 0; - p_info[i].id = FREE_SPACE; - p_info[i].num = PRI_OR_LOG; - p_info[i].volume_label[0] = 0; - p_info[i].fstype[0] = 0; - p_info[i].ostype[0] = 0; - - num_parts++; -} - -void del_part(int i) -{ - int num = p_info[i].num; - - if (i > 0 && (p_info[i-1].id == FREE_SPACE || - p_info[i-1].id == UNUSABLE)) { - /* Merge with previous partition */ - p_info[i-1].last_sector = p_info[i].last_sector; - remove_part(i--); - } - - if (i < num_parts - 1 && (p_info[i+1].id == FREE_SPACE || - p_info[i+1].id == UNUSABLE)) { - /* Merge with next partition */ - p_info[i+1].first_sector = p_info[i].first_sector; - remove_part(i); - } - - if (i > 0) - p_info[i].first_sector = p_info[i-1].last_sector + 1; - else - p_info[i].first_sector = 0; - - if (i < num_parts - 1) - p_info[i].last_sector = p_info[i+1].first_sector - 1; - else - p_info[i].last_sector = sectors*heads*cylinders - 1; - - p_info[i].offset = 0; - p_info[i].flags = 0; - p_info[i].id = FREE_SPACE; - p_info[i].num = PRI_OR_LOG; - - if (IS_LOGICAL(num)) { - /* We have a logical partition --> shrink the extended partition - * if (1) this is the first logical drive, or (2) this is the - * last logical drive; and if there are any other logical drives - * then renumber the ones after "num". - */ - if (i == 0 || (i > 0 && IS_PRIMARY(p_info[i-1].num))) { - ext_info.first_sector = p_info[i].last_sector + 1; - ext_info.offset = 0; - } - if (i == num_parts-1 || - (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num))) - ext_info.last_sector = p_info[i].first_sector - 1; - for (i = 0; i < num_parts; i++) - if (p_info[i].num > num) - p_info[i].num--; - } - - /* Clean up the rest of the partitions */ - check_part_info(); -} - -int add_part(int num, int id, int flags, int first, int last, int offset, - int want_label) -{ - int i, pri = 0, log = 0; - - if (num_parts == MAXIMUM_PARTS || - first < 0 || - first >= cylinders*heads*sectors || - last < 0 || - last >= cylinders*heads*sectors) { - return -1; /* bad start or end */ - } - - for (i = 0; i < num_parts; i++) - if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num)) - pri++; - else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num)) - log++; - if (is_extended(ext_info.id) && log > 0) - pri++; - - if (IS_PRIMARY(num)) - if (pri >= 4) { - return -1; /* no room for more */ - } else - pri++; - - for (i = 0; i < num_parts && p_info[i].last_sector < first; i++); - - if (i == num_parts || p_info[i].id != FREE_SPACE - || last > p_info[i].last_sector) { - return -1; - } - - if (is_extended(id)) { - if (ext_info.id != FREE_SPACE) { - return -1; /* second extended */ - } - else if (IS_PRIMARY(num)) { - ext_info.first_sector = first; - ext_info.last_sector = last; - ext_info.offset = offset; - ext_info.flags = flags; - ext_info.id = id; - ext_info.num = num; - ext_info.volume_label[0] = 0; - ext_info.fstype[0] = 0; - ext_info.ostype[0] = 0; - return 0; - } else { - return -1; /* explicit extended logical */ - } - } - - if (IS_LOGICAL(num)) { - if (!is_extended(ext_info.id)) { - print_warning("!!!! Internal error creating logical " - "drive with no extended partition !!!!"); - } else { - /* We might have a logical partition outside of the extended - * partition's range --> we have to extend the extended - * partition's range to encompass this new partition, but we - * must make sure that there are no primary partitions between - * it and the closest logical drive in extended partition. - */ - if (first < ext_info.first_sector) { - if (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num)) { - print_warning(TWO_EXTENDEDS); - return -1; - } else { - if (first == 0) { - ext_info.first_sector = 0; - ext_info.offset = first = offset; - } else { - ext_info.first_sector = first; - } - } - } else if (last > ext_info.last_sector) { - if (i > 0 && IS_PRIMARY(p_info[i-1].num)) { - print_warning(TWO_EXTENDEDS); - return -1; - } else { - ext_info.last_sector = last; - } - } - } - } - - if (first != p_info[i].first_sector && - !(IS_LOGICAL(num) && first == offset)) { - insert_empty_part(i, p_info[i].first_sector, first-1); - i++; - } - - if (last != p_info[i].last_sector) - insert_empty_part(i+1, last+1, p_info[i].last_sector); - - p_info[i].first_sector = first; - p_info[i].last_sector = last; - p_info[i].offset = offset; - p_info[i].flags = flags; - p_info[i].id = id; - p_info[i].num = num; - p_info[i].volume_label[0] = 0; - p_info[i].fstype[0] = 0; - p_info[i].ostype[0] = 0; - if (want_label) { - if (may_have_dos_label(id)) - get_dos_label(i); - else if (id == LINUX) - get_ext2_label(i); - } - - check_part_info(); - - return 0; -} - -int find_primary(void) -{ - int num = 0, cur = 0; - - while (cur < num_parts && IS_PRIMARY(num)) - if ((p_info[cur].id > 0 && p_info[cur].num == num) || - (is_extended(ext_info.id) && ext_info.num == num)) { - num++; - cur = 0; - } else - cur++; - - if (!IS_PRIMARY(num)) - return -1; - else - return num; -} - -int find_logical(int i) -{ - int num = -1; - int j; - - for (j = i; j < num_parts && num == -1; j++) - if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num)) - num = p_info[j].num; - - if (num == -1) { - num = 4; - for (j = 0; j < num_parts; j++) - if (p_info[j].id > 0 && p_info[j].num == num) - num++; - } - - return num; -} - -void inc_logical(int i) -{ - int j; - - for (j = i; j < num_parts; j++) - if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num)) - p_info[j].num++; -} - -/* Command menu support by Janne Kukonlehto <jtklehto@phoenix.oulu.fi> September 1994 */ - -/* Constants for menuType parameter of menuSelect function */ -#define MENU_HORIZ 1 -#define MENU_VERT 2 -#define MENU_ACCEPT_OTHERS 4 -#define MENU_BUTTON 8 -/* Miscellenous constants */ -#define MENU_SPACING 2 -#define MENU_MAX_ITEMS 256 /* for simpleMenu function */ -#define MENU_UP 1 -#define MENU_DOWN 2 -#define MENU_RIGHT 3 -#define MENU_LEFT 4 - -struct MenuItem -{ - char key; /* Keyboard shortcut; if zero, then there is no more items in the menu item table */ - char *name; /* Item name, should be eight characters with current implementation */ - char *desc; /* Item description to be printed when item is selected */ -}; - -/* Actual function which prints the button bar and highlights the active button * - * Should not be called directly. Call function menuSelect instead. */ - -int menuUpdate( int y, int x, struct MenuItem *menuItems, int itemLength, char *available, int menuType, int current ) -{ - int i, lmargin = x, ymargin = y; - /* Print available buttons */ - move( y, x ); clrtoeol(); - for( i = 0; menuItems[i].key; i++ ) - { - char buff[20]; - int lenName; - /* Search next available button */ - while( menuItems[i].key && !strchr(available, menuItems[i].key) ) - { - i++; - } - if( !menuItems[i].key ) break; /* No more menu items */ - /* If selected item is not available and we have bypassed it, make current item selected */ - if( current < i && menuItems[current].key < 0 ) current = i; - /* If current item is selected, highlight it */ - if( current == i ) /*attron( A_REVERSE )*/ standout (); - /* Print item */ - lenName = strlen( menuItems[i].name ); - if(lenName > itemLength) - print_warning("Menu item too long. Menu may look odd."); - if( menuType & MENU_BUTTON ) - sprintf( buff, "[%*s%-*s]", (itemLength - lenName) / 2, "", - (itemLength - lenName + 1) / 2 + lenName, menuItems[i].name ); - else - sprintf( buff, "%*s%-*s", (itemLength - lenName) / 2, "", - (itemLength - lenName + 1) / 2 + lenName, menuItems[i].name ); - mvaddstr( y, x, buff ); - /* Lowlight after selected item */ - if( current == i ) /*attroff( A_REVERSE )*/ standend (); - /* Calculate position for the next item */ - if( menuType & MENU_VERT ) - { - y += 1; - if( y >= WARNING_START ) - { - y = ymargin; - x += itemLength + MENU_SPACING; - if( menuType & MENU_BUTTON ) x += 2; - } - } - else - { - x += itemLength + MENU_SPACING; - if( menuType & MENU_BUTTON ) x += 2; - if( x > COLUMNS - lmargin - 12 ) - { - x = lmargin; - y ++ ; - } - } - } - /* Print the description of selected item */ - mvaddstr( WARNING_START + 1, (COLUMNS - strlen( menuItems[current].desc )) / 2, menuItems[current].desc ); - return y; -} - -/* This function takes a list of menu items, lets the user choose one of them * - * and returns the value keyboard shortcut of the selected menu item */ - -int menuSelect( int y, int x, struct MenuItem *menuItems, int itemLength, char *available, int menuType, int menuDefault ) -{ - int i, ylast = y, key = 0, current = menuDefault; - if( !( menuType & ( MENU_HORIZ | MENU_VERT ) ) ) - { - print_warning("Menu without direction. Defaulting horizontal."); - menuType |= MENU_HORIZ; - } - /* Make sure that the current is one of the available items */ - while( !strchr(available, menuItems[current].key) ) - { - current ++ ; - if( !menuItems[current].key ) current = 0; - } - /* Repeat until allowable choice has been made */ - while( !key ) - { - /* Display the menu */ - ylast = menuUpdate( y, x, menuItems, itemLength, available, - menuType, current ); - refresh(); - key = getch(); - /* Clear out all prompts and such */ - clear_warning(); - for( i = y; i < ylast; i ++ ) - { - move( i, x ); - clrtoeol(); - } - move( WARNING_START + 1, 0 ); - clrtoeol(); - /* Cursor keys */ - if( key == ESC ) - { - /* Check whether this is a real ESC or one of extended keys */ - /*nodelay(stdscr, TRUE);*/ - key = getch(); - /*nodelay(stdscr, FALSE);*/ - if( key == /*ERR*/ ESC ) - { - /* This is a real ESC */ - key = ESC; - } - if( key == '[' ) - { - /* This is one extended keys */ - switch( getch() ) - { - case 'A': /* Up arrow */ - if( menuType & MENU_VERT ) - { - do { - current -- ; - if( current < 0 ) while( menuItems[current+1].key ) current ++ ; - } while( !strchr( available, menuItems[current].key ) ); - key = 0; - } - else - key = MENU_UP; - break; - case 'B': /* Down arrow */ - if( menuType & MENU_VERT ) - { - do { - current ++ ; - if( !menuItems[current].key ) current = 0 ; - } while( !strchr( available, menuItems[current].key ) ); - key = 0; - } - else - key = MENU_DOWN; - break; - case 'C': /* Right arrow */ - if( menuType & MENU_HORIZ ) - { - do { - current ++ ; - if( !menuItems[current].key ) - { - current = 0 ; - } - } while( !strchr( available, menuItems[current].key ) ); - key = 0; - } - else - key = MENU_RIGHT; - break; - case 'D': /* Left arrow */ - if( menuType & MENU_HORIZ ) - { - do { - current -- ; - if( current < 0 ) - { - while( menuItems[current + 1].key ) current ++ ; - } - } while( !strchr( available, menuItems[current].key ) ); - key = 0; - } - else - key = MENU_LEFT; - break; - } - } - } - /* Enter equals to the keyboard shortcut of current menu item */ - if( key == 13 ) - { - key = menuItems[current].key; - } - /* Should all keys to be accepted? */ - if( key && (menuType & MENU_ACCEPT_OTHERS) ) break; - /* Is pressed key among acceptable ones */ - if( key && (strchr(available, tolower(key)) || strchr(available, key)) ) break; - /* The key has not been accepted so far -> let's reject it */ - if( key ) - { - key = 0; - putchar( BELL ); - print_warning("Illegal key"); - } - } - /* Clear out prompts and such */ - clear_warning(); - for( i = y; i <= ylast; i ++ ) - { - move( i, x ); - clrtoeol(); - } - move( WARNING_START + 1, 0 ); - clrtoeol(); - return key; -} - -/* 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) -{ - static struct MenuItem menuContinueBtn[]= - { - { 'c', "", "Press a key to continue" }, - { 0, NULL, NULL } - }; - - menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, - menuContinueBtn, 0, "c", MENU_HORIZ | MENU_ACCEPT_OTHERS, 0 ); -} - -/* Function menuSelect takes way too many parameters * - * Luckily, most of time we can do with this function */ - -int menuSimple(struct MenuItem *menuItems, int menuDefault) -{ - int i, j, itemLength = 0; - char available[MENU_MAX_ITEMS]; - for(i = 0; menuItems[i].key; i++) - { - j = strlen( menuItems[i].name ); - if( j > itemLength ) itemLength = j; - available[i] = menuItems[i].key; - } - available[i] = 0; - return menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuItems, itemLength, - available, MENU_HORIZ | MENU_BUTTON, menuDefault); -} - -/* End of command menu support code */ - -void new_part(int i) -{ - char response[LINE_LENGTH], def[LINE_LENGTH]; - char c; - int first = p_info[i].first_sector; - int last = p_info[i].last_sector; - int offset = 0; - int flags = 0; - int id = LINUX; - int num = -1; - int num_sects = last - first + 1; - int len, ext, j; - - if (p_info[i].num == PRI_OR_LOG) { - static struct MenuItem menuPartType[]= - { - { 'p', "Primary", "Create a new primary partition" }, - { 'l', "Logical", "Create a new logical partition" }, - { ESC, "Cancel", "Don't create a partition" }, - { 0, NULL, NULL } - }; - - c = menuSimple( menuPartType, 0 ); - if (toupper(c) == 'P') - num = find_primary(); - else if (toupper(c) == 'L') - num = find_logical(i); - else - return; - } else if (p_info[i].num == PRIMARY) - num = find_primary(); - else if (p_info[i].num == LOGICAL) - num = find_logical(i); - else - print_warning("!!! Internal error !!!"); - - sprintf(def, "%.2f", ceiling(num_sects/20.48)/100); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Size (in MB): "); - if ((len = get_string(response, LINE_LENGTH, def)) <= 0 && - len != GS_DEFAULT) - return; - else if (len > 0) { -#define num_cyls(bytes) (round_int(bytes/SECTOR_SIZE/(sectors*heads))) - for (j = 0; - j < len-1 && (isdigit(response[j]) || response[j] == '.'); - j++); - if (toupper(response[j]) == 'K') { - num_sects = num_cyls(atof(response)*1024)*sectors*heads; - } else if (toupper(response[j]) == 'M') { - num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads; - } else if (toupper(response[j]) == 'C') { - num_sects = round_int(atof(response))*sectors*heads; - } else if (toupper(response[j]) == 'S') { - num_sects = round_int(atof(response)); - } else { - num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads; - } - } - - if (num_sects <= 0 || - num_sects > p_info[i].last_sector - p_info[i].first_sector + 1) - return; - - move( COMMAND_LINE_Y, COMMAND_LINE_X ); clrtoeol(); - if (num_sects < p_info[i].last_sector - p_info[i].first_sector + 1) { - /* Determine where inside free space to put partition. - */ - static struct MenuItem menuPlace[]= - { - { 'b', "Beginning", "Add partition at beginning of free space" }, - { 'e', "End", "Add partition at end of free space" }, - { ESC, "Cancel", "Don't create a partition" }, - { 0, NULL, NULL } - }; - c = menuSimple( menuPlace, 0 ); - if (toupper(c) == 'B') - last = first + num_sects - 1; - else if (toupper(c) == 'E') - first = last - num_sects + 1; - else - return; - } - - if (IS_LOGICAL(num) && !is_extended(ext_info.id)) { - /* We want to add a logical partition, but need to create an - * extended partition first. - */ - if ((ext = find_primary()) < 0) { - print_warning(NEED_EXT); - return; - } - (void) add_part(ext, DOS_EXTENDED, 0, first, last, - (first == 0 ? sectors : 0), 0); - first = ext_info.first_sector + ext_info.offset; - } - - if (IS_LOGICAL(num)) - inc_logical(i); - - /* Now we have a complete partition to ourselves */ - if (first == 0 || IS_LOGICAL(num)) - offset = sectors; - - (void) add_part(num, id, flags, first, last, offset, 0); -} - -void clear_p_info(void) -{ - num_parts = 1; - p_info[0].first_sector = 0; - p_info[0].last_sector = sectors*heads*cylinders - 1; - p_info[0].offset = 0; - p_info[0].flags = 0; - p_info[0].id = FREE_SPACE; - p_info[0].num = PRI_OR_LOG; - - ext_info.first_sector = 0; - ext_info.last_sector = 0; - ext_info.offset = 0; - ext_info.flags = 0; - ext_info.id = FREE_SPACE; - ext_info.num = PRIMARY; -} - -void fill_p_info(void) -{ - int p, i; - struct hd_geometry geometry; - partition_table buffer; - partition_info tmp_ext = { 0, 0, 0, 0, FREE_SPACE, PRIMARY }; - - if ((fd = open(disk_device, O_RDWR)) < 0) { - if ((fd = open(disk_device, O_RDONLY)) < 0) - fatal(BAD_OPEN); - opentype = O_RDONLY; - print_warning(READONLY_WARN); - if (curses_started) { - refresh(); - getch(); - clear_warning(); - } - } else - opentype = O_RDWR; - opened = TRUE; - - /* 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) - heads = geometry.heads; - if (!sectors) - sectors = geometry.sectors; - if (!cylinders) - cylinders = geometry.cylinders; - } - - if (!heads || !sectors || !cylinders) - fatal(BAD_GEOMETRY); /* probably a file or cdrom */ - - read_sector(buffer.c.b, 0); - - clear_p_info(); - - if (!zero_table) { - for (i = 0; i < 4; i++) { - int bs = buffer.p.part[i].start_sect; - - if (buffer.p.part[i].sys_ind > 0 && - add_part(i, - buffer.p.part[i].sys_ind, - buffer.p.part[i].boot_ind, - ((bs <= sectors) ? 0 : bs), - buffer.p.part[i].start_sect + - buffer.p.part[i].nr_sects - 1, - ((bs <= sectors) ? bs : 0), - 1)) { - fatal(BAD_PRIMARY); - } - if (is_extended(buffer.p.part[i].sys_ind)) - tmp_ext = ext_info; - } - - if (is_extended(tmp_ext.id)) { - ext_info = tmp_ext; - logical_sectors[logical] = - ext_info.first_sector + ext_info.offset; - read_sector(buffer.c.b, logical_sectors[logical++]); - i = 4; - do { - for (p = 0; - p < 4 && (!buffer.p.part[p].sys_ind || - is_extended(buffer.p.part[p].sys_ind)); - p++); - - if (p < 4 && add_part(i++, - buffer.p.part[p].sys_ind, - buffer.p.part[p].boot_ind, - logical_sectors[logical-1], - logical_sectors[logical-1] + - buffer.p.part[p].start_sect + - buffer.p.part[p].nr_sects - 1, - buffer.p.part[p].start_sect, - 1)) { - fatal(BAD_LOGICAL); - } - - for (p = 0; - p < 4 && !is_extended(buffer.p.part[p].sys_ind); - p++); - if (p < 4) { - logical_sectors[logical] = ext_info.first_sector - + ext_info.offset + buffer.p.part[p].start_sect; - read_sector(buffer.c.b, logical_sectors[logical++]); - } - } while (p < 4 && logical < MAXIMUM_PARTS-4); - } - } -} - -void fill_part_table(struct partition *p, partition_info *pi) -{ - int sects; - - p->boot_ind = pi->flags; - p->sys_ind = pi->id; - if (IS_LOGICAL(pi->num)) - p->start_sect = pi->offset; - else - p->start_sect = pi->first_sector + pi->offset; - p->nr_sects = pi->last_sector - (pi->first_sector+pi->offset) + 1; - sects = (((pi->first_sector+pi->offset)/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->first_sector+pi->offset); - set_hsc(p->head, p->sector, p->cyl, sects); - sects = ((pi->last_sector/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->last_sector); - set_hsc(p->end_head, p->end_sector, p->end_cyl, sects); -} - -void fill_primary_table(partition_table *buffer) -{ - int i; - - /* Zero out existing table */ - for (i = 0x1BE; i < SECTOR_SIZE; i++) - buffer->c.b[i] = 0; - - for (i = 0; i < num_parts; i++) - if (IS_PRIMARY(p_info[i].num)) - fill_part_table(&(buffer->p.part[p_info[i].num]), &(p_info[i])); - - if (is_extended(ext_info.id)) - fill_part_table(&(buffer->p.part[ext_info.num]), &ext_info); - - buffer->p.flag = PART_TABLE_FLAG; -} - -void fill_logical_table(partition_table *buffer, partition_info *pi) -{ - struct partition *p; - int i, sects; - - for (i = 0; i < logical && pi->first_sector != logical_sectors[i]; i++); - if (i == logical || buffer->p.flag != (unsigned short)PART_TABLE_FLAG) - for (i = 0; i < SECTOR_SIZE; i++) - buffer->c.b[i] = 0; - - /* Zero out existing table */ - for (i = 0x1BE; i < SECTOR_SIZE; i++) - buffer->c.b[i] = 0; - - fill_part_table(&(buffer->p.part[0]), pi); - - for (i = 0; - i < num_parts && pi->num != p_info[i].num - 1; - i++); - - if (i < num_parts) { - p = &(buffer->p.part[1]); - pi = &(p_info[i]); - - p->boot_ind = 0; - p->sys_ind = DOS_EXTENDED; - p->start_sect = pi->first_sector - ext_info.first_sector - ext_info.offset; - p->nr_sects = pi->last_sector - pi->first_sector + 1; - sects = ((pi->first_sector/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->first_sector); - set_hsc(p->head, p->sector, p->cyl, sects); - sects = ((pi->last_sector/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->last_sector); - set_hsc(p->end_head, p->end_sector, p->end_cyl, sects); - } - - buffer->p.flag = PART_TABLE_FLAG; -} - -void write_part_table(void) -{ - int i, done = FALSE, len; - partition_table buffer; - struct stat s; - int is_bdev; - char response[LINE_LENGTH]; - - if (opentype == O_RDONLY) { - print_warning(READONLY_WARN); - refresh(); - getch(); - clear_warning(); - return; - } - - is_bdev = 0; - if(fstat(fd, &s) == 0 && S_ISBLK(s.st_mode)) - is_bdev = 1; - - if (is_bdev) { - print_warning(WRITE_WARN); - - while (!done) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Are you sure you want write the partition table " - "to disk? (yes or no): "); - len = get_string(response, LINE_LENGTH, NULL); - clear_warning(); - if (len == GS_ESCAPE) - return; - else if (len == 2 && - toupper(response[0]) == 'N' && - toupper(response[1]) == 'O') { - print_warning(NO_WRITE); - return; - } else if (len == 3 && - toupper(response[0]) == 'Y' && - toupper(response[1]) == 'E' && - toupper(response[2]) == 'S') - done = TRUE; - else - print_warning(YES_NO); - } - - clear_warning(); - print_warning(WRITING_PART); - refresh(); - } - - read_sector(buffer.c.b, 0); - fill_primary_table(&buffer); - write_sector(buffer.c.b, 0); - - for (i = 0; i < num_parts; i++) - if (IS_LOGICAL(p_info[i].num)) { - read_sector(buffer.c.b, p_info[i].first_sector); - fill_logical_table(&buffer, &(p_info[i])); - write_sector(buffer.c.b, p_info[i].first_sector); - } - - if (is_bdev) { - sync(); - sleep(2); - if (!ioctl(fd,BLKRRPART)) - changed = TRUE; - sync(); - sleep(4); - - clear_warning(); - if (changed) - print_warning(YES_WRITE); - else - print_warning(RRPART_FAILED); - } else - print_warning(YES_WRITE); -} - -void fp_printf(FILE *fp, char *format, ...) -{ - va_list args; - char buf[1024]; - int y, x; - - va_start(args, format); - vsprintf(buf, format, args); - va_end(args); - - if (fp == NULL) { - /* The following works best if the string to be printed has at - most only one newline. */ - printw("%s", buf); - getyx(stdscr, y, x); - if (y >= COMMAND_LINE_Y-2) { - menuContinue(); - erase(); - move(0, 0); - } - } else - fprintf(fp, "%s", buf); -} - -#define MAX_PER_LINE 16 -void print_file_buffer(FILE *fp, char *buffer) -{ - int i,l; - - for (i = 0, l = 0; i < SECTOR_SIZE; i++, l++) { - if (l == 0) - fp_printf(fp, "0x%03X:", i); - fp_printf(fp, " %02X", (unsigned char) buffer[i]); - if (l == MAX_PER_LINE - 1) { - fp_printf(fp, "\n"); - l = -1; - } - } - if (l > 0) - fp_printf(fp, "\n"); - fp_printf(fp, "\n"); -} - -void print_raw_table(void) -{ - int i, to_file; - partition_table buffer; - char fname[LINE_LENGTH]; - FILE *fp; - - if (print_only) { - fp = stdout; - to_file = TRUE; - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); - - if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) - return; - - if (to_file) { - if ((fp = fopen(fname, "w")) == NULL) { - char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); - print_warning(errstr); - return; - } - } else { - fp = NULL; - erase(); - move(0, 0); - } - } - - fp_printf(fp, "Disk Drive: %s\n", disk_device); - - fp_printf(fp, "Sector 0:\n"); - read_sector(buffer.c.b, 0); - fill_primary_table(&buffer); - print_file_buffer(fp, buffer.c.b); - - for (i = 0; i < num_parts; i++) - if (IS_LOGICAL(p_info[i].num)) { - fp_printf(fp, "Sector %d:\n", p_info[i].first_sector); - read_sector(buffer.c.b, p_info[i].first_sector); - fill_logical_table(&buffer, &(p_info[i])); - print_file_buffer(fp, buffer.c.b); - } - - if (to_file) { - if (!print_only) - fclose(fp); - } else { - menuContinue(); - } -} - -void print_p_info_entry(FILE *fp, partition_info *p) -{ - int size; - char part_str[40]; - - if (p->id == UNUSABLE) - fp_printf(fp, " None "); - else if (p->id == FREE_SPACE && p->num == PRI_OR_LOG) - fp_printf(fp, " Pri/Log"); - else if (p->id == FREE_SPACE && p->num == PRIMARY) - fp_printf(fp, " Primary"); - else if (p->id == FREE_SPACE && p->num == LOGICAL) - fp_printf(fp, " Logical"); - else - fp_printf(fp, "%2d %-7.7s", p->num+1, - IS_LOGICAL(p->num) ? "Logical" : "Primary"); - - fp_printf(fp, " "); - - fp_printf(fp, "%8d%c", p->first_sector, - ((p->first_sector/(sectors*heads)) != - ((float)p->first_sector/(sectors*heads)) ? - '*' : ' ')); - - fp_printf(fp, "%8d%c", p->last_sector, - (((p->last_sector+1)/(sectors*heads)) != - ((float)(p->last_sector+1)/(sectors*heads)) ? - '*' : ' ')); - - fp_printf(fp, "%7d%c", p->offset, - ((((p->first_sector == 0 || IS_LOGICAL(p->num)) && - (p->offset != sectors)) || - (p->first_sector != 0 && IS_PRIMARY(p->num) && - p->offset != 0)) ? - '#' : ' ')); - - size = p->last_sector - p->first_sector + 1; - fp_printf(fp, "%8d%c", size, - ((size/(sectors*heads)) != ((float)size/(sectors*heads)) ? - '*' : ' ')); - - fp_printf(fp, " "); - - if (p->id == UNUSABLE) - sprintf(part_str, "%.17s", "Unusable"); - else if (p->id == FREE_SPACE) - sprintf(part_str, "%.17s", "Free Space"); - else if (partition_type[p->id]) - sprintf(part_str, "%.17s (%02X)", partition_type[p->id], p->id); - else - sprintf(part_str, "%.17s (%02X)", "Unknown", p->id); - fp_printf(fp, "%-22.22s", part_str); - - fp_printf(fp, " "); - - if (p->flags == ACTIVE_FLAG) - fp_printf(fp, "Boot (%02X)", p->flags); - else if (p->flags != 0) - fp_printf(fp, "Unknown (%02X)", p->flags); - else - fp_printf(fp, "None (%02X)", p->flags); - - fp_printf(fp, "\n"); -} - -void print_p_info(void) -{ - char fname[LINE_LENGTH]; - FILE *fp; - int i, to_file, pext = is_extended(ext_info.id); - - if (print_only) { - fp = stdout; - to_file = TRUE; - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); - - if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) - return; - - if (to_file) { - if ((fp = fopen(fname, "w")) == NULL) { - char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); - print_warning(errstr); - return; - } - } else { - fp = NULL; - erase(); - move(0, 0); - } - } - - fp_printf(fp, "Partition Table for %s\n", disk_device); - fp_printf(fp, "\n"); - fp_printf(fp, " First Last\n"); - fp_printf(fp, " # Type Sector Sector Offset Length Filesystem Type (ID) Flags\n"); - fp_printf(fp, "-- ------- -------- --------- ------ --------- ---------------------- ---------\n"); - - for (i = 0; i < num_parts; i++) { - if (pext && (p_info[i].first_sector >= ext_info.first_sector)) { - print_p_info_entry(fp,&ext_info); - pext = FALSE; - } - print_p_info_entry(fp, &(p_info[i])); - } - - if (to_file) { - if (!print_only) - fclose(fp); - } else { - menuContinue(); - } -} - -void print_part_entry(FILE *fp, int num, partition_info *pi) -{ - int first = 0, start = 0, end = 0, size = 0; - int ss = 0, sh = 0, sc = 0; - int es = 0, eh = 0, ec = 0; - int flags = 0, id = 0; - - if (pi != NULL) { - flags = pi->flags; - id = pi->id; - - if (IS_LOGICAL(num)) - first = pi->offset; - else - first = pi->first_sector + pi->offset; - - start = pi->first_sector + pi->offset; - end = pi->last_sector; - size = end - start + 1; - if ((start/(sectors*heads)) > 1023) - start = heads*sectors*1024 - 1; - if ((end/(sectors*heads)) > 1023) - end = heads*sectors*1024 - 1; - - ss = start % sectors + 1; - start /= sectors; - sh = start % heads; - sc = start / heads; - - es = end % sectors + 1; - end /= sectors; - eh = end % heads; - ec = end / heads; - } - - 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); -} - - -void print_part_table(void) -{ - int i, j, to_file; - char fname[LINE_LENGTH]; - FILE *fp; - - if (print_only) { - fp = stdout; - to_file = TRUE; - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); - - if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) - return; - - if (to_file) { - if ((fp = fopen(fname, "w")) == NULL) { - char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); - print_warning(errstr); - return; - } - } else { - fp = NULL; - erase(); - move(0, 0); - } - } - - fp_printf(fp, "Partition Table for %s\n", disk_device); - fp_printf(fp, "\n"); - fp_printf(fp, " ---Starting--- ----Ending---- Start Number of\n"); - fp_printf(fp, " # Flags Head Sect Cyl ID Head Sect Cyl Sector Sectors\n"); - fp_printf(fp, "-- ----- ---- ---- ---- ---- ---- ---- ---- -------- ---------\n"); - - for (i = 0; i < 4; i++) { - for (j = 0; - j < num_parts && (p_info[j].id <= 0 || p_info[j].num != i); - j++); - if (j < num_parts) { - print_part_entry(fp, i, &(p_info[j])); - } else if (is_extended(ext_info.id) && ext_info.num == i) { - print_part_entry(fp, i, &ext_info); - } else { - print_part_entry(fp, i, NULL); - } - } - - for (i = 0; i < num_parts; i++) - if (IS_LOGICAL(p_info[i].num)) - print_part_entry(fp, p_info[i].num, &(p_info[i])); - - if (to_file) { - if (!print_only) - fclose(fp); - } else { - menuContinue(); - } -} - -void print_tables(void) -{ - int done = FALSE; - - static struct MenuItem menuFormat[]= - { - { 'r', "Raw", "Print the table using raw data format" }, - { 's', "Sectors", "Print the table ordered by sectors" }, - { 't', "Table", "Just print the partition table" }, - { ESC, "Cancel", "Don't print the table" }, - { 0, NULL, NULL } - }; - - while (!done) - switch ( toupper(menuSimple( menuFormat, 2)) ) { - case 'R': - print_raw_table(); - done = TRUE; - break; - case 'S': - print_p_info(); - done = TRUE; - break; - case 'T': - print_part_table(); - done = TRUE; - break; - case ESC: - done = TRUE; - break; - } -} - -#define END_OF_HELP "EOHS!" -#define NEW_HELP_SCREEN "SNHS!" -void display_help() -{ - char *help_text[] = { - "Help Screen for cfdisk " VERSION, - "", - "This is cfdisk, a curses based disk partitioning programs, which", - "allows you to create, delete and modify partitions on your hard", - "disk drive.", - "", - "Copyright (C) 1994-1998 Kevin E. Martin & aeb", - "", - "Command Meaning", - "------- -------", - " b Toggle bootable flag of the current partition", - " d Delete the current partition", - " g Change cylinders, heads, sectors-per-track parameters", - " WARNING: This option should only be used by people who", - " know what they are doing.", - " h Print this screen", - " m Maximize disk usage of the current partition", - " Note: This may make the partition incompatible with", - " DOS, OS/2, ...", - " n Create new partition from free space", - " p Print partition table to the screen or to a file", - " There are several different formats for the partition", - " that you can choose from:", - " r - Raw data (exactly what would be written to disk)", - " s - Table ordered by sectors", - " t - Table in raw format", - " q Quit program without writing partition table", - " t Change the filesystem type", - " u Change units of the partition size display", - " Rotates through Mb, sectors and cylinders", - " W Write partition table to disk (must enter upper case W)", - " Since this might destroy data on the disk, you must", - " either confirm or deny the write by entering `yes' or", - " `no'", - "Up Arrow Move cursor to the previous partition", - "Down Arrow Move cursor to the next partition", - "CTRL-L Redraws the screen", - " ? Print this screen", - "", - "Note: All of the commands can be entered with either upper or lower", - "case letters (except for Writes).", - END_OF_HELP - }; - - int cur_line = 0; - FILE *fp = NULL; - - erase(); - move(0, 0); - while (strcmp(help_text[cur_line], END_OF_HELP)) - if (!strcmp(help_text[cur_line], NEW_HELP_SCREEN)) { - menuContinue(); - erase(); - move(0, 0); - cur_line++; - } else - fp_printf(fp, "%s\n", help_text[cur_line++]); - - menuContinue(); -} - -int change_geometry(void) -{ - int ret_val = FALSE; - int done = FALSE; - char def[LINE_LENGTH]; - char response[LINE_LENGTH]; - int tmp_val; - - while (!done) { - static struct MenuItem menuGeometry[]= - { - { 'c', "Cylinders", "Change cylinder geometry" }, - { 'h', "Heads", "Change head geometry" }, - { 's', "Sectors", "Change sector geometry" }, - { 'd', "Done", "Done with changing geometry" }, - { 0, NULL, NULL } - }; - move(COMMAND_LINE_Y, COMMAND_LINE_X); - clrtoeol(); - refresh(); - - clear_warning(); - - switch (toupper( menuSimple(menuGeometry, 3) )) { - case 'C': - sprintf(def, "%d", cylinders); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of cylinders: "); - if (get_string(response, LINE_LENGTH, def) > 0) { - tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_CYLINDERS) { - cylinders = tmp_val; - ret_val = TRUE; - } else - print_warning(BAD_CYLINDERS); - } - break; - case 'H': - sprintf(def, "%d", heads); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of heads: "); - if (get_string(response, LINE_LENGTH, def) > 0) { - tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_HEADS) { - heads = tmp_val; - ret_val = TRUE; - } else - print_warning(BAD_HEADS); - } - break; - case 'S': - sprintf(def, "%d", sectors); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of sectors per track: "); - if (get_string(response, LINE_LENGTH, def) > 0) { - tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_SECTORS) { - sectors = tmp_val; - ret_val = TRUE; - } else - print_warning(BAD_SECTORS); - } - break; - case ESC: - case 'D': - done = TRUE; - break; - default: - putchar(BELL); - break; - } - } - - if (ret_val) { - int disk_end = heads*sectors*cylinders-1; - - if (p_info[num_parts-1].last_sector > disk_end) { - while (p_info[num_parts-1].first_sector > disk_end) { - if (p_info[num_parts-1].id == FREE_SPACE || - p_info[num_parts-1].id == UNUSABLE) - remove_part(num_parts-1); - else - del_part(num_parts-1); - } - - p_info[num_parts-1].last_sector = disk_end; - - if (ext_info.last_sector > disk_end) - ext_info.last_sector = disk_end; - } else if (p_info[num_parts-1].last_sector < disk_end) { - if (p_info[num_parts-1].id == FREE_SPACE || - p_info[num_parts-1].id == UNUSABLE) { - p_info[num_parts-1].last_sector = disk_end; - } else { - insert_empty_part(num_parts, - p_info[num_parts-1].last_sector+1, - disk_end); - } - } - - /* Make sure the partitions are correct */ - check_part_info(); - } - - return ret_val; -} - -void change_id(int i) -{ - char id[LINE_LENGTH], def[LINE_LENGTH]; - int num_types = 0; - int num_across, num_down; - int len, new_id = LINUX; - int y_start, y_end; - int j, pos; - - for (num_types = 0, j = 1; j < NUM_PART_TYPES; j++) - if (partition_type[j]) - num_types++; - - num_across = COLS/COL_ID_WIDTH; - num_down = (((float)num_types)/num_across + 1); - y_start = COMMAND_LINE_Y - 1 - num_down; - if (y_start > DISK_TABLE_START+cur_part+4) - y_start = DISK_TABLE_START+cur_part+4; - y_end = y_start + num_down - 1; - - for (j = y_start - 1; j <= y_end + 1; j++) { - move(j, 0); - clrtoeol(); - } - - for (pos = 0, j = 1; j < NUM_PART_TYPES; j++) - if (partition_type[j]) { - move(y_start + pos % num_down, (pos/num_down)*COL_ID_WIDTH + 1); - printw("%02X %-16.16s", j, partition_type[j]); - pos++; - } - - sprintf(def, "%02X", new_id); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Enter filesystem type: "); - if ((len = get_string(id, 2, def)) <= 0 && len != GS_DEFAULT) - return; - - if (len != GS_DEFAULT) { - if (!isxdigit(id[0])) - return; - new_id = (isdigit(id[0]) ? id[0] - '0' : tolower(id[0]) - 'a' + 10); - if (len == 2) - if (isxdigit(id[1])) - new_id = new_id*16 + - (isdigit(id[1]) ? id[1] - '0' : tolower(id[1]) - 'a' + 10); - else - return; - } - - if (new_id == 0) - print_warning(ID_EMPTY); - else if (is_extended(new_id)) - print_warning(ID_EXT); - else - p_info[i].id = new_id; -} - -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); - for (j = 0; j < COLS; j++) - addch(' '); - } - - if (p_info[i].id > 0) { - mvprintw(y, NAME_START, - "%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"); - else - mvprintw(y, FLAGS_START, "Unk(%02X)", p_info[i].flags); - if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) { - if (p_info[i].offset != sectors) - addstr(", NC"); - } else { - if (p_info[i].offset != 0) - addstr(", NC"); - } - } else { - if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) { - if (p_info[i].offset != sectors) - mvaddstr(y, FLAGS_START, "NC"); - } else { - if (p_info[i].offset != 0) - mvaddstr(y, FLAGS_START, "NC"); - } - } - } - mvaddstr(y, PTYPE_START, - (p_info[i].id == UNUSABLE ? "" : - (IS_LOGICAL(p_info[i].num) ? "Logical" : - (p_info[i].num >= 0 ? "Primary" : - (p_info[i].num == PRI_OR_LOG ? "Pri/Log" : - (p_info[i].num == PRIMARY ? "Primary" : "Logical")))))); - - t = partition_type_text(i); - if (t) - mvaddstr(y, FSTYPE_START, t); - else - mvprintw(y, FSTYPE_START, "Unknown (%02X)", p_info[i].id); - - if (p_info[i].volume_label[0]) { - int l = strlen(p_info[i].volume_label); - int s = SIZE_START-5-l; - mvprintw(y, (s > LABEL_START) ? LABEL_START : s, - " [%s] ", p_info[i].volume_label); - } - - size = p_info[i].last_sector - p_info[i].first_sector + 1; - if (display_units == SECTORS) - mvprintw(y, SIZE_START, "%9d", size); - else if (display_units == CYLINDERS) - mvprintw(y, SIZE_START, "%9d", size/(sectors*heads)); - else - mvprintw(y, SIZE_START, "%9.2f", ceiling(size/20.48)/100); - if (((size/(sectors*heads)) != ceiling(size/(sectors*(float)heads))) || - ((p_info[i].first_sector/(sectors*heads)) != - ceiling(p_info[i].first_sector/(sectors*heads)))) - mvprintw(y, COLUMNS-1, "*"); -} - -void init_const(void) -{ - if (!defined) { - NAME_START = (((float)NAME_START)/COLUMNS)*COLS; - FLAGS_START = (((float)FLAGS_START)/COLUMNS)*COLS; - PTYPE_START = (((float)PTYPE_START)/COLUMNS)*COLS; - FSTYPE_START = (((float)FSTYPE_START)/COLUMNS)*COLS; - LABEL_START = (((float)LABEL_START)/COLUMNS)*COLS; - SIZE_START = (((float)SIZE_START)/COLUMNS)*COLS; - COMMAND_LINE_X = (((float)COMMAND_LINE_X)/COLUMNS)*COLS; - - COMMAND_LINE_Y = LINES - 4; - WARNING_START = LINES - 2; - - if ((NUM_ON_SCREEN = COMMAND_LINE_Y - DISK_TABLE_START - 3) <= 0) - NUM_ON_SCREEN = 1; - - COLUMNS = COLS; - defined = TRUE; - } -} - -void draw_screen(void) -{ - int i; - char *line; - - line = (char *)malloc((COLS+1)*sizeof(char)); - - if (warning_last_time) { - for (i = 0; i < COLS; i++) { - move(WARNING_START, i); - line[i] = inch(); - } - line[COLS] = 0; - } - - erase(); - - if (warning_last_time) - mvaddstr(WARNING_START, 0, line); - - - sprintf(line, "cfdisk %s", VERSION); - mvaddstr(HEADER_START, (COLS-strlen(line))/2, line); - sprintf(line, "Disk Drive: %s", disk_device); - mvaddstr(HEADER_START+2, (COLS-strlen(line))/2, line); - sprintf(line, "Heads: %d Sectors per Track: %d Cylinders: %d", - heads, sectors, cylinders); - mvaddstr(HEADER_START+3, (COLS-strlen(line))/2, line); - - mvaddstr(DISK_TABLE_START, NAME_START, "Name"); - mvaddstr(DISK_TABLE_START, FLAGS_START, "Flags"); - mvaddstr(DISK_TABLE_START, PTYPE_START-1, "Part Type"); - mvaddstr(DISK_TABLE_START, FSTYPE_START, "FS Type"); - mvaddstr(DISK_TABLE_START, LABEL_START+1, "[Label]"); - if (display_units == SECTORS) - mvaddstr(DISK_TABLE_START, SIZE_START, " Sectors"); - else if (display_units == CYLINDERS) - mvaddstr(DISK_TABLE_START, SIZE_START, "Cylinders"); - else - mvaddstr(DISK_TABLE_START, SIZE_START, "Size (MB)"); - - move(DISK_TABLE_START+1, 1); - for (i = 1; i < COLS-1; i++) - addch('-'); - - if (NUM_ON_SCREEN >= num_parts) - for (i = 0; i < num_parts; i++) - draw_partition(i); - else - for (i = (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN; - i < NUM_ON_SCREEN + (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN && - i < num_parts; - i++) - draw_partition(i); - - free(line); -} - -int draw_cursor(int move) -{ - if (move != 0 && (cur_part + move < 0 || cur_part + move >= num_parts)) - return -1; - - if (arrow_cursor) - mvaddstr(DISK_TABLE_START + cur_part + 2 - - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, " "); - else - draw_partition(cur_part); - - cur_part += move; - - if (((cur_part - move)/NUM_ON_SCREEN)*NUM_ON_SCREEN != - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN) - draw_screen(); - - if (arrow_cursor) - mvaddstr(DISK_TABLE_START + cur_part + 2 - - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, "-->"); - else { - standout(); - draw_partition(cur_part); - standend(); - } - - return 0; -} - -void do_curses_fdisk(void) -{ - int done = FALSE; - char command; - - static struct MenuItem menuMain[]= - { - { 'b', "Bootable", "Toggle bootable flag of the current partition" }, - { 'd', "Delete", "Delete the current partition" }, - { 'g', "Geometry", "Change disk geometry (experts only)" }, - { 'h', "Help", "Print help screen" }, - { 'm', "Maximize", "Maximize disk usage of the current partition (experts only)" }, - { 'n', "New", "Create new partition from free space" }, - { 'p', "Print", "Print partition table to the screen or to a file" }, - { 'q', "Quit", "Quit program without writing partition table" }, - { 't', "Type", "Change the filesystem type (DOS, Linux, OS/2 and so on)" }, - { 'u', "Units", "Change units of the partition size display (MB, sect, cyl)" }, - { 'W', "Write", "Write partition table to disk (this might destroy data)" }, - { 0, NULL, NULL } - }; - curses_started = 1; - initscr(); - init_const(); - - old_SIGINT = signal(SIGINT, die); - old_SIGTERM = signal(SIGTERM, die); -#ifdef DEBUG - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); -#endif - - cbreak(); - noecho(); - nonl(); - - fill_p_info(); - - draw_screen(); - - while (!done) { - char *s; - - (void)draw_cursor(0); - - if (p_info[cur_part].id == FREE_SPACE) { - s = ((opentype == O_RDWR) ? "hnpquW" : "hnpqu"); - command = menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuMain, 8, - s, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, 0); - } else if (p_info[cur_part].id > 0) { - s = ((opentype == O_RDWR) ? "bdhmpqtuW" : "bdhmpqtu"); - command = menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuMain, 8, - s, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, 0); - } else { - s = ((opentype == O_RDWR) ? "hpquW" : "hpqu"); - command = menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuMain, 8, - s, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, 0); - } - switch ( command ) { - case 'B': - case 'b': - if (p_info[cur_part].id > 0) - p_info[cur_part].flags ^= 0x80; - else - print_warning(NO_FLAGS); - break; - case 'D': - case 'd': - if (p_info[cur_part].id > 0) { - del_part(cur_part); - if (cur_part >= num_parts) - cur_part = num_parts - 1; - draw_screen(); - } else - print_warning(DEL_EMPTY); - break; - case 'G': - case 'g': - if (change_geometry()) - draw_screen(); - break; - case 'M': - case 'm': - if (p_info[cur_part].id > 0) { - if (p_info[cur_part].first_sector == 0 || - IS_LOGICAL(p_info[cur_part].num)) { - if (p_info[cur_part].offset == sectors) - p_info[cur_part].offset = 1; - else - p_info[cur_part].offset = sectors; - draw_screen(); - } else if (p_info[cur_part].offset != 0) - p_info[cur_part].offset = 0; - else - print_warning(MAX_UNMAXABLE); - } else - print_warning(MAX_UNMAXABLE); - break; - case 'N': - case 'n': - if (p_info[cur_part].id == FREE_SPACE) { - new_part(cur_part); - draw_screen(); - } else if (p_info[cur_part].id == UNUSABLE) - print_warning(ADD_UNUSABLE); - else - print_warning(ADD_EXISTS); - break; - case 'P': - case 'p': - print_tables(); - draw_screen(); - break; - case 'Q': - case 'q': - done = TRUE; - break; - case 'T': - case 't': - if (p_info[cur_part].id > 0) { - change_id(cur_part); - draw_screen(); - } else - print_warning(TYPE_EMPTY); - break; - case 'U': - case 'u': - if (display_units == MEGABYTES) - display_units = SECTORS; - else if (display_units == SECTORS) - display_units = CYLINDERS; - else if (display_units == CYLINDERS) - display_units = MEGABYTES; - draw_screen(); - break; - case 'W': - write_part_table(); - break; - case 'H': - case 'h': - case '?': - display_help(); - draw_screen(); - break; - case MENU_UP : /* Up arrow */ - if (!draw_cursor(-1)) - command = 0; - else - print_warning(NO_MORE_PARTS); - break; - case MENU_DOWN : /* Down arrow */ - if (!draw_cursor(1)) - command = 0; - else - print_warning(NO_MORE_PARTS); - break; - case REDRAWKEY: - clear(); - draw_screen(); - break; - default: - print_warning(BAD_COMMAND); - putchar(BELL); /* CTRL-G */ - } - } - - die_x(0); -} - -void copyright(void) -{ - fprintf(stderr, "Copyright (C) 1994-1997 Kevin E. Martin & aeb\n"); -} - -void usage(char *prog_name) -{ - fprintf(stderr, "\nUsage:\n"); - fprintf(stderr, "Print version:\n"); - fprintf(stderr, "\t%s -v\n", prog_name); - fprintf(stderr, "Print partition table:\n"); - fprintf(stderr, "\t%s -P {r|s|t} [options] device\n", prog_name); - fprintf(stderr, "Interactive use:\n"); - fprintf(stderr, "\t%s [options] device\n", prog_name); - fprintf(stderr, " -Options: --a: Use arrow instead of highlighting; --z: Start with a zero partition table, instead of reading the pt from disk; --c C -h H -s S: Override the kernel's idea of the number of cylinders, - the number of heads and the number of sectors/track.\n\n"); - - copyright(); -} - -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': - arrow_cursor = TRUE; - break; - case 'c': - cylinders = atoi(optarg); - if (cylinders <= 0 || cylinders > MAX_CYLINDERS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_CYLINDERS); - exit(1); - } - break; - case 'h': - heads = atoi(optarg); - if (heads <= 0 || heads > MAX_HEADS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_HEADS); - exit(1); - } - break; - case 's': - sectors = atoi(optarg); - if (sectors <= 0 || sectors > MAX_SECTORS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_SECTORS); - exit(1); - } - break; - case 'v': - fprintf(stderr, "cfdisk %s\n", VERSION); - copyright(); - exit(0); - case 'z': - zero_table = TRUE; - break; - case 'P': - len = strlen(optarg); - for (i = 0; i < len; i++) { - switch (optarg[i]) { - case 'r': - print_only |= PRINT_RAW_TABLE; - break; - case 's': - print_only |= PRINT_SECTOR_TABLE; - break; - case 't': - print_only |= PRINT_PARTITION_TABLE; - break; - default: - usage(argv[0]); - break; - } - } - break; - default: - usage(argv[0]); - exit(1); - } - - if (argc-optind == 1) - disk_device = argv[optind]; - else if (argc-optind != 0) { - usage(argv[0]); - exit(1); - } else if ((fd = open(DEFAULT_DEVICE, O_RDONLY)) < 0) - disk_device = ALTERNATE_DEVICE; - else close(fd); - - if (print_only) { - fill_p_info(); - if (print_only & PRINT_RAW_TABLE) - print_raw_table(); - if (print_only & PRINT_SECTOR_TABLE) - print_p_info(); - if (print_only & PRINT_PARTITION_TABLE) - print_part_table(); - } else - do_curses_fdisk(); - - return 0; -} diff --git a/disk-utils/cfdisk.c.bak b/disk-utils/cfdisk.c.bak deleted file mode 100644 index 3b9f22f58..000000000 --- a/disk-utils/cfdisk.c.bak +++ /dev/null @@ -1,2066 +0,0 @@ -/**************************************************************************** - * - * CFDISK - * - * cfdisk is a curses based disk drive partitioning program that can - * create partitions for a wide variety of operating systems including - * Linux, MS-DOS and OS/2. - * - * cfdisk was inspired by the fdisk program, by A. V. Le Blanc - * (LeBlanc@mcc.ac.uk). - * - * Copyright (C) 1994 Kevin E. Martin (martin@cs.unc.edu) - * - * cfdisk is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * cfdisk is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with cfdisk; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Created: Fri Jan 28 22:46:58 1994, martin@cs.unc.edu - * - ****************************************************************************/ - -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <unistd.h> -#include <ctype.h> -#include <errno.h> -#include <getopt.h> -#include <fcntl.h> -#include <curses.h> -#include <signal.h> -#include <math.h> -#include <sys/ioctl.h> -#include <linux/genhd.h> -#include <linux/hdreg.h> -#include <linux/fs.h> /* for BLKRRPART */ - -typedef long ext2_loff_t; -extern ext2_loff_t ext2_llseek(unsigned int fd, - ext2_loff_t offset, - unsigned int origin); - -#define VERSION "0.8 BETA (>2GB)" - -#define DEFAULT_DEVICE "/dev/hda" -#define ALTERNATE_DEVICE "/dev/sda" - -#define LINE_LENGTH 80 -#define MAXIMUM_PARTS 60 - -#define SECTOR_SIZE 512 - -#define MAX_CYLINDERS 65535 -#define MAX_HEADS 255 -#define MAX_SECTORS 63 - -#define ACTIVE_FLAG 0x80 -#define PART_TABLE_FLAG 0xAA55 - -#define UNUSABLE -1 -#define FREE_SPACE 0x00 -#define EXTENDED 0x05 -#define LINUX_MINIX 0x81 -#define LINUX_SWAP 0x82 -#define LINUX 0x83 - -#define ADD_EXISTS "This partition is already in use" -#define ADD_UNUSABLE "This partition is unusable" -#define DEL_EMPTY "Cannot delete an empty partition" -#define ID_EMPTY "Cannot change FS Type to empty" -#define ID_EXT "Cannot change FS Type to extended" -#define NEED_EXT "No room to create the extended partition" -#define NO_FLAGS "Cannot make this partition bootable" -#define NO_MORE_PARTS "No more partitions" -#define PRINT_OPEN_ERR "Cannot open file '%s'" -#define TWO_EXTENDEDS "Cannot create logical drive here -- would create two extended partitions" -#define TYPE_EMPTY "Cannot change the type of an empty partition" -#define BAD_COMMAND "Illegal command" -#define MAX_UNMAXABLE "Cannot maximize this partition" -#define BAD_OPEN "Cannot open disk drive" -#define BAD_SEEK "Cannot seek on disk drive" -#define BAD_READ "Cannot read disk drive" -#define BAD_WRITE "Cannot write disk drive" -#define BAD_GEOMETRY "Cannot read disk drive geometry" -#define BAD_PRIMARY "Bad primary partition" -#define BAD_LOGICAL "Bad logical partition" -#define BAD_CYLINDERS "Illegal cylinders value" -#define BAD_HEADS "Illegal heads value" -#define BAD_SECTORS "Illegal sectors value" -#define WRITE_WARN "Warning!! This may destroy data on your disk!" -#define YES_NO "Please enter `yes' or `no'" -#define WRITING_PART "Writing partition table to disk..." -#define YES_WRITE "Wrote partition table to disk" -#define NO_WRITE "Did not write partition table to disk" -#define RRPART_FAILED "Wrote partition table, but re-read table failed. Reboot to update table." - -#define PRI_OR_LOG -1 -#define PRIMARY -2 -#define LOGICAL -3 - -#define COL_ID_WIDTH 20 - -#define CR '\015' -#define ESC '\033' -#define DEL '\177' -#define BELL '\007' -/* '\014' == ^L */ -#define REDRAWKEY '\014' - -/* Display units */ -#define MEGABYTES 1 -#define SECTORS 2 -#define CYLINDERS 3 - -#define GS_DEFAULT -1 -#define GS_ESCAPE -2 - -#define PRINT_RAW_TABLE 1 -#define PRINT_SECTOR_TABLE 2 -#define PRINT_PARTITION_TABLE 4 - -#define IS_PRIMARY(p) ((p) >= 0 && (p) < 4) -#define IS_LOGICAL(p) ((p) > 3) - -#define round_int(d) ((double)((int)(d+0.5))) -#define ceiling(d) ((double)(((d) != (int)(d)) ? (int)(d+1.0) : (int)(d))) - -#define set_hsc(h,s,c,sector) \ -{ \ - s = sector % sectors + 1; \ - sector /= sectors; \ - h = sector % heads; \ - sector /= heads; \ - c = sector & 0xFF; \ - s |= (sector >> 2) & 0xC0;\ -} - -#define ALIGNMENT 2 -typedef union { - struct { - unsigned char align[ALIGNMENT]; - unsigned char b[SECTOR_SIZE]; - } c; - struct { - unsigned char align[ALIGNMENT]; - unsigned char buffer[0x1BE]; - struct partition part[4]; - unsigned short flag; - } p; -} partition_table; - -typedef struct { - int first_sector; /* first sector in partition */ - int last_sector; /* last sector in partition */ - int offset; /* offset from first sector to start of data */ - int flags; /* active == 0x80 */ - int id; /* filesystem type */ - int num; /* number of partition -- primary vs. logical */ -} partition_info; - -char *disk_device = DEFAULT_DEVICE; -int fd; -int heads = 0; -int sectors = 0; -int cylinders = 0; -int changed = FALSE; -int opened = FALSE; - -partition_info p_info[MAXIMUM_PARTS]; -partition_info ext_info; -int num_parts = 0; - -int logical = 0; -int logical_sectors[MAXIMUM_PARTS]; - -__sighandler_t old_SIGINT, old_SIGTERM; - -int arrow_cursor = FALSE; -int display_units = MEGABYTES; -int zero_table = FALSE; -int print_only = 0; - -/* Curses screen information */ -int cur_part = 0; -int warning_last_time = FALSE; -int defined = FALSE; -int COLUMNS = 80; -int NUM_ON_SCREEN = 1; - -/* Y coordinates */ -int HEADER_START = 0; -int DISK_TABLE_START = 5; -int WARNING_START = 23; -int COMMAND_LINE_Y = 21; - -/* X coordinates */ -int NAME_START = 4; -int FLAGS_START = 16; -int PTYPE_START = 30; -int FSTYPE_START = 45; -int SIZE_START = 70; -int COMMAND_LINE_X = 5; - -#define NUM_PART_TYPES 256 -char *partition_type[NUM_PART_TYPES] = { - [LINUX_MINIX] = "Linux/MINIX", - [LINUX_SWAP] = "Linux Swap", - [LINUX] = "Linux", - [FREE_SPACE] = "Free Space", - [EXTENDED] = "Extended", - [0x01] = "DOS 12-bit FAT", - [0x04] = "DOS 16-bit < 32Mb", - [0x06] = "DOS 16-bit >=32Mb", - [0x07] = "OS/2 HPFS", - [0x0A] = "OS/2 Boot Manager", - [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. - */ - - [0x02] = "XENIX root", - [0x03] = "XENIX usr", - [0x08] = "AIX", - [0x09] = "AIX bootable", - [0x40] = "Venix 80286", - [0x51] = "Novell?", - [0x52] = "Microport", - [0x63] = "GNU HURD", - [0x64] = "Novell", - [0x75] = "PC/IX", - [0x80] = "Old MINIX", - [0x93] = "Amoeba", - [0x94] = "Amoeba BBT", - [0xB7] = "BSDI fs", - [0xB8] = "BSDI swap", - [0xC7] = "Syrinx", - [0xDB] = "CP/M", - [0xE1] = "DOS access", - [0xE3] = "DOS R/O", - [0xF2] = "DOS secondary", - [0xFF] = "BBT" -}; - -void fdexit(int ret) -{ - if (opened) - close(fd); - - if (changed) { - fprintf(stderr, "Disk has been changed.\n"); - fprintf(stderr, "Reboot the system to ensure the partition " - "table is correctly updated.\n"); - - fprintf( stderr, "\nWARNING: If you have created or modified any\n" - "DOS 6.x partitions, please see the cfdisk manual\n" - "page for additional information.\n" ); - } - - - exit(ret); -} - -int get_string(char *str, int len, char *def) -{ - char c; - int i = 0; - int x, y; - int use_def = FALSE; - - getyx(stdscr, y, x); - clrtoeol(); - - str[i] = 0; - - if (def != NULL) { - mvaddstr(y, x, def); - move(y, x); - use_def = TRUE; - } - - refresh(); - while ((c = getch()) != '\n' && c != CR) { - switch (c) { - case ESC: - move(y, x); - clrtoeol(); - refresh(); - return GS_ESCAPE; - case DEL: - case '\b': - if (i > 0) { - str[--i] = 0; - mvaddch(y, x+i, ' '); - move(y, x+i); - } else if (use_def) { - clrtoeol(); - use_def = FALSE; - } else - putchar(BELL); - break; - default: - if (i < len && isprint(c)) { - mvaddch(y, x+i, c); - if (use_def) { - clrtoeol(); - use_def = FALSE; - } - str[i++] = c; - str[i] = 0; - } else - putchar(BELL); - } - refresh(); - } - - if (use_def) - return GS_DEFAULT; - else - return i; -} - -void clear_warning(void) -{ - int i; - - if (!warning_last_time) - return; - - move(WARNING_START,0); - for (i = 0; i < COLS; i++) - addch(' '); - - warning_last_time = FALSE; -} - -void print_warning(char *s) -{ - mvaddstr(WARNING_START, (COLS-strlen(s))/2, s); - putchar(BELL); /* CTRL-G */ - - warning_last_time = TRUE; -} - -void fatal(char *s) -{ - char str[LINE_LENGTH]; - - sprintf(str, "FATAL ERROR: %s", s); - mvaddstr(WARNING_START, (COLS-strlen(str))/2, str); - sprintf(str, "Press any key to exit fdisk"); - mvaddstr(WARNING_START+1, (COLS-strlen(str))/2, str); - putchar(BELL); /* CTRL-G */ - - refresh(); - - (void)getch(); - - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); - mvcur(0, COLS-1, LINES-1, 0); - nl(); - endwin(); - fdexit(1); -} - -void read_sector(char *buffer, int sect_num) -{ - if (ext2_llseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0) - fatal(BAD_SEEK); - if (read(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(BAD_READ); -} - -void write_sector(char *buffer, int sect_num) -{ - if (ext2_llseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0) - fatal(BAD_SEEK); - if (write(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(BAD_WRITE); -} - -void check_part_info(void) -{ - int i, pri = 0, log = 0; - - for (i = 0; i < num_parts; i++) - if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num)) - pri++; - else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num)) - log++; - if (ext_info.id == EXTENDED) - if (log > 0) - pri++; - else { - ext_info.first_sector = 0; - ext_info.last_sector = 0; - ext_info.offset = 0; - ext_info.flags = 0; - ext_info.id = FREE_SPACE; - ext_info.num = PRIMARY; - } - - if (pri >= 4) - for (i = 0; i < num_parts; i++) - if (p_info[i].id == FREE_SPACE || p_info[i].id == UNUSABLE) - if (ext_info.id == EXTENDED) - if (p_info[i].first_sector >= ext_info.first_sector && - p_info[i].last_sector <= ext_info.last_sector) { - p_info[i].id = FREE_SPACE; - p_info[i].num = LOGICAL; - } else if (i > 0 && - p_info[i-1].first_sector >= - ext_info.first_sector && - p_info[i-1].last_sector <= - ext_info.last_sector) { - p_info[i].id = FREE_SPACE; - p_info[i].num = LOGICAL; - } else if (i < num_parts-1 && - p_info[i+1].first_sector >= - ext_info.first_sector && - p_info[i+1].last_sector <= - ext_info.last_sector) { - p_info[i].id = FREE_SPACE; - p_info[i].num = LOGICAL; - } else - p_info[i].id = UNUSABLE; - else /* if (ext_info.id != EXTENDED) */ - p_info[i].id = UNUSABLE; - else /* if (p_info[i].id > 0) */ - while (0); /* Leave these alone */ - else /* if (pri < 4) */ - for (i = 0; i < num_parts; i++) { - if (p_info[i].id == UNUSABLE) - p_info[i].id = FREE_SPACE; - if (p_info[i].id == FREE_SPACE) - if (ext_info.id == EXTENDED) - if (p_info[i].first_sector >= ext_info.first_sector && - p_info[i].last_sector <= ext_info.last_sector) - p_info[i].num = LOGICAL; - else if (i > 0 && - p_info[i-1].first_sector >= - ext_info.first_sector && - p_info[i-1].last_sector <= - ext_info.last_sector) - p_info[i].num = PRI_OR_LOG; - else if (i < num_parts-1 && - p_info[i+1].first_sector >= - ext_info.first_sector && - p_info[i+1].last_sector <= - ext_info.last_sector) - p_info[i].num = PRI_OR_LOG; - else - p_info[i].num = PRIMARY; - else /* if (ext_info.id != EXTENDED) */ - p_info[i].num = PRI_OR_LOG; - else /* if (p_info[i].id > 0) */ - while (0); /* Leave these alone */ - } -} - -void remove_part(int i) -{ - int p; - - for (p = i; p < num_parts; p++) - p_info[p] = p_info[p+1]; - - num_parts--; -} - -void insert_part(int i, int num, int id, int flags, int first, int last, - int offset) -{ - int p; - - for (p = num_parts; p > i; p--) - p_info[p] = p_info[p-1]; - - p_info[i].first_sector = first; - p_info[i].last_sector = last; - p_info[i].offset = offset; - p_info[i].flags = flags; - p_info[i].id = id; - p_info[i].num = num; - - num_parts++; -} - -void del_part(int i) -{ - int num = p_info[i].num; - - if (i > 0 && (p_info[i-1].id == FREE_SPACE || - p_info[i-1].id == UNUSABLE)) { - /* Merge with previous partition */ - p_info[i-1].last_sector = p_info[i].last_sector; - remove_part(i--); - } - - if (i < num_parts - 1 && (p_info[i+1].id == FREE_SPACE || - p_info[i+1].id == UNUSABLE)) { - /* Merge with next partition */ - p_info[i+1].first_sector = p_info[i].first_sector; - remove_part(i); - } - - if (i > 0) - p_info[i].first_sector = p_info[i-1].last_sector + 1; - else - p_info[i].first_sector = 0; - - if (i < num_parts - 1) - p_info[i].last_sector = p_info[i+1].first_sector - 1; - else - p_info[i].last_sector = sectors*heads*cylinders - 1; - - p_info[i].offset = 0; - p_info[i].flags = 0; - p_info[i].id = FREE_SPACE; - p_info[i].num = PRI_OR_LOG; - - if (IS_LOGICAL(num)) { - /* We have a logical partition --> shrink the extended partition - * if (1) this is the first logical drive, or (2) this is the - * last logical drive; and if there are any other logical drives - * then renumber the ones after "num". - */ - if (i == 0 || (i > 0 && IS_PRIMARY(p_info[i-1].num))) - ext_info.first_sector = p_info[i].last_sector + 1; - if (i == num_parts-1 || - (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num))) - ext_info.last_sector = p_info[i].first_sector - 1; - for (i = 0; i < num_parts; i++) - if (p_info[i].num > num) - p_info[i].num--; - } - - /* Clean up the rest of the partitions */ - check_part_info(); -} - -int add_part(int num, int id, int flags, int first, int last, int offset) -{ - int i, pri = 0, log = 0; - - if (num_parts == MAXIMUM_PARTS || - first < 0 || - first >= cylinders*heads*sectors || - last < 0 || - last >= cylinders*heads*sectors) - return -1; - - for (i = 0; i < num_parts; i++) - if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num)) - pri++; - else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num)) - log++; - if (ext_info.id == EXTENDED && log > 0) - pri++; - - if (IS_PRIMARY(num)) - if (pri >= 4) - return -1; - else - pri++; - - for (i = 0; p_info[i].last_sector < first; i++); - - if (p_info[i].id != FREE_SPACE || last > p_info[i].last_sector) - return -1; - - if (id == EXTENDED) - if (ext_info.id != FREE_SPACE) - return -1; - else if (IS_PRIMARY(num)) { - ext_info.first_sector = first; - ext_info.last_sector = last; - ext_info.offset = offset; - ext_info.flags = flags; - ext_info.id = EXTENDED; - ext_info.num = num; - - return 0; - } else - return -1; - - if (IS_LOGICAL(num)) { - if (ext_info.id != EXTENDED) { - print_warning("!!!! Internal error creating logical " - "drive with no extended partition !!!!"); - } else { - /* We might have a logical partition outside of the extended - * partition's range --> we have to extend the extended - * partition's range to encompass this new partition, but we - * must make sure that there are no primary partitions between - * it and the closest logical drive in extended partition. - */ - if (first < ext_info.first_sector) { - if (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num)) { - print_warning(TWO_EXTENDEDS); - return -1; - } else { - if (first == 0) { - ext_info.first_sector = 0; - ext_info.offset = first = offset; - } else - ext_info.first_sector = first; - } - } else if (last > ext_info.last_sector) { - if (i > 0 && IS_PRIMARY(p_info[i-1].num)) { - print_warning(TWO_EXTENDEDS); - return -1; - } else - ext_info.last_sector = last; - } - } - } - - if (first != p_info[i].first_sector && - !(IS_LOGICAL(num) && first == offset)) { - insert_part(i, PRI_OR_LOG, FREE_SPACE, 0, - p_info[i].first_sector, first-1, 0); - i++; - } - - if (last != p_info[i].last_sector) - insert_part(i+1, PRI_OR_LOG, FREE_SPACE, 0, - last+1, p_info[i].last_sector, 0); - - p_info[i].first_sector = first; - p_info[i].last_sector = last; - p_info[i].offset = offset; - p_info[i].flags = flags; - p_info[i].id = id; - p_info[i].num = num; - - check_part_info(); - - return 0; -} - -int find_primary(void) -{ - int num = 0, cur = 0; - - while (cur < num_parts && IS_PRIMARY(num)) - if ((p_info[cur].id > 0 && p_info[cur].num == num) || - (ext_info.id == EXTENDED && ext_info.num == num)) { - num++; - cur = 0; - } else - cur++; - - if (!IS_PRIMARY(num)) - return -1; - else - return num; -} - -int find_logical(int i) -{ - int num = -1; - int j; - - for (j = i; j < num_parts && num == -1; j++) - if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num)) - num = p_info[j].num; - - if (num == -1) { - num = 4; - for (j = 0; j < num_parts; j++) - if (p_info[j].id > 0 && p_info[j].num == num) - num++; - } - - return num; -} - -void inc_logical(int i) -{ - int j; - - for (j = i; j < num_parts; j++) - if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num)) - p_info[j].num++; -} - -void new_part(int i) -{ - char response[LINE_LENGTH], def[LINE_LENGTH]; - char c; - int first = p_info[i].first_sector; - int last = p_info[i].last_sector; - int offset = 0; - int flags = 0; - int id = LINUX; - int num = -1; - int num_sects = last - first + 1; - int len, ext, j; - - if (p_info[i].num == PRI_OR_LOG) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Primary or logical [pl]: "); - clrtoeol(); - refresh(); - while (toupper(c = getch()) != 'P' && toupper(c) != 'L' && c != ESC); - if (toupper(c) == 'P') - num = find_primary(); - else if (toupper(c) == 'L') - num = find_logical(i); - else - return; - } else if (p_info[i].num == PRIMARY) - num = find_primary(); - else if (p_info[i].num == LOGICAL) - num = find_logical(i); - else - print_warning("!!! Internal error !!!"); - - sprintf(def, "%.2f", ceiling(num_sects/20.48)/100); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Size (in MB): "); - if ((len = get_string(response, LINE_LENGTH, def)) <= 0 && - len != GS_DEFAULT) - return; - else if (len > 0) { -#define num_cyls(bytes) (round_int(bytes/SECTOR_SIZE/(sectors*heads))) - for (j = 0; - j < len-1 && (isdigit(response[j]) || response[j] == '.'); - j++); - if (toupper(response[j]) == 'K') { - num_sects = num_cyls(atof(response)*1024)*sectors*heads; - } else if (toupper(response[j]) == 'M') { - num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads; - } else if (toupper(response[j]) == 'C') { - num_sects = round_int(atof(response))*sectors*heads; - } else if (toupper(response[j]) == 'S') { - num_sects = round_int(atof(response)); - } else { - num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads; - } - } - - if (num_sects <= 0 || - num_sects > p_info[i].last_sector - p_info[i].first_sector + 1) - return; - - if (num_sects < p_info[i].last_sector - p_info[i].first_sector + 1) { - /* Determine where inside free space to put partition. - */ - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Add partition at beginning or end of free space [be]: "); - clrtoeol(); - refresh(); - while (toupper(c = getch()) != 'B' && toupper(c) != 'E' && c != ESC); - if (toupper(c) == 'B') - last = first + num_sects - 1; - else if (toupper(c) == 'E') - first = last - num_sects + 1; - else - return; - } - - if (IS_LOGICAL(num) && ext_info.id != EXTENDED) { - /* We want to add a logical partition, but need to create an - * extended partition first. - */ - if ((ext = find_primary()) < 0) { - print_warning(NEED_EXT); - return; - } - (void)add_part(ext, EXTENDED, 0, first, last, - (first == 0 ? sectors : 0)); - } - - if (IS_LOGICAL(num)) - inc_logical(i); - - /* Now we have a complete partition to ourselves */ - if (first == 0 || IS_LOGICAL(num)) - offset = sectors; - - (void)add_part(num, id, flags, first, last, offset); -} - -void clear_p_info(void) -{ - num_parts = 1; - p_info[0].first_sector = 0; - p_info[0].last_sector = sectors*heads*cylinders - 1; - p_info[0].offset = 0; - p_info[0].flags = 0; - p_info[0].id = FREE_SPACE; - p_info[0].num = PRI_OR_LOG; - - ext_info.first_sector = 0; - ext_info.last_sector = 0; - ext_info.offset = 0; - ext_info.flags = 0; - ext_info.id = FREE_SPACE; - ext_info.num = PRIMARY; -} - -void fill_p_info(void) -{ - int p, i; - struct hd_geometry geometry; - partition_table buffer; - partition_info tmp_ext = { 0, 0, 0, 0, FREE_SPACE, PRIMARY }; - - if ((fd = open(disk_device, O_RDWR)) < 0) - fatal(BAD_OPEN); - read_sector(buffer.c.b, 0); - - if (!ioctl(fd, HDIO_GETGEO, &geometry)) { - if (!heads) - heads = geometry.heads; - if (!sectors) - sectors = geometry.sectors; - if (!cylinders) - cylinders = geometry.cylinders; - } - - if (!heads || !sectors || !cylinders) - fatal(BAD_GEOMETRY); - - clear_p_info(); - - if (!zero_table) { - for (i = 0; i < 4; i++) { - if (buffer.p.part[i].sys_ind > 0 && - add_part(i, - buffer.p.part[i].sys_ind, - buffer.p.part[i].boot_ind, - ((buffer.p.part[i].start_sect <= sectors) ? - 0 : buffer.p.part[i].start_sect), - buffer.p.part[i].start_sect + - buffer.p.part[i].nr_sects - 1, - ((buffer.p.part[i].start_sect <= sectors) ? - buffer.p.part[i].start_sect : 0))) { - fatal(BAD_PRIMARY); - } - if (buffer.p.part[i].sys_ind == EXTENDED) - tmp_ext = ext_info; - } - - if (tmp_ext.id == EXTENDED) { - ext_info = tmp_ext; - logical_sectors[logical] = ext_info.first_sector; - read_sector(buffer.c.b, logical_sectors[logical++]); - i = 4; - do { - for (p = 0; - p < 4 && (!buffer.p.part[p].sys_ind || - buffer.p.part[p].sys_ind == 5); - p++); - if (p > 3) - fatal(BAD_LOGICAL); - - if (add_part(i++, - buffer.p.part[p].sys_ind, - buffer.p.part[p].boot_ind, - logical_sectors[logical-1], - logical_sectors[logical-1] + - buffer.p.part[p].start_sect + - buffer.p.part[p].nr_sects - 1, - buffer.p.part[p].start_sect)) { - fatal(BAD_LOGICAL); - } - - for (p = 0; - p < 4 && buffer.p.part[p].sys_ind != 5; - p++); - if (p < 4) { - logical_sectors[logical] = - ext_info.first_sector + buffer.p.part[p].start_sect; - read_sector(buffer.c.b, logical_sectors[logical++]); - } - } while (p < 4 && logical < MAXIMUM_PARTS-4); - } - } -} - -void fill_part_table(struct partition *p, partition_info *pi) -{ - int sects; - - p->boot_ind = pi->flags; - p->sys_ind = pi->id; - if (IS_LOGICAL(pi->num)) - p->start_sect = pi->offset; - else - p->start_sect = pi->first_sector + pi->offset; - p->nr_sects = pi->last_sector - (pi->first_sector+pi->offset) + 1; - sects = (((pi->first_sector+pi->offset)/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->first_sector+pi->offset); - set_hsc(p->head, p->sector, p->cyl, sects); - sects = ((pi->last_sector/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->last_sector); - set_hsc(p->end_head, p->end_sector, p->end_cyl, sects); -} - -void fill_primary_table(partition_table *buffer) -{ - int i; - - /* Zero out existing table */ - for (i = 0x1BE; i < SECTOR_SIZE; i++) - buffer->c.b[i] = 0; - - for (i = 0; i < num_parts; i++) - if (IS_PRIMARY(p_info[i].num)) - fill_part_table(&(buffer->p.part[p_info[i].num]), &(p_info[i])); - - if (ext_info.id == EXTENDED) - fill_part_table(&(buffer->p.part[ext_info.num]), &ext_info); - - buffer->p.flag = PART_TABLE_FLAG; -} - -void fill_logical_table(partition_table *buffer, partition_info *pi) -{ - struct partition *p; - int i, sects; - - for (i = 0; i < logical && pi->first_sector != logical_sectors[i]; i++); - if (i == logical || buffer->p.flag != (unsigned short)PART_TABLE_FLAG) - for (i = 0; i < SECTOR_SIZE; i++) - buffer->c.b[i] = 0; - - /* Zero out existing table */ - for (i = 0x1BE; i < SECTOR_SIZE; i++) - buffer->c.b[i] = 0; - - fill_part_table(&(buffer->p.part[0]), pi); - - for (i = 0; - i < num_parts && pi->num != p_info[i].num - 1; - i++); - - if (i < num_parts) { - p = &(buffer->p.part[1]); - pi = &(p_info[i]); - - p->boot_ind = 0; - p->sys_ind = 5; - p->start_sect = pi->first_sector - ext_info.first_sector; - p->nr_sects = pi->last_sector - pi->first_sector + 1; - sects = ((pi->first_sector/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->first_sector); - set_hsc(p->head, p->sector, p->cyl, sects); - sects = ((pi->last_sector/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->last_sector); - set_hsc(p->end_head, p->end_sector, p->end_cyl, sects); - } - - buffer->p.flag = PART_TABLE_FLAG; -} - -void write_part_table(void) -{ - int i, done = FALSE, len; - partition_table buffer; - char response[LINE_LENGTH]; - - print_warning(WRITE_WARN); - - while (!done) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Are you sure you want write the partition table to disk? (yes or no): "); - - len = get_string(response, LINE_LENGTH, NULL); - - clear_warning(); - - if (len == GS_ESCAPE) - return; - else if (len == 2 && - toupper(response[0]) == 'N' && - toupper(response[1]) == 'O') { - print_warning(NO_WRITE); - return; - } else if (len == 3 && - toupper(response[0]) == 'Y' && - toupper(response[1]) == 'E' && - toupper(response[2]) == 'S') - done = TRUE; - else - print_warning(YES_NO); - } - - clear_warning(); - print_warning(WRITING_PART); - refresh(); - - read_sector(buffer.c.b, 0); - fill_primary_table(&buffer); - write_sector(buffer.c.b, 0); - - for (i = 0; i < num_parts; i++) - if (IS_LOGICAL(p_info[i].num)) { - /* Read the extended partition table from disk ??? KEM */ - read_sector(buffer.c.b, p_info[i].first_sector); - fill_logical_table(&buffer, &(p_info[i])); - write_sector(buffer.c.b, p_info[i].first_sector); - } - - sync(); - sleep(2); - if (!ioctl(fd,BLKRRPART)) - changed = TRUE; - sync(); - sleep(4); - - clear_warning(); - if (changed) - print_warning(YES_WRITE); - else - print_warning(RRPART_FAILED); -} - -void fp_printf(FILE *fp, char *format, ...) -{ - va_list args; - char buf[1024]; - int y, x; - - va_start(args, format); - vsprintf(buf, format, args); - va_end(args); - - if (fp == NULL) { - /* The following works best if the string to be printed has at - most only one newline. */ - printw("%s", buf); - getyx(stdscr, y, x); - if (y >= COMMAND_LINE_Y-2) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - erase(); - move(0, 0); - } - } else - fprintf(fp, "%s", buf); -} - -#define MAX_PER_LINE 16 -void print_file_buffer(FILE *fp, char *buffer) -{ - int i,l; - - for (i = 0, l = 0; i < SECTOR_SIZE; i++, l++) { - if (l == 0) - fp_printf(fp, "0x%03X:", i); - fp_printf(fp, " %02X", (unsigned char) buffer[i]); - if (l == MAX_PER_LINE - 1) { - fp_printf(fp, "\n"); - l = -1; - } - } - if (l > 0) - fp_printf(fp, "\n"); - fp_printf(fp, "\n"); -} - -void print_raw_table(void) -{ - int i, to_file; - partition_table buffer; - char fname[LINE_LENGTH]; - FILE *fp; - - if (print_only) { - fp = stdout; - to_file = TRUE; - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); - - if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) - return; - - if (to_file) { - if ((fp = fopen(fname, "w")) == NULL) { - char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); - print_warning(errstr); - return; - } - } else { - fp = NULL; - erase(); - move(0, 0); - } - } - - fp_printf(fp, "Disk Drive: %s\n", disk_device); - - read_sector(buffer.c.b, 0); - fill_primary_table(&buffer); - print_file_buffer(fp, buffer.c.b); - - for (i = 0; i < num_parts; i++) - if (IS_LOGICAL(p_info[i].num)) { - read_sector(buffer.c.b, p_info[i].first_sector); - fill_logical_table(&buffer, &(p_info[i])); - print_file_buffer(fp, buffer.c.b); - } - - if (to_file) { - if (!print_only) - fclose(fp); - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - } -} - -void print_p_info_entry(FILE *fp, partition_info *p) -{ - int size; - char part_str[21]; - - if (p->id == UNUSABLE) - fp_printf(fp, " None "); - else if (p->id == FREE_SPACE && p->num == PRI_OR_LOG) - fp_printf(fp, " Pri/Log"); - else if (p->id == FREE_SPACE && p->num == PRIMARY) - fp_printf(fp, " Primary"); - else if (p->id == FREE_SPACE && p->num == LOGICAL) - fp_printf(fp, " Logical"); - else - fp_printf(fp, "%2d %-7.7s", p->num+1, - IS_LOGICAL(p->num) ? "Logical" : "Primary"); - - fp_printf(fp, " "); - - fp_printf(fp, "%7d%c", p->first_sector, - ((p->first_sector/(sectors*heads)) != - ((float)p->first_sector/(sectors*heads)) ? - '*' : ' ')); - - fp_printf(fp, " "); - - fp_printf(fp, "%7d%c", p->last_sector, - (((p->last_sector+1)/(sectors*heads)) != - ((float)(p->last_sector+1)/(sectors*heads)) ? - '*' : ' ')); - - fp_printf(fp, " "); - - fp_printf(fp, "%6d%c", p->offset, - ((((p->first_sector == 0 || IS_LOGICAL(p->num)) && - (p->offset != sectors)) || - (p->first_sector != 0 && IS_PRIMARY(p->num) && - p->offset != 0)) ? - '#' : ' ')); - - fp_printf(fp, " "); - - size = p->last_sector - p->first_sector + 1; - fp_printf(fp, "%7d%c", size, - ((size/(sectors*heads)) != ((float)size/(sectors*heads)) ? - '*' : ' ')); - - fp_printf(fp, " "); - - if (p->id == UNUSABLE) - sprintf(part_str, "%.16s", "Unusable"); - else if (p->id == FREE_SPACE) - sprintf(part_str, "%.16s", "Free Space"); - else if (partition_type[p->id]) - sprintf(part_str, "%.16s (%02X)", partition_type[p->id], p->id); - else - sprintf(part_str, "%.16s (%02X)", "Unknown", p->id); - fp_printf(fp, "%-21.21s", part_str); - - fp_printf(fp, " "); - - if (p->flags == ACTIVE_FLAG) - fp_printf(fp, "Boot (%02X)", p->flags); - else if (p->flags != 0) - fp_printf(fp, "Unknown (%02X)", p->flags); - else - fp_printf(fp, "None (%02X)", p->flags); - - fp_printf(fp, "\n"); -} - -void print_p_info(void) -{ - char fname[LINE_LENGTH]; - FILE *fp; - int i, to_file, pext = (ext_info.id == EXTENDED); - - if (print_only) { - fp = stdout; - to_file = TRUE; - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); - - if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) - return; - - if (to_file) { - if ((fp = fopen(fname, "w")) == NULL) { - char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); - print_warning(errstr); - return; - } - } else { - fp = NULL; - erase(); - move(0, 0); - } - } - - fp_printf(fp, "Partition Table for %s\n", disk_device); - fp_printf(fp, "\n"); - fp_printf(fp, " First Last\n"); - fp_printf(fp, " # Type Sector Sector Offset Length Filesystem Type (ID) Flags\n"); - fp_printf(fp, "-- ------- -------- -------- ------- -------- --------------------- ---------\n"); - - for (i = 0; i < num_parts; i++) { - if (pext && (p_info[i].first_sector >= ext_info.first_sector)) { - print_p_info_entry(fp,&ext_info); - pext = FALSE; - } - print_p_info_entry(fp, &(p_info[i])); - } - - if (to_file) { - if (!print_only) - fclose(fp); - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - } -} - -void print_part_entry(FILE *fp, int num, partition_info *pi) -{ - int first = 0, start = 0, end = 0, size = 0; - int ss = 0, sh = 0, sc = 0; - int es = 0, eh = 0, ec = 0; - int flags = 0, id = 0; - - if (pi != NULL) { - flags = pi->flags; - id = pi->id; - - if (IS_LOGICAL(num)) - first = pi->offset; - else - first = pi->first_sector + pi->offset; - - start = pi->first_sector + pi->offset; - end = pi->last_sector; - size = end - start + 1; - if ((start/(sectors*heads)) > 1023) - start = heads*sectors*1024 - 1; - if ((end/(sectors*heads)) > 1023) - end = heads*sectors*1024 - 1; - - ss = start % sectors + 1; - start /= sectors; - sh = start % heads; - sc = start / heads; - - es = end % sectors + 1; - end /= sectors; - eh = end % heads; - ec = end / heads; - } - - fp_printf(fp, "%2d 0x%02X %4d %4d %4d 0x%02X %4d %4d %4d %7d %7d\n", - num+1, flags, sh, ss, sc, id, eh, es, ec, first, size); -} - - -void print_part_table(void) -{ - int i, j, to_file; - char fname[LINE_LENGTH]; - FILE *fp; - - if (print_only) { - fp = stdout; - to_file = TRUE; - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); - - if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) - return; - - if (to_file) { - if ((fp = fopen(fname, "w")) == NULL) { - char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); - print_warning(errstr); - return; - } - } else { - fp = NULL; - erase(); - move(0, 0); - } - } - - fp_printf(fp, "Partition Table for %s\n", disk_device); - fp_printf(fp, "\n"); - fp_printf(fp, " ---Starting--- ----Ending---- Start Number\n"); - fp_printf(fp, " # Flags Head Sect Cyl ID Head Sect Cyl Sector Sectors\n"); - fp_printf(fp, "-- ----- ---- ---- ---- ---- ---- ---- ---- ------- -------\n"); - - for (i = 0; i < 4; i++) { - for (j = 0; - j < num_parts && (p_info[j].id <= 0 || p_info[j].num != i); - j++); - if (j < num_parts) { - print_part_entry(fp, i, &(p_info[j])); - } else if (ext_info.id == EXTENDED && ext_info.num == i) { - print_part_entry(fp, i, &ext_info); - } else { - print_part_entry(fp, i, NULL); - } - } - - for (i = 0; i < num_parts; i++) - if (IS_LOGICAL(p_info[i].num)) - print_part_entry(fp, p_info[i].num, &(p_info[i])); - - if (to_file) { - if (!print_only) - fclose(fp); - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - } -} - -void print_tables(void) -{ - int done = FALSE; - - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Print format [rst]: "); - clrtoeol(); - refresh(); - - while (!done) - switch (toupper(getch())) { - case 'R': - print_raw_table(); - done = TRUE; - break; - case 'S': - print_p_info(); - done = TRUE; - break; - case 'T': - print_part_table(); - done = TRUE; - break; - case ESC: - done = TRUE; - break; - } -} - -#define END_OF_HELP "EOHS!" -#define NEW_HELP_SCREEN "SNHS!" -void display_help() -{ - char *help_text[] = { - "Help Screen for cfdisk " VERSION, - "", - "This is cfdisk, a curses based disk partitioning programs, which", - "allows you to create, delete and modify partitions on your hard", - "disk drive.", - "", - "Copyright (C) 1994 Kevin E. Martin", - "", - "Command Meaning", - "------- -------", - " b Toggle bootable flag of the current partition", - " d Delete the current partition", - " g Change cylinders, heads, sectors-per-track parameters", - " WARNING: This option should only be used by people who", - " know what they are doing.", - " h Print this screen", - " m Maximize disk usage of the current partition", - " Note: This may make the partition incompatible with", - " DOS, OS/2, ...", - " n Create new partition from free space", - " p Print partition table to the screen or to a file", - " There are several different formats for the partition", - " that you can choose from:", - " r - Raw data (exactly what would be written to disk)", - " s - Table ordered by sectors", - " t - Table in raw format", - " q Quit program without writing partition table", - " t Change the filesystem type", - " u Change units of the partition size display", - " Rotates through Mb, sectors and cylinders", - " W Write partition table to disk (must enter upper case W)", - " Since this might destroy data on the disk, you must", - " either confirm or deny the write by entering `yes' or", - " `no'", - "Up Arrow Move cursor to the previous partition", - "Down Arrow Move cursor to the next partition", - "CTRL-L Redraws the screen", - " ? Print this screen", - "", - "Note: All of the commands can be entered with either upper or lower", - "case letters (except for Writes).", - END_OF_HELP - }; - - int cur_line = 0; - FILE *fp = NULL; - - erase(); - move(0, 0); - while (strcmp(help_text[cur_line], END_OF_HELP)) - if (!strcmp(help_text[cur_line], NEW_HELP_SCREEN)) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - erase(); - move(0, 0); - cur_line++; - } else - fp_printf(fp, "%s\n", help_text[cur_line++]); - - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); -} - -int change_geometry(void) -{ - int ret_val = FALSE; - int done = FALSE; - char def[LINE_LENGTH]; - char response[LINE_LENGTH]; - int tmp_val; - - while (!done) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Change disk geometry information [chs]: "); - clrtoeol(); - refresh(); - - clear_warning(); - - switch (toupper(getch())) { - case 'C': - sprintf(def, "%d", cylinders); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of cylinders: "); - if (get_string(response, LINE_LENGTH, def) > 0) { - tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_CYLINDERS) { - cylinders = tmp_val; - ret_val = TRUE; - } else - print_warning(BAD_CYLINDERS); - } - break; - case 'H': - sprintf(def, "%d", heads); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of heads: "); - if (get_string(response, LINE_LENGTH, def) > 0) { - tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_HEADS) { - heads = tmp_val; - ret_val = TRUE; - } else - print_warning(BAD_HEADS); - } - break; - case 'S': - sprintf(def, "%d", sectors); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of sectors per track: "); - if (get_string(response, LINE_LENGTH, def) > 0) { - tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_SECTORS) { - sectors = tmp_val; - ret_val = TRUE; - } else - print_warning(BAD_SECTORS); - } - break; - case ESC: - case CR: - done = TRUE; - break; - default: - putchar(BELL); - break; - } - } - - if (ret_val) { - if (p_info[num_parts-1].last_sector > heads*sectors*cylinders-1) { - while (p_info[num_parts-1].first_sector > heads*sectors*cylinders-1) { - if (p_info[num_parts-1].id == FREE_SPACE || - p_info[num_parts-1].id == UNUSABLE) - remove_part(num_parts-1); - else - del_part(num_parts-1); - } - - p_info[num_parts-1].last_sector = heads*sectors*cylinders - 1; - - if (ext_info.last_sector > heads*sectors*cylinders-1) - ext_info.last_sector = heads*sectors*cylinders - 1; - } else if (p_info[num_parts-1].last_sector < heads*sectors*cylinders-1) { - if (p_info[num_parts-1].id == FREE_SPACE || - p_info[num_parts-1].id == UNUSABLE) { - p_info[num_parts-1].last_sector = heads*sectors*cylinders - 1; - } else { - insert_part(num_parts, PRI_OR_LOG, FREE_SPACE, 0, - p_info[num_parts-1].last_sector+1, - heads*sectors*cylinders-1, 0); - } - } - - /* Make sure the partitions are correct */ - check_part_info(); - } - - return ret_val; -} - -void change_id(int i) -{ - char id[LINE_LENGTH], def[LINE_LENGTH]; - int num_types = 0; - int num_across, num_down; - int len, new_id = LINUX; - int y_start, y_end; - int j, pos; - - for (num_types = 0, j = 1; j < NUM_PART_TYPES; j++) - if (partition_type[j]) - num_types++; - - num_across = COLS/COL_ID_WIDTH; - num_down = (((float)num_types)/num_across + 1); - y_start = COMMAND_LINE_Y - 1 - num_down; - if (y_start > DISK_TABLE_START+cur_part+4) - y_start = DISK_TABLE_START+cur_part+4; - y_end = y_start + num_down - 1; - - for (j = y_start - 1; j <= y_end + 1; j++) { - move(j, 0); - clrtoeol(); - } - - for (pos = 0, j = 1; j < NUM_PART_TYPES; j++) - if (partition_type[j]) { - move(y_start + pos % num_down, (pos/num_down)*COL_ID_WIDTH + 1); - printw("%02X %-16.16s", j, partition_type[j]); - pos++; - } - - sprintf(def, "%02X", new_id); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Enter filesystem type: "); - if ((len = get_string(id, 2, def)) <= 0 && len != GS_DEFAULT) - return; - - if (len != GS_DEFAULT) { - if (!isxdigit(id[0])) - return; - new_id = (isdigit(id[0]) ? id[0] - '0' : tolower(id[0]) - 'a' + 10); - if (len == 2) - if (isxdigit(id[1])) - new_id = new_id*16 + - (isdigit(id[1]) ? id[1] - '0' : tolower(id[1]) - 'a' + 10); - else - return; - } - - if (new_id == 0) - print_warning(ID_EMPTY); - else if (new_id == EXTENDED) - print_warning(ID_EXT); - else - p_info[i].id = new_id; -} - -void draw_partition(int i) -{ - int size, j; - int y = i + DISK_TABLE_START + 2 - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN; - - if (!arrow_cursor) { - move(y, 0); - for (j = 0; j < COLS; j++) - addch(' '); - } - - if (p_info[i].id > 0) { - mvprintw(y, NAME_START, - "%s%d", disk_device, p_info[i].num+1); - if (p_info[i].flags) { - if (p_info[i].flags == ACTIVE_FLAG) - mvaddstr(y, FLAGS_START, "Boot"); - else - mvprintw(y, FLAGS_START, "Unk(%02X)", p_info[i].flags); - if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) { - if (p_info[i].offset != sectors) - addstr(", NC"); - } else { - if (p_info[i].offset != 0) - addstr(", NC"); - } - } else { - if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) { - if (p_info[i].offset != sectors) - mvaddstr(y, FLAGS_START, "NC"); - } else { - if (p_info[i].offset != 0) - mvaddstr(y, FLAGS_START, "NC"); - } - } - } - mvaddstr(y, PTYPE_START, - (p_info[i].id == UNUSABLE ? "" : - (IS_LOGICAL(p_info[i].num) ? "Logical" : - (p_info[i].num >= 0 ? "Primary" : - (p_info[i].num == PRI_OR_LOG ? "Pri/Log" : - (p_info[i].num == PRIMARY ? "Primary" : "Logical")))))); - 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]); - else - mvprintw(y, FSTYPE_START, "Unknown (%02X)", p_info[i].id); - - size = p_info[i].last_sector - p_info[i].first_sector + 1; - if (display_units == SECTORS) - mvprintw(y, SIZE_START, "%9d", size); - else if (display_units == CYLINDERS) - mvprintw(y, SIZE_START, "%9d", size/(sectors*heads)); - else - mvprintw(y, SIZE_START, "%9.2f", ceiling(size/20.48)/100); - if (((size/(sectors*heads)) != ceiling(size/(sectors*(float)heads))) || - ((p_info[i].first_sector/(sectors*heads)) != - ceiling(p_info[i].first_sector/(sectors*heads)))) - mvprintw(y, COLUMNS-1, "*"); -} - -void init_const(void) -{ - if (!defined) { - NAME_START = (((float)NAME_START)/COLUMNS)*COLS; - FLAGS_START = (((float)FLAGS_START)/COLUMNS)*COLS; - PTYPE_START = (((float)PTYPE_START)/COLUMNS)*COLS; - FSTYPE_START = (((float)FSTYPE_START)/COLUMNS)*COLS; - SIZE_START = (((float)SIZE_START)/COLUMNS)*COLS; - COMMAND_LINE_X = (((float)COMMAND_LINE_X)/COLUMNS)*COLS; - - COMMAND_LINE_Y = LINES - 4; - WARNING_START = LINES - 2; - - if ((NUM_ON_SCREEN = COMMAND_LINE_Y - DISK_TABLE_START - 3) <= 0) - NUM_ON_SCREEN = 1; - - COLUMNS = COLS; - defined = TRUE; - } -} - -void draw_screen(void) -{ - int i; - char *line; - - line = (char *)malloc((COLS+1)*sizeof(char)); - - if (warning_last_time) { - for (i = 0; i < COLS; i++) { - move(WARNING_START, i); - line[i] = inch(); - } - line[COLS] = 0; - } - - erase(); - - if (warning_last_time) - mvaddstr(WARNING_START, 0, line); - - - sprintf(line, "cfdisk %s", VERSION); - mvaddstr(HEADER_START, (COLS-strlen(line))/2, line); - sprintf(line, "Disk Drive: %s", disk_device); - mvaddstr(HEADER_START+2, (COLS-strlen(line))/2, line); - sprintf(line, "Heads: %d Sectors per Track: %d Cylinders: %d", - heads, sectors, cylinders); - mvaddstr(HEADER_START+3, (COLS-strlen(line))/2, line); - - mvaddstr(DISK_TABLE_START, NAME_START, "Name"); - mvaddstr(DISK_TABLE_START, FLAGS_START, "Flags"); - mvaddstr(DISK_TABLE_START, PTYPE_START, "Part Type"); - mvaddstr(DISK_TABLE_START, FSTYPE_START, "FS Type"); - if (display_units == SECTORS) - mvaddstr(DISK_TABLE_START, SIZE_START, " Sectors"); - else if (display_units == CYLINDERS) - mvaddstr(DISK_TABLE_START, SIZE_START, "Cylinders"); - else - mvaddstr(DISK_TABLE_START, SIZE_START, "Size (MB)"); - - move(DISK_TABLE_START+1, 1); - for (i = 1; i < COLS-1; i++) - addch('-'); - - if (NUM_ON_SCREEN >= num_parts) - for (i = 0; i < num_parts; i++) - draw_partition(i); - else - for (i = (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN; - i < NUM_ON_SCREEN + (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN && - i < num_parts; - i++) - draw_partition(i); - - free(line); -} - -int draw_cursor(int move) -{ - if (move != 0 && (cur_part + move < 0 || cur_part + move >= num_parts)) - return -1; - - if (arrow_cursor) - mvaddstr(DISK_TABLE_START + cur_part + 2 - - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, " "); - else - draw_partition(cur_part); - - cur_part += move; - - if (((cur_part - move)/NUM_ON_SCREEN)*NUM_ON_SCREEN != - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN) - draw_screen(); - - if (arrow_cursor) - mvaddstr(DISK_TABLE_START + cur_part + 2 - - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, "-->"); - else { - standout(); - draw_partition(cur_part); - standend(); - } - - return 0; -} - -void die(int dummy) -{ - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); - mvcur(0, COLS-1, LINES-1, 0); - nl(); - endwin(); - fdexit(0); -} - -void do_curses_fdisk(void) -{ - int done = FALSE; - char command; - - initscr(); - old_SIGINT = signal(SIGINT, die); - old_SIGTERM = signal(SIGTERM, die); -#ifdef DEBUG - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); -#endif - - cbreak(); - noecho(); - nonl(); - - init_const(); - - fill_p_info(); - - draw_screen(); - - while (!done) { - (void)draw_cursor(0); - - if (p_info[cur_part].id == FREE_SPACE) - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [hnpquW?]: "); - else if (p_info[cur_part].id > 0) - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [bdhmpqtuW?]: "); - else - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [hpquW?]: "); - - clrtoeol(); - refresh(); - - clear_warning(); - - switch (command = getch()) { - case 'B': - case 'b': - if (p_info[cur_part].id > 0) - p_info[cur_part].flags ^= 0x80; - else - print_warning(NO_FLAGS); - break; - case 'D': - case 'd': - if (p_info[cur_part].id > 0) { - del_part(cur_part); - if (cur_part >= num_parts) - cur_part = num_parts - 1; - draw_screen(); - } else - print_warning(DEL_EMPTY); - break; - case 'G': - case 'g': - if (change_geometry()) - draw_screen(); - break; - case 'M': - case 'm': - if (p_info[cur_part].id > 0) { - if (p_info[cur_part].first_sector == 0 || - IS_LOGICAL(p_info[cur_part].num)) { - if (p_info[cur_part].offset == sectors) - p_info[cur_part].offset = 1; - else - p_info[cur_part].offset = sectors; - draw_screen(); - } else if (p_info[cur_part].offset != 0) - p_info[cur_part].offset = 0; - else - print_warning(MAX_UNMAXABLE); - } else - print_warning(MAX_UNMAXABLE); - break; - case 'N': - case 'n': - if (p_info[cur_part].id == FREE_SPACE) { - new_part(cur_part); - draw_screen(); - } else if (p_info[cur_part].id == UNUSABLE) - print_warning(ADD_UNUSABLE); - else - print_warning(ADD_EXISTS); - break; - case 'P': - case 'p': - print_tables(); - draw_screen(); - break; - case 'Q': - case 'q': - done = TRUE; - break; - case 'T': - case 't': - if (p_info[cur_part].id > 0) { - change_id(cur_part); - draw_screen(); - } else - print_warning(TYPE_EMPTY); - break; - case 'U': - case 'u': - if (display_units == MEGABYTES) - display_units = SECTORS; - else if (display_units == SECTORS) - display_units = CYLINDERS; - else if (display_units == CYLINDERS) - display_units = MEGABYTES; - draw_screen(); - break; - case 'W': - write_part_table(); - break; - case 'H': - case 'h': - case '?': - display_help(); - draw_screen(); - break; - case ESC: - if ((command = getch()) == '[') { - command = getch(); - switch (command) { - case 'A' : /* Up arrow */ - if (!draw_cursor(-1)) - command = 0; - else - print_warning(NO_MORE_PARTS); - break; - case 'B' : /* Down arrow */ - if (!draw_cursor(1)) - command = 0; - else - print_warning(NO_MORE_PARTS); - break; - case 'C' : /* Right arrow */ - case 'D' : /* Left arrow */ - } - } - if (command) - putchar(BELL); /* CTRL-G */ - break; - case REDRAWKEY: - clear(); - draw_screen(); - break; - default: - print_warning(BAD_COMMAND); - putchar(BELL); /* CTRL-G */ - } - } - - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); - mvcur(0, COLS-1, LINES-1, 0); - nl(); - endwin(); - fdexit(0); -} - -void copyright(void) -{ - fprintf(stderr, "Copyright (C) 1994 Kevin E. Martin\n"); -} - -void usage(char *prog_name) -{ - fprintf(stderr, - "%s: [-avz] [-c # cylinders] [-h # heads] [-s # sectors/track]\n", - prog_name); - fprintf(stderr, - "[ -P opt ] device\n"); - copyright(); -} - -void main(int argc, char **argv) -{ - char c; - int i, len; - - while ((c = getopt(argc, argv, "ac:h:s:vzP:")) != EOF) - switch (c) { - case 'a': - arrow_cursor = TRUE; - break; - case 'c': - cylinders = atoi(optarg); - if (cylinders <= 0 || cylinders > MAX_CYLINDERS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_CYLINDERS); - exit(1); - } - break; - case 'h': - heads = atoi(optarg); - if (heads <= 0 || heads > MAX_HEADS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_HEADS); - exit(1); - } - break; - case 's': - sectors = atoi(optarg); - if (sectors <= 0 || sectors > MAX_SECTORS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_SECTORS); - exit(1); - } - break; - case 'v': - fprintf(stderr, "cfdisk %s\n", VERSION); - copyright(); - exit(0); - case 'z': - zero_table = TRUE; - break; - case 'P': - len = strlen(optarg); - for (i = 0; i < len; i++) { - switch (optarg[i]) { - case 'r': - print_only |= PRINT_RAW_TABLE; - break; - case 's': - print_only |= PRINT_SECTOR_TABLE; - break; - case 't': - print_only |= PRINT_PARTITION_TABLE; - break; - default: - usage(argv[0]); - break; - } - } - break; - default: - usage(argv[0]); - exit(1); - } - - if (argc-optind == 1) - disk_device = argv[optind]; - else if (argc-optind != 0) { - usage(argv[0]); - exit(1); - } else if ((fd = open(DEFAULT_DEVICE, O_RDWR)) < 0) - disk_device = ALTERNATE_DEVICE; - else close(fd); - - if (print_only) { - fill_p_info(); - if (print_only & PRINT_RAW_TABLE) - print_raw_table(); - if (print_only & PRINT_SECTOR_TABLE) - print_p_info(); - if (print_only & PRINT_PARTITION_TABLE) - print_part_table(); - } else - do_curses_fdisk(); -} diff --git a/disk-utils/cfdisk.c.orig b/disk-utils/cfdisk.c.orig deleted file mode 100644 index 3b9f22f58..000000000 --- a/disk-utils/cfdisk.c.orig +++ /dev/null @@ -1,2066 +0,0 @@ -/**************************************************************************** - * - * CFDISK - * - * cfdisk is a curses based disk drive partitioning program that can - * create partitions for a wide variety of operating systems including - * Linux, MS-DOS and OS/2. - * - * cfdisk was inspired by the fdisk program, by A. V. Le Blanc - * (LeBlanc@mcc.ac.uk). - * - * Copyright (C) 1994 Kevin E. Martin (martin@cs.unc.edu) - * - * cfdisk is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * cfdisk is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with cfdisk; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Created: Fri Jan 28 22:46:58 1994, martin@cs.unc.edu - * - ****************************************************************************/ - -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <unistd.h> -#include <ctype.h> -#include <errno.h> -#include <getopt.h> -#include <fcntl.h> -#include <curses.h> -#include <signal.h> -#include <math.h> -#include <sys/ioctl.h> -#include <linux/genhd.h> -#include <linux/hdreg.h> -#include <linux/fs.h> /* for BLKRRPART */ - -typedef long ext2_loff_t; -extern ext2_loff_t ext2_llseek(unsigned int fd, - ext2_loff_t offset, - unsigned int origin); - -#define VERSION "0.8 BETA (>2GB)" - -#define DEFAULT_DEVICE "/dev/hda" -#define ALTERNATE_DEVICE "/dev/sda" - -#define LINE_LENGTH 80 -#define MAXIMUM_PARTS 60 - -#define SECTOR_SIZE 512 - -#define MAX_CYLINDERS 65535 -#define MAX_HEADS 255 -#define MAX_SECTORS 63 - -#define ACTIVE_FLAG 0x80 -#define PART_TABLE_FLAG 0xAA55 - -#define UNUSABLE -1 -#define FREE_SPACE 0x00 -#define EXTENDED 0x05 -#define LINUX_MINIX 0x81 -#define LINUX_SWAP 0x82 -#define LINUX 0x83 - -#define ADD_EXISTS "This partition is already in use" -#define ADD_UNUSABLE "This partition is unusable" -#define DEL_EMPTY "Cannot delete an empty partition" -#define ID_EMPTY "Cannot change FS Type to empty" -#define ID_EXT "Cannot change FS Type to extended" -#define NEED_EXT "No room to create the extended partition" -#define NO_FLAGS "Cannot make this partition bootable" -#define NO_MORE_PARTS "No more partitions" -#define PRINT_OPEN_ERR "Cannot open file '%s'" -#define TWO_EXTENDEDS "Cannot create logical drive here -- would create two extended partitions" -#define TYPE_EMPTY "Cannot change the type of an empty partition" -#define BAD_COMMAND "Illegal command" -#define MAX_UNMAXABLE "Cannot maximize this partition" -#define BAD_OPEN "Cannot open disk drive" -#define BAD_SEEK "Cannot seek on disk drive" -#define BAD_READ "Cannot read disk drive" -#define BAD_WRITE "Cannot write disk drive" -#define BAD_GEOMETRY "Cannot read disk drive geometry" -#define BAD_PRIMARY "Bad primary partition" -#define BAD_LOGICAL "Bad logical partition" -#define BAD_CYLINDERS "Illegal cylinders value" -#define BAD_HEADS "Illegal heads value" -#define BAD_SECTORS "Illegal sectors value" -#define WRITE_WARN "Warning!! This may destroy data on your disk!" -#define YES_NO "Please enter `yes' or `no'" -#define WRITING_PART "Writing partition table to disk..." -#define YES_WRITE "Wrote partition table to disk" -#define NO_WRITE "Did not write partition table to disk" -#define RRPART_FAILED "Wrote partition table, but re-read table failed. Reboot to update table." - -#define PRI_OR_LOG -1 -#define PRIMARY -2 -#define LOGICAL -3 - -#define COL_ID_WIDTH 20 - -#define CR '\015' -#define ESC '\033' -#define DEL '\177' -#define BELL '\007' -/* '\014' == ^L */ -#define REDRAWKEY '\014' - -/* Display units */ -#define MEGABYTES 1 -#define SECTORS 2 -#define CYLINDERS 3 - -#define GS_DEFAULT -1 -#define GS_ESCAPE -2 - -#define PRINT_RAW_TABLE 1 -#define PRINT_SECTOR_TABLE 2 -#define PRINT_PARTITION_TABLE 4 - -#define IS_PRIMARY(p) ((p) >= 0 && (p) < 4) -#define IS_LOGICAL(p) ((p) > 3) - -#define round_int(d) ((double)((int)(d+0.5))) -#define ceiling(d) ((double)(((d) != (int)(d)) ? (int)(d+1.0) : (int)(d))) - -#define set_hsc(h,s,c,sector) \ -{ \ - s = sector % sectors + 1; \ - sector /= sectors; \ - h = sector % heads; \ - sector /= heads; \ - c = sector & 0xFF; \ - s |= (sector >> 2) & 0xC0;\ -} - -#define ALIGNMENT 2 -typedef union { - struct { - unsigned char align[ALIGNMENT]; - unsigned char b[SECTOR_SIZE]; - } c; - struct { - unsigned char align[ALIGNMENT]; - unsigned char buffer[0x1BE]; - struct partition part[4]; - unsigned short flag; - } p; -} partition_table; - -typedef struct { - int first_sector; /* first sector in partition */ - int last_sector; /* last sector in partition */ - int offset; /* offset from first sector to start of data */ - int flags; /* active == 0x80 */ - int id; /* filesystem type */ - int num; /* number of partition -- primary vs. logical */ -} partition_info; - -char *disk_device = DEFAULT_DEVICE; -int fd; -int heads = 0; -int sectors = 0; -int cylinders = 0; -int changed = FALSE; -int opened = FALSE; - -partition_info p_info[MAXIMUM_PARTS]; -partition_info ext_info; -int num_parts = 0; - -int logical = 0; -int logical_sectors[MAXIMUM_PARTS]; - -__sighandler_t old_SIGINT, old_SIGTERM; - -int arrow_cursor = FALSE; -int display_units = MEGABYTES; -int zero_table = FALSE; -int print_only = 0; - -/* Curses screen information */ -int cur_part = 0; -int warning_last_time = FALSE; -int defined = FALSE; -int COLUMNS = 80; -int NUM_ON_SCREEN = 1; - -/* Y coordinates */ -int HEADER_START = 0; -int DISK_TABLE_START = 5; -int WARNING_START = 23; -int COMMAND_LINE_Y = 21; - -/* X coordinates */ -int NAME_START = 4; -int FLAGS_START = 16; -int PTYPE_START = 30; -int FSTYPE_START = 45; -int SIZE_START = 70; -int COMMAND_LINE_X = 5; - -#define NUM_PART_TYPES 256 -char *partition_type[NUM_PART_TYPES] = { - [LINUX_MINIX] = "Linux/MINIX", - [LINUX_SWAP] = "Linux Swap", - [LINUX] = "Linux", - [FREE_SPACE] = "Free Space", - [EXTENDED] = "Extended", - [0x01] = "DOS 12-bit FAT", - [0x04] = "DOS 16-bit < 32Mb", - [0x06] = "DOS 16-bit >=32Mb", - [0x07] = "OS/2 HPFS", - [0x0A] = "OS/2 Boot Manager", - [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. - */ - - [0x02] = "XENIX root", - [0x03] = "XENIX usr", - [0x08] = "AIX", - [0x09] = "AIX bootable", - [0x40] = "Venix 80286", - [0x51] = "Novell?", - [0x52] = "Microport", - [0x63] = "GNU HURD", - [0x64] = "Novell", - [0x75] = "PC/IX", - [0x80] = "Old MINIX", - [0x93] = "Amoeba", - [0x94] = "Amoeba BBT", - [0xB7] = "BSDI fs", - [0xB8] = "BSDI swap", - [0xC7] = "Syrinx", - [0xDB] = "CP/M", - [0xE1] = "DOS access", - [0xE3] = "DOS R/O", - [0xF2] = "DOS secondary", - [0xFF] = "BBT" -}; - -void fdexit(int ret) -{ - if (opened) - close(fd); - - if (changed) { - fprintf(stderr, "Disk has been changed.\n"); - fprintf(stderr, "Reboot the system to ensure the partition " - "table is correctly updated.\n"); - - fprintf( stderr, "\nWARNING: If you have created or modified any\n" - "DOS 6.x partitions, please see the cfdisk manual\n" - "page for additional information.\n" ); - } - - - exit(ret); -} - -int get_string(char *str, int len, char *def) -{ - char c; - int i = 0; - int x, y; - int use_def = FALSE; - - getyx(stdscr, y, x); - clrtoeol(); - - str[i] = 0; - - if (def != NULL) { - mvaddstr(y, x, def); - move(y, x); - use_def = TRUE; - } - - refresh(); - while ((c = getch()) != '\n' && c != CR) { - switch (c) { - case ESC: - move(y, x); - clrtoeol(); - refresh(); - return GS_ESCAPE; - case DEL: - case '\b': - if (i > 0) { - str[--i] = 0; - mvaddch(y, x+i, ' '); - move(y, x+i); - } else if (use_def) { - clrtoeol(); - use_def = FALSE; - } else - putchar(BELL); - break; - default: - if (i < len && isprint(c)) { - mvaddch(y, x+i, c); - if (use_def) { - clrtoeol(); - use_def = FALSE; - } - str[i++] = c; - str[i] = 0; - } else - putchar(BELL); - } - refresh(); - } - - if (use_def) - return GS_DEFAULT; - else - return i; -} - -void clear_warning(void) -{ - int i; - - if (!warning_last_time) - return; - - move(WARNING_START,0); - for (i = 0; i < COLS; i++) - addch(' '); - - warning_last_time = FALSE; -} - -void print_warning(char *s) -{ - mvaddstr(WARNING_START, (COLS-strlen(s))/2, s); - putchar(BELL); /* CTRL-G */ - - warning_last_time = TRUE; -} - -void fatal(char *s) -{ - char str[LINE_LENGTH]; - - sprintf(str, "FATAL ERROR: %s", s); - mvaddstr(WARNING_START, (COLS-strlen(str))/2, str); - sprintf(str, "Press any key to exit fdisk"); - mvaddstr(WARNING_START+1, (COLS-strlen(str))/2, str); - putchar(BELL); /* CTRL-G */ - - refresh(); - - (void)getch(); - - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); - mvcur(0, COLS-1, LINES-1, 0); - nl(); - endwin(); - fdexit(1); -} - -void read_sector(char *buffer, int sect_num) -{ - if (ext2_llseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0) - fatal(BAD_SEEK); - if (read(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(BAD_READ); -} - -void write_sector(char *buffer, int sect_num) -{ - if (ext2_llseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0) - fatal(BAD_SEEK); - if (write(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(BAD_WRITE); -} - -void check_part_info(void) -{ - int i, pri = 0, log = 0; - - for (i = 0; i < num_parts; i++) - if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num)) - pri++; - else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num)) - log++; - if (ext_info.id == EXTENDED) - if (log > 0) - pri++; - else { - ext_info.first_sector = 0; - ext_info.last_sector = 0; - ext_info.offset = 0; - ext_info.flags = 0; - ext_info.id = FREE_SPACE; - ext_info.num = PRIMARY; - } - - if (pri >= 4) - for (i = 0; i < num_parts; i++) - if (p_info[i].id == FREE_SPACE || p_info[i].id == UNUSABLE) - if (ext_info.id == EXTENDED) - if (p_info[i].first_sector >= ext_info.first_sector && - p_info[i].last_sector <= ext_info.last_sector) { - p_info[i].id = FREE_SPACE; - p_info[i].num = LOGICAL; - } else if (i > 0 && - p_info[i-1].first_sector >= - ext_info.first_sector && - p_info[i-1].last_sector <= - ext_info.last_sector) { - p_info[i].id = FREE_SPACE; - p_info[i].num = LOGICAL; - } else if (i < num_parts-1 && - p_info[i+1].first_sector >= - ext_info.first_sector && - p_info[i+1].last_sector <= - ext_info.last_sector) { - p_info[i].id = FREE_SPACE; - p_info[i].num = LOGICAL; - } else - p_info[i].id = UNUSABLE; - else /* if (ext_info.id != EXTENDED) */ - p_info[i].id = UNUSABLE; - else /* if (p_info[i].id > 0) */ - while (0); /* Leave these alone */ - else /* if (pri < 4) */ - for (i = 0; i < num_parts; i++) { - if (p_info[i].id == UNUSABLE) - p_info[i].id = FREE_SPACE; - if (p_info[i].id == FREE_SPACE) - if (ext_info.id == EXTENDED) - if (p_info[i].first_sector >= ext_info.first_sector && - p_info[i].last_sector <= ext_info.last_sector) - p_info[i].num = LOGICAL; - else if (i > 0 && - p_info[i-1].first_sector >= - ext_info.first_sector && - p_info[i-1].last_sector <= - ext_info.last_sector) - p_info[i].num = PRI_OR_LOG; - else if (i < num_parts-1 && - p_info[i+1].first_sector >= - ext_info.first_sector && - p_info[i+1].last_sector <= - ext_info.last_sector) - p_info[i].num = PRI_OR_LOG; - else - p_info[i].num = PRIMARY; - else /* if (ext_info.id != EXTENDED) */ - p_info[i].num = PRI_OR_LOG; - else /* if (p_info[i].id > 0) */ - while (0); /* Leave these alone */ - } -} - -void remove_part(int i) -{ - int p; - - for (p = i; p < num_parts; p++) - p_info[p] = p_info[p+1]; - - num_parts--; -} - -void insert_part(int i, int num, int id, int flags, int first, int last, - int offset) -{ - int p; - - for (p = num_parts; p > i; p--) - p_info[p] = p_info[p-1]; - - p_info[i].first_sector = first; - p_info[i].last_sector = last; - p_info[i].offset = offset; - p_info[i].flags = flags; - p_info[i].id = id; - p_info[i].num = num; - - num_parts++; -} - -void del_part(int i) -{ - int num = p_info[i].num; - - if (i > 0 && (p_info[i-1].id == FREE_SPACE || - p_info[i-1].id == UNUSABLE)) { - /* Merge with previous partition */ - p_info[i-1].last_sector = p_info[i].last_sector; - remove_part(i--); - } - - if (i < num_parts - 1 && (p_info[i+1].id == FREE_SPACE || - p_info[i+1].id == UNUSABLE)) { - /* Merge with next partition */ - p_info[i+1].first_sector = p_info[i].first_sector; - remove_part(i); - } - - if (i > 0) - p_info[i].first_sector = p_info[i-1].last_sector + 1; - else - p_info[i].first_sector = 0; - - if (i < num_parts - 1) - p_info[i].last_sector = p_info[i+1].first_sector - 1; - else - p_info[i].last_sector = sectors*heads*cylinders - 1; - - p_info[i].offset = 0; - p_info[i].flags = 0; - p_info[i].id = FREE_SPACE; - p_info[i].num = PRI_OR_LOG; - - if (IS_LOGICAL(num)) { - /* We have a logical partition --> shrink the extended partition - * if (1) this is the first logical drive, or (2) this is the - * last logical drive; and if there are any other logical drives - * then renumber the ones after "num". - */ - if (i == 0 || (i > 0 && IS_PRIMARY(p_info[i-1].num))) - ext_info.first_sector = p_info[i].last_sector + 1; - if (i == num_parts-1 || - (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num))) - ext_info.last_sector = p_info[i].first_sector - 1; - for (i = 0; i < num_parts; i++) - if (p_info[i].num > num) - p_info[i].num--; - } - - /* Clean up the rest of the partitions */ - check_part_info(); -} - -int add_part(int num, int id, int flags, int first, int last, int offset) -{ - int i, pri = 0, log = 0; - - if (num_parts == MAXIMUM_PARTS || - first < 0 || - first >= cylinders*heads*sectors || - last < 0 || - last >= cylinders*heads*sectors) - return -1; - - for (i = 0; i < num_parts; i++) - if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num)) - pri++; - else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num)) - log++; - if (ext_info.id == EXTENDED && log > 0) - pri++; - - if (IS_PRIMARY(num)) - if (pri >= 4) - return -1; - else - pri++; - - for (i = 0; p_info[i].last_sector < first; i++); - - if (p_info[i].id != FREE_SPACE || last > p_info[i].last_sector) - return -1; - - if (id == EXTENDED) - if (ext_info.id != FREE_SPACE) - return -1; - else if (IS_PRIMARY(num)) { - ext_info.first_sector = first; - ext_info.last_sector = last; - ext_info.offset = offset; - ext_info.flags = flags; - ext_info.id = EXTENDED; - ext_info.num = num; - - return 0; - } else - return -1; - - if (IS_LOGICAL(num)) { - if (ext_info.id != EXTENDED) { - print_warning("!!!! Internal error creating logical " - "drive with no extended partition !!!!"); - } else { - /* We might have a logical partition outside of the extended - * partition's range --> we have to extend the extended - * partition's range to encompass this new partition, but we - * must make sure that there are no primary partitions between - * it and the closest logical drive in extended partition. - */ - if (first < ext_info.first_sector) { - if (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num)) { - print_warning(TWO_EXTENDEDS); - return -1; - } else { - if (first == 0) { - ext_info.first_sector = 0; - ext_info.offset = first = offset; - } else - ext_info.first_sector = first; - } - } else if (last > ext_info.last_sector) { - if (i > 0 && IS_PRIMARY(p_info[i-1].num)) { - print_warning(TWO_EXTENDEDS); - return -1; - } else - ext_info.last_sector = last; - } - } - } - - if (first != p_info[i].first_sector && - !(IS_LOGICAL(num) && first == offset)) { - insert_part(i, PRI_OR_LOG, FREE_SPACE, 0, - p_info[i].first_sector, first-1, 0); - i++; - } - - if (last != p_info[i].last_sector) - insert_part(i+1, PRI_OR_LOG, FREE_SPACE, 0, - last+1, p_info[i].last_sector, 0); - - p_info[i].first_sector = first; - p_info[i].last_sector = last; - p_info[i].offset = offset; - p_info[i].flags = flags; - p_info[i].id = id; - p_info[i].num = num; - - check_part_info(); - - return 0; -} - -int find_primary(void) -{ - int num = 0, cur = 0; - - while (cur < num_parts && IS_PRIMARY(num)) - if ((p_info[cur].id > 0 && p_info[cur].num == num) || - (ext_info.id == EXTENDED && ext_info.num == num)) { - num++; - cur = 0; - } else - cur++; - - if (!IS_PRIMARY(num)) - return -1; - else - return num; -} - -int find_logical(int i) -{ - int num = -1; - int j; - - for (j = i; j < num_parts && num == -1; j++) - if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num)) - num = p_info[j].num; - - if (num == -1) { - num = 4; - for (j = 0; j < num_parts; j++) - if (p_info[j].id > 0 && p_info[j].num == num) - num++; - } - - return num; -} - -void inc_logical(int i) -{ - int j; - - for (j = i; j < num_parts; j++) - if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num)) - p_info[j].num++; -} - -void new_part(int i) -{ - char response[LINE_LENGTH], def[LINE_LENGTH]; - char c; - int first = p_info[i].first_sector; - int last = p_info[i].last_sector; - int offset = 0; - int flags = 0; - int id = LINUX; - int num = -1; - int num_sects = last - first + 1; - int len, ext, j; - - if (p_info[i].num == PRI_OR_LOG) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Primary or logical [pl]: "); - clrtoeol(); - refresh(); - while (toupper(c = getch()) != 'P' && toupper(c) != 'L' && c != ESC); - if (toupper(c) == 'P') - num = find_primary(); - else if (toupper(c) == 'L') - num = find_logical(i); - else - return; - } else if (p_info[i].num == PRIMARY) - num = find_primary(); - else if (p_info[i].num == LOGICAL) - num = find_logical(i); - else - print_warning("!!! Internal error !!!"); - - sprintf(def, "%.2f", ceiling(num_sects/20.48)/100); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Size (in MB): "); - if ((len = get_string(response, LINE_LENGTH, def)) <= 0 && - len != GS_DEFAULT) - return; - else if (len > 0) { -#define num_cyls(bytes) (round_int(bytes/SECTOR_SIZE/(sectors*heads))) - for (j = 0; - j < len-1 && (isdigit(response[j]) || response[j] == '.'); - j++); - if (toupper(response[j]) == 'K') { - num_sects = num_cyls(atof(response)*1024)*sectors*heads; - } else if (toupper(response[j]) == 'M') { - num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads; - } else if (toupper(response[j]) == 'C') { - num_sects = round_int(atof(response))*sectors*heads; - } else if (toupper(response[j]) == 'S') { - num_sects = round_int(atof(response)); - } else { - num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads; - } - } - - if (num_sects <= 0 || - num_sects > p_info[i].last_sector - p_info[i].first_sector + 1) - return; - - if (num_sects < p_info[i].last_sector - p_info[i].first_sector + 1) { - /* Determine where inside free space to put partition. - */ - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Add partition at beginning or end of free space [be]: "); - clrtoeol(); - refresh(); - while (toupper(c = getch()) != 'B' && toupper(c) != 'E' && c != ESC); - if (toupper(c) == 'B') - last = first + num_sects - 1; - else if (toupper(c) == 'E') - first = last - num_sects + 1; - else - return; - } - - if (IS_LOGICAL(num) && ext_info.id != EXTENDED) { - /* We want to add a logical partition, but need to create an - * extended partition first. - */ - if ((ext = find_primary()) < 0) { - print_warning(NEED_EXT); - return; - } - (void)add_part(ext, EXTENDED, 0, first, last, - (first == 0 ? sectors : 0)); - } - - if (IS_LOGICAL(num)) - inc_logical(i); - - /* Now we have a complete partition to ourselves */ - if (first == 0 || IS_LOGICAL(num)) - offset = sectors; - - (void)add_part(num, id, flags, first, last, offset); -} - -void clear_p_info(void) -{ - num_parts = 1; - p_info[0].first_sector = 0; - p_info[0].last_sector = sectors*heads*cylinders - 1; - p_info[0].offset = 0; - p_info[0].flags = 0; - p_info[0].id = FREE_SPACE; - p_info[0].num = PRI_OR_LOG; - - ext_info.first_sector = 0; - ext_info.last_sector = 0; - ext_info.offset = 0; - ext_info.flags = 0; - ext_info.id = FREE_SPACE; - ext_info.num = PRIMARY; -} - -void fill_p_info(void) -{ - int p, i; - struct hd_geometry geometry; - partition_table buffer; - partition_info tmp_ext = { 0, 0, 0, 0, FREE_SPACE, PRIMARY }; - - if ((fd = open(disk_device, O_RDWR)) < 0) - fatal(BAD_OPEN); - read_sector(buffer.c.b, 0); - - if (!ioctl(fd, HDIO_GETGEO, &geometry)) { - if (!heads) - heads = geometry.heads; - if (!sectors) - sectors = geometry.sectors; - if (!cylinders) - cylinders = geometry.cylinders; - } - - if (!heads || !sectors || !cylinders) - fatal(BAD_GEOMETRY); - - clear_p_info(); - - if (!zero_table) { - for (i = 0; i < 4; i++) { - if (buffer.p.part[i].sys_ind > 0 && - add_part(i, - buffer.p.part[i].sys_ind, - buffer.p.part[i].boot_ind, - ((buffer.p.part[i].start_sect <= sectors) ? - 0 : buffer.p.part[i].start_sect), - buffer.p.part[i].start_sect + - buffer.p.part[i].nr_sects - 1, - ((buffer.p.part[i].start_sect <= sectors) ? - buffer.p.part[i].start_sect : 0))) { - fatal(BAD_PRIMARY); - } - if (buffer.p.part[i].sys_ind == EXTENDED) - tmp_ext = ext_info; - } - - if (tmp_ext.id == EXTENDED) { - ext_info = tmp_ext; - logical_sectors[logical] = ext_info.first_sector; - read_sector(buffer.c.b, logical_sectors[logical++]); - i = 4; - do { - for (p = 0; - p < 4 && (!buffer.p.part[p].sys_ind || - buffer.p.part[p].sys_ind == 5); - p++); - if (p > 3) - fatal(BAD_LOGICAL); - - if (add_part(i++, - buffer.p.part[p].sys_ind, - buffer.p.part[p].boot_ind, - logical_sectors[logical-1], - logical_sectors[logical-1] + - buffer.p.part[p].start_sect + - buffer.p.part[p].nr_sects - 1, - buffer.p.part[p].start_sect)) { - fatal(BAD_LOGICAL); - } - - for (p = 0; - p < 4 && buffer.p.part[p].sys_ind != 5; - p++); - if (p < 4) { - logical_sectors[logical] = - ext_info.first_sector + buffer.p.part[p].start_sect; - read_sector(buffer.c.b, logical_sectors[logical++]); - } - } while (p < 4 && logical < MAXIMUM_PARTS-4); - } - } -} - -void fill_part_table(struct partition *p, partition_info *pi) -{ - int sects; - - p->boot_ind = pi->flags; - p->sys_ind = pi->id; - if (IS_LOGICAL(pi->num)) - p->start_sect = pi->offset; - else - p->start_sect = pi->first_sector + pi->offset; - p->nr_sects = pi->last_sector - (pi->first_sector+pi->offset) + 1; - sects = (((pi->first_sector+pi->offset)/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->first_sector+pi->offset); - set_hsc(p->head, p->sector, p->cyl, sects); - sects = ((pi->last_sector/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->last_sector); - set_hsc(p->end_head, p->end_sector, p->end_cyl, sects); -} - -void fill_primary_table(partition_table *buffer) -{ - int i; - - /* Zero out existing table */ - for (i = 0x1BE; i < SECTOR_SIZE; i++) - buffer->c.b[i] = 0; - - for (i = 0; i < num_parts; i++) - if (IS_PRIMARY(p_info[i].num)) - fill_part_table(&(buffer->p.part[p_info[i].num]), &(p_info[i])); - - if (ext_info.id == EXTENDED) - fill_part_table(&(buffer->p.part[ext_info.num]), &ext_info); - - buffer->p.flag = PART_TABLE_FLAG; -} - -void fill_logical_table(partition_table *buffer, partition_info *pi) -{ - struct partition *p; - int i, sects; - - for (i = 0; i < logical && pi->first_sector != logical_sectors[i]; i++); - if (i == logical || buffer->p.flag != (unsigned short)PART_TABLE_FLAG) - for (i = 0; i < SECTOR_SIZE; i++) - buffer->c.b[i] = 0; - - /* Zero out existing table */ - for (i = 0x1BE; i < SECTOR_SIZE; i++) - buffer->c.b[i] = 0; - - fill_part_table(&(buffer->p.part[0]), pi); - - for (i = 0; - i < num_parts && pi->num != p_info[i].num - 1; - i++); - - if (i < num_parts) { - p = &(buffer->p.part[1]); - pi = &(p_info[i]); - - p->boot_ind = 0; - p->sys_ind = 5; - p->start_sect = pi->first_sector - ext_info.first_sector; - p->nr_sects = pi->last_sector - pi->first_sector + 1; - sects = ((pi->first_sector/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->first_sector); - set_hsc(p->head, p->sector, p->cyl, sects); - sects = ((pi->last_sector/(sectors*heads) > 1023) ? - heads*sectors*1024 - 1 : pi->last_sector); - set_hsc(p->end_head, p->end_sector, p->end_cyl, sects); - } - - buffer->p.flag = PART_TABLE_FLAG; -} - -void write_part_table(void) -{ - int i, done = FALSE, len; - partition_table buffer; - char response[LINE_LENGTH]; - - print_warning(WRITE_WARN); - - while (!done) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Are you sure you want write the partition table to disk? (yes or no): "); - - len = get_string(response, LINE_LENGTH, NULL); - - clear_warning(); - - if (len == GS_ESCAPE) - return; - else if (len == 2 && - toupper(response[0]) == 'N' && - toupper(response[1]) == 'O') { - print_warning(NO_WRITE); - return; - } else if (len == 3 && - toupper(response[0]) == 'Y' && - toupper(response[1]) == 'E' && - toupper(response[2]) == 'S') - done = TRUE; - else - print_warning(YES_NO); - } - - clear_warning(); - print_warning(WRITING_PART); - refresh(); - - read_sector(buffer.c.b, 0); - fill_primary_table(&buffer); - write_sector(buffer.c.b, 0); - - for (i = 0; i < num_parts; i++) - if (IS_LOGICAL(p_info[i].num)) { - /* Read the extended partition table from disk ??? KEM */ - read_sector(buffer.c.b, p_info[i].first_sector); - fill_logical_table(&buffer, &(p_info[i])); - write_sector(buffer.c.b, p_info[i].first_sector); - } - - sync(); - sleep(2); - if (!ioctl(fd,BLKRRPART)) - changed = TRUE; - sync(); - sleep(4); - - clear_warning(); - if (changed) - print_warning(YES_WRITE); - else - print_warning(RRPART_FAILED); -} - -void fp_printf(FILE *fp, char *format, ...) -{ - va_list args; - char buf[1024]; - int y, x; - - va_start(args, format); - vsprintf(buf, format, args); - va_end(args); - - if (fp == NULL) { - /* The following works best if the string to be printed has at - most only one newline. */ - printw("%s", buf); - getyx(stdscr, y, x); - if (y >= COMMAND_LINE_Y-2) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - erase(); - move(0, 0); - } - } else - fprintf(fp, "%s", buf); -} - -#define MAX_PER_LINE 16 -void print_file_buffer(FILE *fp, char *buffer) -{ - int i,l; - - for (i = 0, l = 0; i < SECTOR_SIZE; i++, l++) { - if (l == 0) - fp_printf(fp, "0x%03X:", i); - fp_printf(fp, " %02X", (unsigned char) buffer[i]); - if (l == MAX_PER_LINE - 1) { - fp_printf(fp, "\n"); - l = -1; - } - } - if (l > 0) - fp_printf(fp, "\n"); - fp_printf(fp, "\n"); -} - -void print_raw_table(void) -{ - int i, to_file; - partition_table buffer; - char fname[LINE_LENGTH]; - FILE *fp; - - if (print_only) { - fp = stdout; - to_file = TRUE; - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); - - if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) - return; - - if (to_file) { - if ((fp = fopen(fname, "w")) == NULL) { - char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); - print_warning(errstr); - return; - } - } else { - fp = NULL; - erase(); - move(0, 0); - } - } - - fp_printf(fp, "Disk Drive: %s\n", disk_device); - - read_sector(buffer.c.b, 0); - fill_primary_table(&buffer); - print_file_buffer(fp, buffer.c.b); - - for (i = 0; i < num_parts; i++) - if (IS_LOGICAL(p_info[i].num)) { - read_sector(buffer.c.b, p_info[i].first_sector); - fill_logical_table(&buffer, &(p_info[i])); - print_file_buffer(fp, buffer.c.b); - } - - if (to_file) { - if (!print_only) - fclose(fp); - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - } -} - -void print_p_info_entry(FILE *fp, partition_info *p) -{ - int size; - char part_str[21]; - - if (p->id == UNUSABLE) - fp_printf(fp, " None "); - else if (p->id == FREE_SPACE && p->num == PRI_OR_LOG) - fp_printf(fp, " Pri/Log"); - else if (p->id == FREE_SPACE && p->num == PRIMARY) - fp_printf(fp, " Primary"); - else if (p->id == FREE_SPACE && p->num == LOGICAL) - fp_printf(fp, " Logical"); - else - fp_printf(fp, "%2d %-7.7s", p->num+1, - IS_LOGICAL(p->num) ? "Logical" : "Primary"); - - fp_printf(fp, " "); - - fp_printf(fp, "%7d%c", p->first_sector, - ((p->first_sector/(sectors*heads)) != - ((float)p->first_sector/(sectors*heads)) ? - '*' : ' ')); - - fp_printf(fp, " "); - - fp_printf(fp, "%7d%c", p->last_sector, - (((p->last_sector+1)/(sectors*heads)) != - ((float)(p->last_sector+1)/(sectors*heads)) ? - '*' : ' ')); - - fp_printf(fp, " "); - - fp_printf(fp, "%6d%c", p->offset, - ((((p->first_sector == 0 || IS_LOGICAL(p->num)) && - (p->offset != sectors)) || - (p->first_sector != 0 && IS_PRIMARY(p->num) && - p->offset != 0)) ? - '#' : ' ')); - - fp_printf(fp, " "); - - size = p->last_sector - p->first_sector + 1; - fp_printf(fp, "%7d%c", size, - ((size/(sectors*heads)) != ((float)size/(sectors*heads)) ? - '*' : ' ')); - - fp_printf(fp, " "); - - if (p->id == UNUSABLE) - sprintf(part_str, "%.16s", "Unusable"); - else if (p->id == FREE_SPACE) - sprintf(part_str, "%.16s", "Free Space"); - else if (partition_type[p->id]) - sprintf(part_str, "%.16s (%02X)", partition_type[p->id], p->id); - else - sprintf(part_str, "%.16s (%02X)", "Unknown", p->id); - fp_printf(fp, "%-21.21s", part_str); - - fp_printf(fp, " "); - - if (p->flags == ACTIVE_FLAG) - fp_printf(fp, "Boot (%02X)", p->flags); - else if (p->flags != 0) - fp_printf(fp, "Unknown (%02X)", p->flags); - else - fp_printf(fp, "None (%02X)", p->flags); - - fp_printf(fp, "\n"); -} - -void print_p_info(void) -{ - char fname[LINE_LENGTH]; - FILE *fp; - int i, to_file, pext = (ext_info.id == EXTENDED); - - if (print_only) { - fp = stdout; - to_file = TRUE; - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); - - if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) - return; - - if (to_file) { - if ((fp = fopen(fname, "w")) == NULL) { - char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); - print_warning(errstr); - return; - } - } else { - fp = NULL; - erase(); - move(0, 0); - } - } - - fp_printf(fp, "Partition Table for %s\n", disk_device); - fp_printf(fp, "\n"); - fp_printf(fp, " First Last\n"); - fp_printf(fp, " # Type Sector Sector Offset Length Filesystem Type (ID) Flags\n"); - fp_printf(fp, "-- ------- -------- -------- ------- -------- --------------------- ---------\n"); - - for (i = 0; i < num_parts; i++) { - if (pext && (p_info[i].first_sector >= ext_info.first_sector)) { - print_p_info_entry(fp,&ext_info); - pext = FALSE; - } - print_p_info_entry(fp, &(p_info[i])); - } - - if (to_file) { - if (!print_only) - fclose(fp); - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - } -} - -void print_part_entry(FILE *fp, int num, partition_info *pi) -{ - int first = 0, start = 0, end = 0, size = 0; - int ss = 0, sh = 0, sc = 0; - int es = 0, eh = 0, ec = 0; - int flags = 0, id = 0; - - if (pi != NULL) { - flags = pi->flags; - id = pi->id; - - if (IS_LOGICAL(num)) - first = pi->offset; - else - first = pi->first_sector + pi->offset; - - start = pi->first_sector + pi->offset; - end = pi->last_sector; - size = end - start + 1; - if ((start/(sectors*heads)) > 1023) - start = heads*sectors*1024 - 1; - if ((end/(sectors*heads)) > 1023) - end = heads*sectors*1024 - 1; - - ss = start % sectors + 1; - start /= sectors; - sh = start % heads; - sc = start / heads; - - es = end % sectors + 1; - end /= sectors; - eh = end % heads; - ec = end / heads; - } - - fp_printf(fp, "%2d 0x%02X %4d %4d %4d 0x%02X %4d %4d %4d %7d %7d\n", - num+1, flags, sh, ss, sc, id, eh, es, ec, first, size); -} - - -void print_part_table(void) -{ - int i, j, to_file; - char fname[LINE_LENGTH]; - FILE *fp; - - if (print_only) { - fp = stdout; - to_file = TRUE; - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter filename or press RETURN to display on screen: "); - - if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0) - return; - - if (to_file) { - if ((fp = fopen(fname, "w")) == NULL) { - char errstr[LINE_LENGTH]; - sprintf(errstr, PRINT_OPEN_ERR, fname); - print_warning(errstr); - return; - } - } else { - fp = NULL; - erase(); - move(0, 0); - } - } - - fp_printf(fp, "Partition Table for %s\n", disk_device); - fp_printf(fp, "\n"); - fp_printf(fp, " ---Starting--- ----Ending---- Start Number\n"); - fp_printf(fp, " # Flags Head Sect Cyl ID Head Sect Cyl Sector Sectors\n"); - fp_printf(fp, "-- ----- ---- ---- ---- ---- ---- ---- ---- ------- -------\n"); - - for (i = 0; i < 4; i++) { - for (j = 0; - j < num_parts && (p_info[j].id <= 0 || p_info[j].num != i); - j++); - if (j < num_parts) { - print_part_entry(fp, i, &(p_info[j])); - } else if (ext_info.id == EXTENDED && ext_info.num == i) { - print_part_entry(fp, i, &ext_info); - } else { - print_part_entry(fp, i, NULL); - } - } - - for (i = 0; i < num_parts; i++) - if (IS_LOGICAL(p_info[i].num)) - print_part_entry(fp, p_info[i].num, &(p_info[i])); - - if (to_file) { - if (!print_only) - fclose(fp); - } else { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - } -} - -void print_tables(void) -{ - int done = FALSE; - - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Print format [rst]: "); - clrtoeol(); - refresh(); - - while (!done) - switch (toupper(getch())) { - case 'R': - print_raw_table(); - done = TRUE; - break; - case 'S': - print_p_info(); - done = TRUE; - break; - case 'T': - print_part_table(); - done = TRUE; - break; - case ESC: - done = TRUE; - break; - } -} - -#define END_OF_HELP "EOHS!" -#define NEW_HELP_SCREEN "SNHS!" -void display_help() -{ - char *help_text[] = { - "Help Screen for cfdisk " VERSION, - "", - "This is cfdisk, a curses based disk partitioning programs, which", - "allows you to create, delete and modify partitions on your hard", - "disk drive.", - "", - "Copyright (C) 1994 Kevin E. Martin", - "", - "Command Meaning", - "------- -------", - " b Toggle bootable flag of the current partition", - " d Delete the current partition", - " g Change cylinders, heads, sectors-per-track parameters", - " WARNING: This option should only be used by people who", - " know what they are doing.", - " h Print this screen", - " m Maximize disk usage of the current partition", - " Note: This may make the partition incompatible with", - " DOS, OS/2, ...", - " n Create new partition from free space", - " p Print partition table to the screen or to a file", - " There are several different formats for the partition", - " that you can choose from:", - " r - Raw data (exactly what would be written to disk)", - " s - Table ordered by sectors", - " t - Table in raw format", - " q Quit program without writing partition table", - " t Change the filesystem type", - " u Change units of the partition size display", - " Rotates through Mb, sectors and cylinders", - " W Write partition table to disk (must enter upper case W)", - " Since this might destroy data on the disk, you must", - " either confirm or deny the write by entering `yes' or", - " `no'", - "Up Arrow Move cursor to the previous partition", - "Down Arrow Move cursor to the next partition", - "CTRL-L Redraws the screen", - " ? Print this screen", - "", - "Note: All of the commands can be entered with either upper or lower", - "case letters (except for Writes).", - END_OF_HELP - }; - - int cur_line = 0; - FILE *fp = NULL; - - erase(); - move(0, 0); - while (strcmp(help_text[cur_line], END_OF_HELP)) - if (!strcmp(help_text[cur_line], NEW_HELP_SCREEN)) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); - erase(); - move(0, 0); - cur_line++; - } else - fp_printf(fp, "%s\n", help_text[cur_line++]); - - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Press any key to continue..."); - clrtoeol(); - refresh(); - (void)getch(); -} - -int change_geometry(void) -{ - int ret_val = FALSE; - int done = FALSE; - char def[LINE_LENGTH]; - char response[LINE_LENGTH]; - int tmp_val; - - while (!done) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Change disk geometry information [chs]: "); - clrtoeol(); - refresh(); - - clear_warning(); - - switch (toupper(getch())) { - case 'C': - sprintf(def, "%d", cylinders); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of cylinders: "); - if (get_string(response, LINE_LENGTH, def) > 0) { - tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_CYLINDERS) { - cylinders = tmp_val; - ret_val = TRUE; - } else - print_warning(BAD_CYLINDERS); - } - break; - case 'H': - sprintf(def, "%d", heads); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of heads: "); - if (get_string(response, LINE_LENGTH, def) > 0) { - tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_HEADS) { - heads = tmp_val; - ret_val = TRUE; - } else - print_warning(BAD_HEADS); - } - break; - case 'S': - sprintf(def, "%d", sectors); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - "Enter the number of sectors per track: "); - if (get_string(response, LINE_LENGTH, def) > 0) { - tmp_val = atoi(response); - if (tmp_val > 0 && tmp_val <= MAX_SECTORS) { - sectors = tmp_val; - ret_val = TRUE; - } else - print_warning(BAD_SECTORS); - } - break; - case ESC: - case CR: - done = TRUE; - break; - default: - putchar(BELL); - break; - } - } - - if (ret_val) { - if (p_info[num_parts-1].last_sector > heads*sectors*cylinders-1) { - while (p_info[num_parts-1].first_sector > heads*sectors*cylinders-1) { - if (p_info[num_parts-1].id == FREE_SPACE || - p_info[num_parts-1].id == UNUSABLE) - remove_part(num_parts-1); - else - del_part(num_parts-1); - } - - p_info[num_parts-1].last_sector = heads*sectors*cylinders - 1; - - if (ext_info.last_sector > heads*sectors*cylinders-1) - ext_info.last_sector = heads*sectors*cylinders - 1; - } else if (p_info[num_parts-1].last_sector < heads*sectors*cylinders-1) { - if (p_info[num_parts-1].id == FREE_SPACE || - p_info[num_parts-1].id == UNUSABLE) { - p_info[num_parts-1].last_sector = heads*sectors*cylinders - 1; - } else { - insert_part(num_parts, PRI_OR_LOG, FREE_SPACE, 0, - p_info[num_parts-1].last_sector+1, - heads*sectors*cylinders-1, 0); - } - } - - /* Make sure the partitions are correct */ - check_part_info(); - } - - return ret_val; -} - -void change_id(int i) -{ - char id[LINE_LENGTH], def[LINE_LENGTH]; - int num_types = 0; - int num_across, num_down; - int len, new_id = LINUX; - int y_start, y_end; - int j, pos; - - for (num_types = 0, j = 1; j < NUM_PART_TYPES; j++) - if (partition_type[j]) - num_types++; - - num_across = COLS/COL_ID_WIDTH; - num_down = (((float)num_types)/num_across + 1); - y_start = COMMAND_LINE_Y - 1 - num_down; - if (y_start > DISK_TABLE_START+cur_part+4) - y_start = DISK_TABLE_START+cur_part+4; - y_end = y_start + num_down - 1; - - for (j = y_start - 1; j <= y_end + 1; j++) { - move(j, 0); - clrtoeol(); - } - - for (pos = 0, j = 1; j < NUM_PART_TYPES; j++) - if (partition_type[j]) { - move(y_start + pos % num_down, (pos/num_down)*COL_ID_WIDTH + 1); - printw("%02X %-16.16s", j, partition_type[j]); - pos++; - } - - sprintf(def, "%02X", new_id); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Enter filesystem type: "); - if ((len = get_string(id, 2, def)) <= 0 && len != GS_DEFAULT) - return; - - if (len != GS_DEFAULT) { - if (!isxdigit(id[0])) - return; - new_id = (isdigit(id[0]) ? id[0] - '0' : tolower(id[0]) - 'a' + 10); - if (len == 2) - if (isxdigit(id[1])) - new_id = new_id*16 + - (isdigit(id[1]) ? id[1] - '0' : tolower(id[1]) - 'a' + 10); - else - return; - } - - if (new_id == 0) - print_warning(ID_EMPTY); - else if (new_id == EXTENDED) - print_warning(ID_EXT); - else - p_info[i].id = new_id; -} - -void draw_partition(int i) -{ - int size, j; - int y = i + DISK_TABLE_START + 2 - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN; - - if (!arrow_cursor) { - move(y, 0); - for (j = 0; j < COLS; j++) - addch(' '); - } - - if (p_info[i].id > 0) { - mvprintw(y, NAME_START, - "%s%d", disk_device, p_info[i].num+1); - if (p_info[i].flags) { - if (p_info[i].flags == ACTIVE_FLAG) - mvaddstr(y, FLAGS_START, "Boot"); - else - mvprintw(y, FLAGS_START, "Unk(%02X)", p_info[i].flags); - if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) { - if (p_info[i].offset != sectors) - addstr(", NC"); - } else { - if (p_info[i].offset != 0) - addstr(", NC"); - } - } else { - if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) { - if (p_info[i].offset != sectors) - mvaddstr(y, FLAGS_START, "NC"); - } else { - if (p_info[i].offset != 0) - mvaddstr(y, FLAGS_START, "NC"); - } - } - } - mvaddstr(y, PTYPE_START, - (p_info[i].id == UNUSABLE ? "" : - (IS_LOGICAL(p_info[i].num) ? "Logical" : - (p_info[i].num >= 0 ? "Primary" : - (p_info[i].num == PRI_OR_LOG ? "Pri/Log" : - (p_info[i].num == PRIMARY ? "Primary" : "Logical")))))); - 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]); - else - mvprintw(y, FSTYPE_START, "Unknown (%02X)", p_info[i].id); - - size = p_info[i].last_sector - p_info[i].first_sector + 1; - if (display_units == SECTORS) - mvprintw(y, SIZE_START, "%9d", size); - else if (display_units == CYLINDERS) - mvprintw(y, SIZE_START, "%9d", size/(sectors*heads)); - else - mvprintw(y, SIZE_START, "%9.2f", ceiling(size/20.48)/100); - if (((size/(sectors*heads)) != ceiling(size/(sectors*(float)heads))) || - ((p_info[i].first_sector/(sectors*heads)) != - ceiling(p_info[i].first_sector/(sectors*heads)))) - mvprintw(y, COLUMNS-1, "*"); -} - -void init_const(void) -{ - if (!defined) { - NAME_START = (((float)NAME_START)/COLUMNS)*COLS; - FLAGS_START = (((float)FLAGS_START)/COLUMNS)*COLS; - PTYPE_START = (((float)PTYPE_START)/COLUMNS)*COLS; - FSTYPE_START = (((float)FSTYPE_START)/COLUMNS)*COLS; - SIZE_START = (((float)SIZE_START)/COLUMNS)*COLS; - COMMAND_LINE_X = (((float)COMMAND_LINE_X)/COLUMNS)*COLS; - - COMMAND_LINE_Y = LINES - 4; - WARNING_START = LINES - 2; - - if ((NUM_ON_SCREEN = COMMAND_LINE_Y - DISK_TABLE_START - 3) <= 0) - NUM_ON_SCREEN = 1; - - COLUMNS = COLS; - defined = TRUE; - } -} - -void draw_screen(void) -{ - int i; - char *line; - - line = (char *)malloc((COLS+1)*sizeof(char)); - - if (warning_last_time) { - for (i = 0; i < COLS; i++) { - move(WARNING_START, i); - line[i] = inch(); - } - line[COLS] = 0; - } - - erase(); - - if (warning_last_time) - mvaddstr(WARNING_START, 0, line); - - - sprintf(line, "cfdisk %s", VERSION); - mvaddstr(HEADER_START, (COLS-strlen(line))/2, line); - sprintf(line, "Disk Drive: %s", disk_device); - mvaddstr(HEADER_START+2, (COLS-strlen(line))/2, line); - sprintf(line, "Heads: %d Sectors per Track: %d Cylinders: %d", - heads, sectors, cylinders); - mvaddstr(HEADER_START+3, (COLS-strlen(line))/2, line); - - mvaddstr(DISK_TABLE_START, NAME_START, "Name"); - mvaddstr(DISK_TABLE_START, FLAGS_START, "Flags"); - mvaddstr(DISK_TABLE_START, PTYPE_START, "Part Type"); - mvaddstr(DISK_TABLE_START, FSTYPE_START, "FS Type"); - if (display_units == SECTORS) - mvaddstr(DISK_TABLE_START, SIZE_START, " Sectors"); - else if (display_units == CYLINDERS) - mvaddstr(DISK_TABLE_START, SIZE_START, "Cylinders"); - else - mvaddstr(DISK_TABLE_START, SIZE_START, "Size (MB)"); - - move(DISK_TABLE_START+1, 1); - for (i = 1; i < COLS-1; i++) - addch('-'); - - if (NUM_ON_SCREEN >= num_parts) - for (i = 0; i < num_parts; i++) - draw_partition(i); - else - for (i = (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN; - i < NUM_ON_SCREEN + (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN && - i < num_parts; - i++) - draw_partition(i); - - free(line); -} - -int draw_cursor(int move) -{ - if (move != 0 && (cur_part + move < 0 || cur_part + move >= num_parts)) - return -1; - - if (arrow_cursor) - mvaddstr(DISK_TABLE_START + cur_part + 2 - - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, " "); - else - draw_partition(cur_part); - - cur_part += move; - - if (((cur_part - move)/NUM_ON_SCREEN)*NUM_ON_SCREEN != - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN) - draw_screen(); - - if (arrow_cursor) - mvaddstr(DISK_TABLE_START + cur_part + 2 - - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, "-->"); - else { - standout(); - draw_partition(cur_part); - standend(); - } - - return 0; -} - -void die(int dummy) -{ - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); - mvcur(0, COLS-1, LINES-1, 0); - nl(); - endwin(); - fdexit(0); -} - -void do_curses_fdisk(void) -{ - int done = FALSE; - char command; - - initscr(); - old_SIGINT = signal(SIGINT, die); - old_SIGTERM = signal(SIGTERM, die); -#ifdef DEBUG - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); -#endif - - cbreak(); - noecho(); - nonl(); - - init_const(); - - fill_p_info(); - - draw_screen(); - - while (!done) { - (void)draw_cursor(0); - - if (p_info[cur_part].id == FREE_SPACE) - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [hnpquW?]: "); - else if (p_info[cur_part].id > 0) - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [bdhmpqtuW?]: "); - else - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [hpquW?]: "); - - clrtoeol(); - refresh(); - - clear_warning(); - - switch (command = getch()) { - case 'B': - case 'b': - if (p_info[cur_part].id > 0) - p_info[cur_part].flags ^= 0x80; - else - print_warning(NO_FLAGS); - break; - case 'D': - case 'd': - if (p_info[cur_part].id > 0) { - del_part(cur_part); - if (cur_part >= num_parts) - cur_part = num_parts - 1; - draw_screen(); - } else - print_warning(DEL_EMPTY); - break; - case 'G': - case 'g': - if (change_geometry()) - draw_screen(); - break; - case 'M': - case 'm': - if (p_info[cur_part].id > 0) { - if (p_info[cur_part].first_sector == 0 || - IS_LOGICAL(p_info[cur_part].num)) { - if (p_info[cur_part].offset == sectors) - p_info[cur_part].offset = 1; - else - p_info[cur_part].offset = sectors; - draw_screen(); - } else if (p_info[cur_part].offset != 0) - p_info[cur_part].offset = 0; - else - print_warning(MAX_UNMAXABLE); - } else - print_warning(MAX_UNMAXABLE); - break; - case 'N': - case 'n': - if (p_info[cur_part].id == FREE_SPACE) { - new_part(cur_part); - draw_screen(); - } else if (p_info[cur_part].id == UNUSABLE) - print_warning(ADD_UNUSABLE); - else - print_warning(ADD_EXISTS); - break; - case 'P': - case 'p': - print_tables(); - draw_screen(); - break; - case 'Q': - case 'q': - done = TRUE; - break; - case 'T': - case 't': - if (p_info[cur_part].id > 0) { - change_id(cur_part); - draw_screen(); - } else - print_warning(TYPE_EMPTY); - break; - case 'U': - case 'u': - if (display_units == MEGABYTES) - display_units = SECTORS; - else if (display_units == SECTORS) - display_units = CYLINDERS; - else if (display_units == CYLINDERS) - display_units = MEGABYTES; - draw_screen(); - break; - case 'W': - write_part_table(); - break; - case 'H': - case 'h': - case '?': - display_help(); - draw_screen(); - break; - case ESC: - if ((command = getch()) == '[') { - command = getch(); - switch (command) { - case 'A' : /* Up arrow */ - if (!draw_cursor(-1)) - command = 0; - else - print_warning(NO_MORE_PARTS); - break; - case 'B' : /* Down arrow */ - if (!draw_cursor(1)) - command = 0; - else - print_warning(NO_MORE_PARTS); - break; - case 'C' : /* Right arrow */ - case 'D' : /* Left arrow */ - } - } - if (command) - putchar(BELL); /* CTRL-G */ - break; - case REDRAWKEY: - clear(); - draw_screen(); - break; - default: - print_warning(BAD_COMMAND); - putchar(BELL); /* CTRL-G */ - } - } - - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); - mvcur(0, COLS-1, LINES-1, 0); - nl(); - endwin(); - fdexit(0); -} - -void copyright(void) -{ - fprintf(stderr, "Copyright (C) 1994 Kevin E. Martin\n"); -} - -void usage(char *prog_name) -{ - fprintf(stderr, - "%s: [-avz] [-c # cylinders] [-h # heads] [-s # sectors/track]\n", - prog_name); - fprintf(stderr, - "[ -P opt ] device\n"); - copyright(); -} - -void main(int argc, char **argv) -{ - char c; - int i, len; - - while ((c = getopt(argc, argv, "ac:h:s:vzP:")) != EOF) - switch (c) { - case 'a': - arrow_cursor = TRUE; - break; - case 'c': - cylinders = atoi(optarg); - if (cylinders <= 0 || cylinders > MAX_CYLINDERS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_CYLINDERS); - exit(1); - } - break; - case 'h': - heads = atoi(optarg); - if (heads <= 0 || heads > MAX_HEADS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_HEADS); - exit(1); - } - break; - case 's': - sectors = atoi(optarg); - if (sectors <= 0 || sectors > MAX_SECTORS) { - fprintf(stderr, "%s: %s\n", argv[0], BAD_SECTORS); - exit(1); - } - break; - case 'v': - fprintf(stderr, "cfdisk %s\n", VERSION); - copyright(); - exit(0); - case 'z': - zero_table = TRUE; - break; - case 'P': - len = strlen(optarg); - for (i = 0; i < len; i++) { - switch (optarg[i]) { - case 'r': - print_only |= PRINT_RAW_TABLE; - break; - case 's': - print_only |= PRINT_SECTOR_TABLE; - break; - case 't': - print_only |= PRINT_PARTITION_TABLE; - break; - default: - usage(argv[0]); - break; - } - } - break; - default: - usage(argv[0]); - exit(1); - } - - if (argc-optind == 1) - disk_device = argv[optind]; - else if (argc-optind != 0) { - usage(argv[0]); - exit(1); - } else if ((fd = open(DEFAULT_DEVICE, O_RDWR)) < 0) - disk_device = ALTERNATE_DEVICE; - else close(fd); - - if (print_only) { - fill_p_info(); - if (print_only & PRINT_RAW_TABLE) - print_raw_table(); - if (print_only & PRINT_SECTOR_TABLE) - print_p_info(); - if (print_only & PRINT_PARTITION_TABLE) - print_part_table(); - } else - do_curses_fdisk(); -} diff --git a/disk-utils/fdformat.c b/disk-utils/fdformat.c index 46b9e2320..7f792c5c9 100644 --- a/disk-utils/fdformat.c +++ b/disk-utils/fdformat.c @@ -56,9 +56,19 @@ static void verify_disk(char *name) fflush(stdout); if ((fd = open(name,O_RDONLY)) < 0) PERROR(name); for (cyl = 0; cyl < param.track; cyl++) { + int read_bytes; + printf("%3d\b\b\b",cyl); fflush(stdout); - if (read(fd,data,cyl_size) != cyl_size) PERROR("read"); + read_bytes = read(fd,data,cyl_size); + if(read_bytes != cyl_size) { + if(read_bytes < 0) + perror("Read: "); + fprintf(stderr, + "Problem reading cylinder %d, expected %d, read %d\n", + cyl, cyl_size, read_bytes); + exit(1); + } for (count = 0; count < cyl_size; count++) if (data[count] != FD_FILL_BYTE) { printf("bad data in cyl %d\nContinuing ... ",cyl); diff --git a/disk-utils/fdisk.8 b/disk-utils/fdisk.8 deleted file mode 100644 index 576bce2ec..000000000 --- a/disk-utils/fdisk.8 +++ /dev/null @@ -1,213 +0,0 @@ -.\" 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 "11 June 1998" "Linux 2.0" "Linux Programmer's Manual" -.SH NAME -fdisk \- Partition table manipulator for Linux -.SH SYNOPSIS -.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 -(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: -.br -.nf -.RS -/dev/hda -/dev/hdb -/dev/sda -/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 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 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). - -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. - -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" - -The DOS 6.x FORMAT command looks for some information in the first -sector of the data area of the partition, and treats this information -as more reliable than the information in the partition table. DOS -FORMAT expects DOS FDISK to clear the first 512 bytes of the data area -of a partition whenever a size change occurs. DOS FORMAT will look at -this extra information even if the /U flag is given -- we consider -this a bug in DOS FORMAT and DOS FDISK. - -The bottom line is that if you use cfdisk or fdisk to change the size of a -DOS partition table entry, then you must also use -.B dd -to zero the first 512 bytes of that partition before using DOS FORMAT to -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. - -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. - -.SH OPTIONS -.TP -.B \-v -Print version number of -.B fdisk -program and exit. -.TP -.B \-l -List the partition tables for -.BR /dev/hd[a-d] , -.BR /dev/sd[a-h] , -.BR /dev/ed[a-d] , -and then exit. -.TP -.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 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. -(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 -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 deleted file mode 100644 index d99a8b452..000000000 --- a/disk-utils/fdisk.c +++ /dev/null @@ -1,1940 +0,0 @@ -/* fdisk.c -- Partition table manipulator for Linux. - * - * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk) - * - * This program is free software. You can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation: either version 1 or - * (at your option) any later version. - * - * Before Linux version 0.95c, this program requires a kernel patch. - * - * Modified, Tue Feb 2 18:46:49 1993, faith@cs.unc.edu to better support SCSI. - * Modified, Sat Feb 27 18:11:27 1993, faith@cs.unc.edu: added extfs support. - * Modified, Sat Mar 6 10:14:12 1993, faith@cs.unc.edu: added more comments. - * Modified, Sat Mar 6 12:25:45 1993, faith@cs.unc.edu: - * Added patches from Michael Bischoff (i1041905@ws.rz.tu-bs.de - * or mbi@mo.math.nat.tu-bs.de) to fix the following problems: - * 1) Incorrect mapping of head/sector/cylinder to absolute sector - * 2) Odd sector count causes one sector to be lost - * Modified, Sat Mar 6 12:25:52 1993, faith@cs.unc.edu: improved verification. - * Modified, Sat Apr 17 15:00:00 1993, LeBlanc@mcc.ac.uk: add -s, fix -l. - * Modified, Sat Apr 24 10:00:00 1993, LeBlanc@mcc.ac.uk: fix overlap bug. - * Modified, Wed May 5 21:30:00 1993, LeBlanc@mcc.ac.uk: errors to stderr. - * Modified, Mon Mar 21 20:00:00 1994, LeBlanc@mcc.ac.uk: - * more stderr for messages, avoid division by 0, and - * give reboot message only if ioctl(fd, BLKRRPART) fails. - * Modified, Mon Apr 25 01:01:05 1994, martin@cs.unc.edu: - * 1) Added support for DOS, OS/2, ... compatibility. We should be able - * use this fdisk to partition our drives for other operating systems. - * 2) Added a print the raw data in the partition table command. - * Modified, Wed Jun 22 21:05:30 1994, faith@cs.unc.edu: - * Added/changed a few partition type names to conform to cfdisk. - * (suggested by Sujal, smpatel@wam.umd.edu) - * Modified 3/5/95 leisner@sdsp.mc.xerox.com -- on -l only open - * devices RDONLY (instead of RDWR). This allows you to - * have the disks as rw-r----- with group disk (and if you - * want is safe to setguid fdisk to disk). - * Modified Sat Mar 11 10:02 1995 with more partition types, faith@cs.unc.edu - * Modified, Thu May 4 01:11:45 1995, esr@snark.thyrsus.com: - * It's user-interface cleanup time. - * Actual error messages for out-of-bounds values (what a concept!). - * Enable read-only access to partition table for learners. - * Smart defaults for most numeric prompts. - * Fixed a bug preventing a partition from crossing cylinder 8064, aeb, 950801. - * Read partition table twice to avoid kernel bug - * (from Daniel Quinlan <quinlan@yggdrasil.com>), Tue Sep 26 10:25:28 1995 - * Modified, Sat Jul 1 23:43:16 MET DST 1995, fasten@cs.bonn.edu: - * editor for NetBSD/i386 (and Linux/Alpha?) disklabels. - * 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. - */ - - -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <ctype.h> -#include <setjmp.h> -#include <errno.h> -#include <getopt.h> - -#include <sys/stat.h> -#include <sys/ioctl.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); \ - isdigit(_c) ? _c - '0' : \ - tolower(_c) + 10 - 'a'; \ - }) - - -#define VERSION "2.8" /* util-linux version */ - -#define DEFAULT_DEVICE "/dev/hda" -#define ALTERNATE_DEVICE "/dev/sda" -#define LINE_LENGTH 80 -#define offset(b, n) ((struct partition *)((b) + 0x1be + \ - (n) * sizeof(struct partition))) -#define sector(s) ((s) & 0x3f) -#define cylinder(s, c) ((c) | (((s) & 0xc0) << 2)) - -#define calculate(h,s,c) (sector(s) - 1 + sectors * \ - ((h) + heads * cylinder(s,c))) -#define set_hsc(h,s,c,sector) { \ - s = sector % sectors + 1; \ - sector /= sectors; \ - h = sector % heads; \ - sector /= heads; \ - c = sector & 0xff; \ - s |= (sector >> 2) & 0xc0; \ - } - -/* A valid partition table sector ends in 0x55 0xaa */ -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 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; - -char *disk_device = DEFAULT_DEVICE, /* hda, unless specified */ - *line_ptr, /* interactive input */ - line_buffer[LINE_LENGTH], - changed[MAXIMUM_PARTS], /* marks changed buffers */ - buffer[SECTOR_SIZE], /* first four partitions */ - *buffers[MAXIMUM_PARTS] /* pointers to buffers */ - = {buffer, buffer, buffer, buffer}; - -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 */ - -uint heads, - sectors, - cylinders, - sector_offset = 1, - display_factor = 1, /* in units/sector */ - unit_flag = 1, - full_bits = 0, /* 1024 cylinders in sectors */ - 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[] = { - {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; - -void fatal(enum failure why) -{ - char error[LINE_LENGTH], - *message = error; - - if (listing) { - close(fd); - longjmp(listingbuf, 1); - } - - switch (why) { - case usage: message = -"Usage: fdisk [-b] [-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); - break; - case unable_to_read: - sprintf(error, "Unable to read %s\n", disk_device); - break; - case unable_to_seek: - sprintf(error, "Unable to seek on %s\n", disk_device); - break; - case unable_to_write: - sprintf(error, "Unable to write %s\n", disk_device); - break; - case out_of_memory: - message = "Unable to allocate any more memory\n"; - break; - default: message = "Fatal error\n"; - } - - fputc('\n', stderr); - fputs(message, stderr); - exit(1); -} - -void menu(void) -{ - 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" - " 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" - " 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)" - ); -} - -void xmenu(void) -{ - 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" /* sun */ - " h change number of heads\n" - " 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" - ); -} - -char *partition_type(unsigned char type) -{ - 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; -} - -void list_types(struct systypes *sys) -{ - 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; - - do { - printf("%c%2x %-15.15s", i ? ' ' : '\n', - sys[next].index, sys[next].name); - next = last[i++] + done; - if (i > 3 || next >= last[i]) { - i = 0; - next = ++done; - } - } while (done < last[0]); - putchar('\n'); -} - -void clear_partition(struct partition *p) -{ - p->boot_ind = 0; - p->head = 0; - p->sector = 0; - p->cyl = 0; - p->sys_ind = 0; - p->end_head = 0; - p->end_sector = 0; - p->end_cyl = 0; - set_start_sect(p,0); - set_nr_sects(p,0); -} - -void set_partition(int i, struct partition *p, uint start, uint stop, - int sysid, uint offset) -{ - p->boot_ind = 0; - 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); - if (dos_compatible_flag && (stop/(sectors*heads) > 1023)) - stop = heads*sectors*1024 - 1; - set_hsc(p->end_head, p->end_sector, p->end_cyl, stop); - changed[i] = 1; -} - -int test_c(char **m, char *mesg) -{ - int val = 0; - if (!*m) - fprintf(stderr, "You must set"); - else { - fprintf(stderr, " %s", *m); - val = 1; - } - *m = mesg; - return val; -} - -int warn_geometry(void) -{ - char *m = NULL; - int prev = 0; - if (!heads) - prev = test_c(&m, "heads"); - if (!sectors) - prev = test_c(&m, "sectors"); - if (!cylinders) - prev = test_c(&m, "cylinders"); - if (!m) - return 0; - fprintf(stderr, - "%s%s.\nYou can do this from the extra functions menu.\n", - prev ? " and " : " ", m); - return 1; -} - -uint rounded(uint calcul, uint start) -{ - uint i; - if (!full_bits) - return calcul; - while ((i = calcul + full_bits) <= start) - calcul = i; - return calcul; -} - -void update_units(void) -{ - full_bits = 1024 * heads * sectors; - if (unit_flag && full_bits) - display_factor = full_bits >> 10; - else display_factor = 1; -} - -void warn_cylinders(void) -{ - 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 from other OSs\n" - " (e.g., DOS FDISK, OS/2 FDISK)\n", - cylinders); -} - -void read_extended(struct partition *p) -{ - int i; - struct partition *q; - - ext_pointers[ext_index] = part_table[ext_index]; - if (!get_start_sect(p)) - fprintf(stderr, "Bad offset in primary extended partition\n"); - else while (IS_EXTENDED (p->sys_ind)) { - if (partitions >= MAXIMUM_PARTS) { - fprintf(stderr, - "Warning: deleting partitions after %d\n", - partitions); - clear_partition(ext_pointers[partitions - 1]); - changed[partitions - 1] = 1; - return; - } - offsets[partitions] = extended_offset + get_start_sect(p); - if (!extended_offset) - extended_offset = get_start_sect(p); - if (ext2_llseek(fd, (ext2_loff_t)offsets[partitions] - * SECTOR_SIZE, SEEK_SET) < 0) - fatal(unable_to_seek); - if (!(buffers[partitions] = (char *) malloc(SECTOR_SIZE))) - fatal(out_of_memory); - if (SECTOR_SIZE != read(fd, buffers[partitions], SECTOR_SIZE)) - fatal(unable_to_read); - part_table[partitions] = ext_pointers[partitions] = NULL; - q = p = offset(buffers[partitions], 0); - for (i = 0; i < 4; i++, p++) { - if (IS_EXTENDED (p->sys_ind)) - if (ext_pointers[partitions]) - fprintf(stderr, "Warning: extra link " - "pointer in partition table " - "%d\n", partitions + 1); - else - ext_pointers[partitions] = p; - else if (p->sys_ind) - if (part_table[partitions]) - fprintf(stderr, - "Warning: ignoring extra data " - "in partition table %d\n", - partitions + 1); - else - part_table[partitions] = p; - } - if (!part_table[partitions]) - if (q != ext_pointers[partitions]) - part_table[partitions] = q; - else part_table[partitions] = q + 1; - if (!ext_pointers[partitions]) - if (q != part_table[partitions]) - ext_pointers[partitions] = q; - else ext_pointers[partitions] = q + 1; - p = ext_pointers[partitions++]; - } -} - -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 (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); - -#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; - if (dos_compatible_flag) - sector_offset = sectors; - } else { - if (!ioctl(fd, BLKGETSIZE, §ors)) { - heads = 1; - cylinders = 1; - } else { - heads = cylinders = sectors = 0; - } - } - update_units(); - -got_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(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 (!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 0; -} - -int read_line(void) -{ - if (!fgets(line_buffer, LINE_LENGTH, stdin)) - return 0; - line_ptr = line_buffer; - while (*line_ptr && !isgraph(*line_ptr)) - line_ptr++; - return *line_ptr; -} - -char read_char(char *mesg) -{ - do { - fputs(mesg, stdout); - } while (!read_line()); - return *line_ptr; -} - -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; - - while (1) - { - read_char("Hex code (type L to list codes): "); - if (tolower(*line_ptr) == 'l') - list_types(sys); - else if (isxdigit (*line_ptr)) - { - hex = 0; - do - hex = hex << 4 | hex_val(*line_ptr++); - while (isxdigit(*line_ptr)); - return hex; - } - } -} - - -uint read_int(uint low, uint dflt, uint high, enum offset base, char *mesg) -{ - uint i, use_default = 1; - char ms[70]; - - switch(base) { - case lower: - sprintf(ms, "%s ([%d]-%d): ", mesg, low, high); - break; - case upper: - sprintf(ms, "%s (%d-[%d]): ", mesg, low, high); - break; - case deflt: - sprintf(ms, "%s (%d-[%d]-%d): ", mesg, low, dflt, high); - break; - default: - sprintf(ms, "%s (%d-%d): ", mesg, low, high); - break; - } - - while (1) { - 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; - i = atoi(line_ptr); - while (isdigit(*line_ptr)) - { - line_ptr++; - use_default = 0; - } - switch (*line_ptr) { - case 'c': - case 'C': if (!unit_flag) - i *= heads * sectors; - break; - case 'k': - case 'K': i *= 2; - i /= display_factor; - break; - case 'm': - case 'M': i *= 2048; - i /= display_factor; - break; - default: break; - } - switch(base) { - case lower: i += low; break; - case upper: i += high; break; - case deflt: i += dflt; break; - case ignore: - } - } - else - { - i = atoi(line_ptr); - while (isdigit(*line_ptr)) - { - line_ptr++; - use_default = 0; - } - } - if (use_default) - printf("Using default value %d\n", i = dflt); - if (i >= low && i <= high) - break; - else - printf("Value out of range.\n"); - } - return i; -} - -int get_partition(int warn, int max) -{ - /* - * try to pick a default least likely to do damage, - * in case luser just types a newline - */ - int i = read_int(1, max, max, ignore, "Partition number") - 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; -} - -char *const str_units(void) -{ - return unit_flag ? "cylinder" : "sector"; -} - -void change_units(void) -{ - if ((unit_flag = !unit_flag)) - display_factor = 1; - else display_factor = heads * sectors; - update_units(); - printf("Changing display/entry units to %ss\n", - str_units()); -} - -void toggle_active(int i) -{ - struct partition *p = part_table[i]; - - if (IS_EXTENDED (p->sys_ind) && !p->boot_ind) - fprintf(stderr, - "WARNING: Partition %d is an extended partition\n", - i + 1); - if (p->boot_ind) - p->boot_ind = 0; - else p->boot_ind = ACTIVE_FLAG; - changed[i] = 1; -} - -void toggle_dos(void) -{ - dos_compatible_flag = ~dos_compatible_flag; - printf("DOS Compatibility flag is "); - if (dos_compatible_flag) - sector_offset = sectors; - else { - sector_offset = 1; - printf("not "); - } - printf("set\n"); -} - -void delete_partition(int i) -{ - struct partition *p = part_table[i], *q = ext_pointers[i]; - -/* Note that for the fifth partition (i == 4) we don't actually - * decrement partitions. - */ - - if (warn_geometry()) - return; - changed[i] = 1; -#if defined(sparc) - if (sun_label) { - sun_delete_partition(i); - return; - } -#endif - if (i < 4) { - if (IS_EXTENDED (p->sys_ind) && i == ext_index) { - while (partitions > 4) - free(buffers[--partitions]); - ext_pointers[ext_index] = NULL; - extended_offset = 0; - } - clear_partition(p); - } - else if (!q->sys_ind && i > 4) { - free(buffers[--partitions]); - clear_partition(ext_pointers[--i]); - } - else if (i > 3) { - if (i > 4) { - p = ext_pointers[i - 1]; - p->boot_ind = 0; - p->head = q->head; - p->sector = q->sector; - p->cyl = q->cyl; - p->sys_ind = EXTENDED; - p->end_head = q->end_head; - p->end_sector = q->end_sector; - p->end_cyl = q->end_cyl; - 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 */ - set_start_sect(part_table[5], - get_start_sect(part_table[5]) + - offsets[5] - extended_offset); - offsets[5] = extended_offset; - changed[5] = 1; - } - if (partitions > 5) { - partitions--; - free(buffers[i]); - while (i < partitions) { - changed[i] = changed[i + 1]; - buffers[i] = buffers[i + 1]; - offsets[i] = offsets[i + 1]; - part_table[i] = part_table[i + 1]; - ext_pointers[i] = ext_pointers[i + 1]; - i++; - } - } - else - clear_partition(part_table[i]); - } -} - -void change_sysid(void) -{ - char *temp; - int i = get_partition(0, partitions), sys, origsys; - struct partition *p = part_table[i]; - -#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 - - 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 (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, - * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross, - * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S. - * Lubkin Oct. 1991). */ - -static void long2chs(ulong ls, uint *c, uint *h, uint *s) -{ - int spc = heads * sectors; - - *c = ls / spc; - ls = ls % spc; - *h = ls / sectors; - *s = ls % sectors + 1; /* sectors count from 1 */ -} - -static void check_consistency(struct partition *p, int partition) -{ - uint pbc, pbh, pbs; /* physical beginning c, h, s */ - uint pec, peh, pes; /* physical ending c, h, s */ - uint lbc, lbh, lbs; /* logical beginning c, h, s */ - uint lec, leh, les; /* logical ending c, h, s */ - - if (!heads || !sectors || (partition >= 4)) - return; /* do not check extended partitions */ - -/* physical beginning c, h, s */ - pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300); - pbh = p->head; - pbs = p->sector & 0x3f; - -/* physical ending c, h, s */ - pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300); - peh = p->end_head; - pes = p->end_sector & 0x3f; - -/* compute logical beginning (c, h, s) */ - long2chs(get_start_sect(p), &lbc, &lbh, &lbs); - -/* compute logical ending (c, h, s) */ - 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)) { - printf("Partition %d has different physical/logical " - "beginnings (non-Linux?):\n", partition + 1); - printf(" phys=(%d, %d, %d) ", pbc, pbh, pbs); - printf("logical=(%d, %d, %d)\n",lbc, lbh, lbs); - } - -/* Same physical / logical ending? */ - if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) { - printf("Partition %d has different physical/logical " - "endings:\n", partition + 1); - printf(" phys=(%d, %d, %d) ", pec, peh, pes); - printf("logical=(%d, %d, %d)\n",lec, leh, les); - } - -#if 0 -/* Beginning on cylinder boundary? */ - if (pbh != !pbc || pbs != 1) { - printf("Partition %i does not start on cylinder " - "boundary:\n", partition + 1); - printf(" phys=(%d, %d, %d) ", pbc, pbh, pbs); - printf("should be (%d, %d, 1)\n", pbc, !pbc); - } -#endif - -/* Ending on cylinder boundary? */ - if (peh != (heads - 1) || pes != sectors) { - printf("Partition %i does not end on cylinder boundary:\n", - partition + 1); - printf(" phys=(%d, %d, %d) ", pec, peh, pes); - printf("should be (%d, %d, %d)\n", - pec, heads - 1, sectors); - } -} - -void list_table(int xtra) -{ - struct partition *p; - char *type; - 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 %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) { - 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), - 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) -{ - struct partition *p, **q; - int i; - - if (extend) - q = ext_pointers; - else - q = part_table; - printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n", - disk_device, heads, sectors, cylinders); - printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"); - for (i = 0 ; i < partitions; i++) - if ((p = q[i]) != NULL) { - printf("%2d %02x%4d%4d%5d%4d%4d%5d%8d%8d %02x\n", - i + 1, p->boot_ind, p->head, - sector(p->sector), - cylinder(p->sector, p->cyl), p->end_head, - sector(p->end_sector), - cylinder(p->end_sector, p->end_cyl), - get_start_sect(p), get_nr_sects(p), p->sys_ind); - if (p->sys_ind) - check_consistency(p, i); - } -} - -void check_bounds(uint *first, uint *last) -{ - int i; - uint max = 0xffffffff; /* used to be 256 * 63 * 1024 - but that made it impossible to add a - partition crossing cylinder 8064 */ - struct partition *p = part_table[0]; - - 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 { - first[i] = rounded(calculate(p->head, p->sector, - 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) -{ - uint total, real_s, real_c, i; - - real_s = sector(s) - 1; - real_c = cylinder(s, c); - total = (real_c * sectors + real_s) * heads + h; - if (full_bits) - while ((i = total + full_bits) <= start) { - real_c += 1024; - total = i; - } - if (!total) - fprintf(stderr, "Warning: partition %d contains sector 0\n", n); - if (h >= heads) - fprintf(stderr, - "Partition %d: head %d greater than maximum %d\n", - n, h + 1, heads); - if (real_s >= sectors) - fprintf(stderr, "Partition %d: sector %d greater than " - "maximum %d\n", n, s, sectors); - if (real_c >= cylinders) - fprintf(stderr, "Partitions %d: cylinder %d greater than " - "maximum %d\n", n, real_c + 1, cylinders); - if (cylinders <= 1024 && start != total) - fprintf(stderr, - "Partition %d: previous sectors %d disagrees with " - "total %d\n", n, start, total); -} - - -void verify(void) -{ - int i, j; - uint total = 1, - first[partitions], last[partitions]; - struct partition *p = part_table[0]; - - 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 && !IS_EXTENDED (p->sys_ind)) { - check_consistency(p, 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, - last[i]); - total += last[i] + 1 - first[i]; - for (j = 0; j < i; j++) - if ((first[i] >= first[j] && first[i] <= last[j]) - || ((last[i] <= last[j] && last[i] >= first[j]))) { - printf("Warning: partition %d overlaps " - "partition %d.\n", j + 1, i + 1); - total += first[i] >= first[j] ? - first[i] : first[j]; - total -= last[i] <= last[j] ? - last[i] : last[j]; - } - } - - if (extended_offset) { - 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]) { - total++; - if (!p->sys_ind) { - if (i != 4 || i + 1 < partitions) - printf("Warning: partition %d " - "is empty\n", i + 1); - } - else if (first[i] < extended_offset || - last[i] > e_last) - printf("Logical partition %d not entirely in " - "partition %d\n", i + 1, ext_index + 1); - } - } - - if (total > heads * sectors * cylinders) - printf("Total allocated sectors %d greater than the maximum " - "%d\n", total, heads * sectors * cylinders); - else if ((total = heads * sectors * cylinders - total) != 0) - printf("%d unallocated sectors\n", total); -} - -void add_partition(int n, int sys) -{ - char mesg[48]; - int i, read = 0; - struct partition *p = part_table[n], *q = part_table[ext_index]; - uint start, stop = 0, limit, temp, - first[partitions], last[partitions]; - - if (p->sys_ind) { - printf("Partition %d is already defined. Delete " - "it before re-adding it.\n", n + 1); - return; - } - check_bounds(first, last); - if (n < 4) { - start = sector_offset; - limit = heads * sectors * cylinders - 1; - if (extended_offset) { - first[ext_index] = extended_offset; - last[ext_index] = get_start_sect(q) + - get_nr_sects(q) - 1; - } - } else { - start = extended_offset + sector_offset; - limit = get_start_sect(q) + get_nr_sects(q) - 1; - } - if (unit_flag) - for (i = 0; i < partitions; i++) - first[i] = (cround(first[i]) - 1) * display_factor; - - sprintf(mesg, "First %s", str_units()); - do { - temp = start; - for (i = 0; i < partitions; i++) { - int lastplusoff; - - if (start == offsets[i]) - start += 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+display_factor && read) { - printf("Sector %d is already allocated\n", temp); - temp = start; - read = 0; - } - if (!read && start == temp) { - uint i; - 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); - if (n > 4) /* NOT for fifth partition */ - offsets[n] = start - sector_offset; - - for (i = 0; i < partitions; i++) { - if (start < offsets[i] && limit >= offsets[i]) - limit = offsets[i] - 1; - if (start < first[i] && limit >= first[i]) - limit = first[i] - 1; - } - if (start > limit) { - printf("No free sectors available\n"); - if (n > 4) { - free(buffers[n]); - partitions--; - } - return; - } - if (cround(start) == cround(limit)) - stop = start; - else { - sprintf(mesg, "Last %s or +size or +sizeM or +sizeK", - str_units()); - stop = read_int(cround(start), cround(limit), cround(limit), - lower, mesg); - if (unit_flag) { - stop = stop * display_factor - 1; - if (stop >limit) - stop = limit; - } - } - - set_partition(n, p, start, stop, sys, offsets[n]); - - if (IS_EXTENDED (sys)) { - ext_index = n; - offsets[4] = extended_offset = start; - ext_pointers[n] = p; - if (!(buffers[4] = calloc(1, SECTOR_SIZE))) - fatal(out_of_memory); - part_table[4] = offset(buffers[4], 0); - ext_pointers[4] = part_table[4] + 1; - changed[4] = 1; - partitions = 5; - } - else { - if (n > 4) - set_partition(n - 1, ext_pointers[n - 1], - start - sector_offset, stop, EXTENDED, - extended_offset); -#if 0 - if ((limit = get_nr_sects(p)) & 1) - printf("Warning: partition %d has an odd " - "number of sectors.\n", n + 1); -#endif - } -} - -void add_logical(void) -{ - if (partitions > 5 || part_table[4]->sys_ind) { - if (!(buffers[partitions] = calloc(1, SECTOR_SIZE))) - fatal(out_of_memory); - part_table[partitions] = offset(buffers[partitions], 0); - ext_pointers[partitions] = part_table[partitions] + 1; - offsets[partitions] = 0; - partitions++; - } - add_partition(partitions - 1, LINUX_NATIVE); -} - -void new_partition(void) -{ - int i, free_primary = 0; - - 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; - } - - for (i = 0; i < 4; i++) - free_primary += !part_table[i]->sys_ind; - if (!free_primary) - if (extended_offset) - add_logical(); - else - printf("You must delete some partition and add " - "an extended partition first\n"); - else { - char c, line[LINE_LENGTH]; - sprintf(line, "Command action\n %s\n p primary " - "partition (1-4)\n", extended_offset ? - "l logical (5 or over)" : "e extended"); - while (1) - if ((c = tolower(read_char(line))) == 'p') { - add_partition(get_partition(0, 4), - LINUX_NATIVE); - return; - } - else if (c == 'l' && extended_offset) { - add_logical(); - return; - } - else if (c == 'e' && !extended_offset) { - add_partition(get_partition(0, 4), - EXTENDED); - return; - } - else - printf("Invalid partition number " - "for type `%c'\n", c); - - } -} - -void write_table(void) -{ - int i, error = 0; - - changed[3] = changed[0] || changed[1] || changed[2] || changed[3]; - if (!sun_label) { - for (i = 3; i < partitions; i++) { - if (changed[i]) { - 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"); - - printf("Calling ioctl() to re-read partition table.\n"); - sync(); - sleep(2); - if ((i = ioctl(fd, BLKRRPART)) != 0) { - error = errno; - } else { - /* some kernel versions (1.2.x) seem to have trouble - rereading the partition table, but if asked to do it - twice, the second time works. - biro@yggdrasil.com */ - sync(); - sleep(2); - if((i = ioctl(fd, BLKRRPART)) != 0) - error = errno; - } - - close(fd); - - printf("Syncing disks.\n"); - sync(); - sleep(4); /* for sync() */ - - if (i < 0) - printf("Re-read table failed with error %d: %s.\nReboot your " - "system to ensure the partition table is updated.\n", - error, strerror(error)); - - 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"); - - exit(0); -} - -#define MAX_PER_LINE 16 -void print_buffer(char buffer[]) -{ - int i, - l; - - for (i = 0, l = 0; i < SECTOR_SIZE; i++, l++) { - if (l == 0) - printf("0x%03X:", i); - printf(" %02X", (unsigned char) buffer[i]); - if (l == MAX_PER_LINE - 1) { - printf("\n"); - l = -1; - } - } - if (l > 0) - printf("\n"); - printf("\n"); -} - -void print_raw(void) -{ - int i; - - printf("Device: %s\n", disk_device); - if (sun_label) - print_buffer(buffer); - else for (i = 3; i < partitions; i++) - print_buffer(buffers[i]); -} - -void move_begin(int i) -{ - struct partition *p = part_table[i]; - uint new, first; - - if (warn_geometry()) - return; - 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), - get_start_sect(p) + offsets[i]); - new = read_int(first, first, - get_start_sect(p) + get_nr_sects(p) + offsets[i] - 1, - lower, "New beginning of data") - offsets[i]; - - 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; - } -} - -void xselect(void) -{ - while(1) { - putchar('\n'); - switch (tolower(read_char("Expert command (m for help): "))) { -#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(); - } - } -} - -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(try_only) < 0) { - if (btrydev(device) < 0) - fprintf(stderr, - "Disk doesn't contain a valid " - "partition table\n"); - close(fd); - } else { - close(fd); - list_table(0); - if (!sun_label && partitions > 4) - delete_partition(ext_index); - } - } else { - /* Ignore other errors, since we try IDE - and SCSI hard disks which may not be - installed on the system. */ - if(errno == EACCES) { - fprintf(stderr, "Cannot open %s\n", device); - return; - } - } - } -} - -void -dummy(int *kk) {} - -void main(int argc, char **argv) -{ - 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); - } - } - - 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-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(fdisk); - - while (1) { - putchar('\n'); - switch (tolower(read_char("Command (m for help): "))) { - 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 - toggle_dos(); - 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 deleted file mode 100644 index 11f529d48..000000000 --- a/disk-utils/fdisk.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - fdisk.h -*/ - -#define SECTOR_SIZE 512 -#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) -typedef long long ext2_loff_t; -#else -typedef long ext2_loff_t; -#endif - -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; -}; - -/* prototypes for fdisk.c */ -extern char *disk_device, - *line_ptr; -extern int fd, - partitions; -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); -extern int read_line (void); -extern char read_char(char *mesg); -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 int btrydev (char * dev); - -/* prototypes for fdisksunlabel.c */ diff --git a/disk-utils/fdisklabel.c b/disk-utils/fdisklabel.c deleted file mode 100644 index d98d49d0d..000000000 --- a/disk-utils/fdisklabel.c +++ /dev/null @@ -1,815 +0,0 @@ -/* - NetBSD disklabel editor for Linux fdisk - Written by Bernhard Fastenrath (fasten@informatik.uni-bonn.de) - with code from the NetBSD disklabel command: - - Copyright (c) 1987, 1988 Regents of the University of California. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by the University of - California, Berkeley and its contributors. - 4. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. -*/ - -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <ctype.h> -#include <setjmp.h> -#include <errno.h> - -#include <sys/ioctl.h> -#include <sys/param.h> - -#include <linux/hdreg.h> /* for HDIO_GETGEO */ - -#include "fdisk.h" -#define NETBSD_PARTITION 0xa5 -#define DKTYPENAMES -#include "fdisklabel.h" - -static void xbsd_delete_part (void); -static void xbsd_new_part (void); -static void xbsd_print_disklabel (int show_all); -static void xbsd_write_disklabel (void); -static int xbsd_create_disklabel (void); -static void xbsd_edit_disklabel (void); -static void xbsd_write_bootstrap (void); -static void xbsd_change_fstype (void); -static int xbsd_get_part_index (int max); -static int xbsd_check_new_partition (int *i); -static void xbsd_list_types (void); -static u_short xbsd_dkcksum (struct xbsd_disklabel *lp); -static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex); -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) || defined (sparc) -static int xbsd_translate_fstype (int linux_type); -static void xbsd_link_part (void); -#endif -#if defined (__alpha__) -void alpha_bootblock_checksum (char *boot); -#endif - -static struct xbsd_disklabel xbsd_dlabel; -static char buffer[BSD_BBSIZE]; -#if defined (i386) || defined (sparc) -static struct partition *xbsd_part; -static int xbsd_part_index; -#endif - -int -btrydev (char * dev) { - if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0) - return -1; - printf("\nBSD label for device: %s\n", dev); - xbsd_print_disklabel (0); - return 0; -} - -void -bmenu (void) -{ - puts ("Command action\n" - " d delete a BSD partition\n" - " e edit drive data\n" - " i install bootstrap\n" - " l list known filesystem types\n" - " m print this menu\n" - " n add a new BSD partition\n" - " p print BSD partition table\n" - " q quit without saving changes\n" -#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) || defined (sparc) - " x link BSD partition to non-BSD partition" -#endif - ); -} - -void -bselect (void) -{ -#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; - 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, ss + BSD_LABELSECTOR); - if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0) - if (xbsd_create_disklabel () == 0) - return; - break; - } - - if (t == 4) - { - printf ("There is no NetBSD partition on %s.\n", disk_device); - return; - } - -#elif defined (__alpha__) - - if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0) - if (xbsd_create_disklabel () == 0) - exit ( EXIT_SUCCESS ); - -#endif - - while (1) - { - putchar ('\n'); - switch (tolower (read_char ("BSD disklabel command (m for help): "))) - { - case 'd': - xbsd_delete_part (); - break; - case 'e': - xbsd_edit_disklabel (); - break; - case 'i': - xbsd_write_bootstrap (); - break; - case 'l': - xbsd_list_types (); - break; - case 'n': - xbsd_new_part (); - break; - case 'p': - xbsd_print_disklabel (0); - break; - case 'q': - close (fd); - exit ( EXIT_SUCCESS ); - case 's': - xbsd_print_disklabel (1); - break; - case 't': - xbsd_change_fstype (); - break; - case 'w': - xbsd_write_disklabel (); - break; -#if defined (i386) || defined (sparc) - case 'r': - return; - case 'x': - xbsd_link_part (); - break; -#endif - default: - bmenu (); - break; - } - } -} - -static void -xbsd_delete_part (void) -{ - int i; - - i = xbsd_get_part_index (xbsd_dlabel.d_npartitions); - xbsd_dlabel.d_partitions[i].p_size = 0; - xbsd_dlabel.d_partitions[i].p_offset = 0; - xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED; - if (xbsd_dlabel.d_npartitions == i + 1) - while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0) - xbsd_dlabel.d_npartitions--; -} - -static void -xbsd_new_part (void) -{ - uint begin, end; - char mesg[48]; - int i; - - if (!xbsd_check_new_partition (&i)) - return; - -#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; -#endif - - sprintf (mesg, "First %s", str_units()); - begin = read_int (cround (begin), cround (begin), cround (end), ignore, mesg); - - sprintf (mesg, "Last %s or +size or +sizeM or +sizeK", str_units()); - end = read_int (cround (begin), cround (end), cround (end), ignore, mesg); - - if (unit_flag) - { - begin = (begin - 1) * display_factor; - end = end * display_factor - 1; - } - xbsd_dlabel.d_partitions[i].p_size = end - begin + 1; - xbsd_dlabel.d_partitions[i].p_offset = begin; - xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED; -} - -static void -xbsd_print_disklabel (int show_all) -{ - struct xbsd_disklabel *lp = &xbsd_dlabel; - struct xbsd_partition *pp; - FILE *f = stdout; - int i, j; - - if (show_all) - { -#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); -#endif - if ((unsigned) lp->d_type < BSD_DKMAXTYPES) - fprintf(f, "type: %s\n", xbsd_dktypenames[lp->d_type]); - else - fprintf(f, "type: %d\n", lp->d_type); - fprintf(f, "disk: %.*s\n", (int) sizeof(lp->d_typename), lp->d_typename); - fprintf(f, "label: %.*s\n", (int) sizeof(lp->d_packname), lp->d_packname); - fprintf(f, "flags:"); - if (lp->d_flags & BSD_D_REMOVABLE) - fprintf(f, " removable"); - if (lp->d_flags & BSD_D_ECC) - fprintf(f, " ecc"); - if (lp->d_flags & BSD_D_BADSECT) - fprintf(f, " badsect"); - fprintf(f, "\n"); - /* On various machines the fields of *lp are short/int/long */ - /* In order to avoid problems, we cast them all to long. */ - fprintf(f, "bytes/sector: %ld\n", (long) lp->d_secsize); - fprintf(f, "sectors/track: %ld\n", (long) lp->d_nsectors); - fprintf(f, "tracks/cylinder: %ld\n", (long) lp->d_ntracks); - fprintf(f, "sectors/cylinder: %ld\n", (long) lp->d_secpercyl); - fprintf(f, "cylinders: %ld\n", (long) lp->d_ncylinders); - fprintf(f, "rpm: %d\n", lp->d_rpm); - fprintf(f, "interleave: %d\n", lp->d_interleave); - fprintf(f, "trackskew: %d\n", lp->d_trackskew); - fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); - fprintf(f, "headswitch: %ld\t\t# milliseconds\n", (long) lp->d_headswitch); - fprintf(f, "track-to-track seek: %ld\t# milliseconds\n", (long) lp->d_trkseek); - fprintf(f, "drivedata: "); - for (i = NDDATA - 1; i >= 0; i--) - if (lp->d_drivedata[i]) - break; - if (i < 0) - i = 0; - for (j = 0; j <= i; j++) - fprintf(f, "%ld ", (long) lp->d_drivedata[j]); - } - fprintf (f, "\n%d partitions:\n", lp->d_npartitions); - fprintf (f, "# size offset fstype [fsize bsize cpg]\n"); - pp = lp->d_partitions; - for (i = 0; i < lp->d_npartitions; i++, pp++) { - if (pp->p_size) { - fprintf(f, " %c: %8ld %8ld ", 'a' + i, - (long) pp->p_size, (long) pp->p_offset); - if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES) - fprintf(f, "%8.8s", xbsd_fstypes[pp->p_fstype].name); - else - fprintf(f, "%8x", pp->p_fstype); - switch (pp->p_fstype) - { - case BSD_FS_UNUSED: - fprintf(f, " %5ld %5ld %5.5s ", - (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, ""); - break; - - case BSD_FS_BSDFFS: - fprintf(f, " %5ld %5ld %5d ", - (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, - pp->p_cpg); - break; - - default: - fprintf(f, "%20.20s", ""); - break; - } - fprintf(f, "\t# (Cyl. %4ld", (long) -#if 0 - pp->p_offset / lp->d_secpercyl); /* differs from Linux fdisk */ -#else - pp->p_offset / lp->d_secpercyl + 1); -#endif - if (pp->p_offset % lp->d_secpercyl) - putc('*', f); - else - putc(' ', f); - fprintf(f, "- %ld", - (long) (pp->p_offset + - pp->p_size + lp->d_secpercyl - 1) / -#if 0 - lp->d_secpercyl - 1); /* differs from Linux fdisk */ -#else - lp->d_secpercyl); -#endif - if (pp->p_size % lp->d_secpercyl) - putc('*', f); - fprintf(f, ")\n"); - } - } -} - -static void -xbsd_write_disklabel (void) -{ -#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__) - printf ("Writing disklabel to %s.\n", disk_device); - xbsd_writelabel (NULL, &xbsd_dlabel); -#endif -} - -static int -xbsd_create_disklabel (void) -{ - char c; - -#if defined (i386) || defined (sparc) - fprintf (stderr, "%s%d contains no disklabel.\n", - disk_device, xbsd_part_index+1); -#elif defined (__alpha__) - fprintf (stderr, "%s contains no disklabel.\n", disk_device); -#endif - - while (1) - if ((c = tolower (read_char ("Do you want to create a disklabel? (y/n) "))) == 'y') - { -#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) -#endif - { - xbsd_print_disklabel (1); - return 1; - } - else - return 0; - } - else if (c == 'n') - return 0; -} - -static int -edit_int (int def, char *mesg) -{ - do { - fputs (mesg, stdout); - printf (" (%d): ", def); - if (!read_line ()) - return def; - } - while (!isdigit (*line_ptr)); - return atoi (line_ptr); -} - -static void -xbsd_edit_disklabel (void) -{ - struct xbsd_disklabel *d; - - d = &xbsd_dlabel; - -#ifdef __alpha__ - d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,"bytes/sector"); - d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,"sectors/track"); - d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,"tracks/cylinder"); - d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,"cylinders"); -#endif - - /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */ - while (1) - { - d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks, - "sectors/cylinder"); - if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks) - break; - - printf ("Must be <= sectors/track * tracks/cylinder (default).\n"); - } - d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,"rpm"); - d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,"interleave"); - d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,"trackskew"); - d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,"cylinderskew"); - d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,"headswitch"); - d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,"track-to-track seek"); - - d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders; -} - -static int -xbsd_get_bootstrap (char *path, void *ptr, int size) -{ - int fd; - - if ((fd = open (path, O_RDONLY)) < 0) - { - perror (path); - return 0; - } - if (read (fd, ptr, size) < 0) - { - perror (path); - close (fd); - return 0; - } - printf (" ... %s\n", path); - close (fd); - return 1; -} - -static void -xbsd_write_bootstrap (void) -{ - char *bootdir = BSD_LINUX_BOOTDIR; - char path[MAXPATHLEN]; - char *dkbasename; - struct xbsd_disklabel dl; - char *d, *p, *e; - int sector; - - if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI) - dkbasename = "sd"; - else - dkbasename = "wd"; - - printf ("Bootstrap: %sboot -> boot%s (%s): ", dkbasename, dkbasename, dkbasename); - if (read_line ()) - { - line_ptr[strlen (line_ptr)-1] = '\0'; - dkbasename = line_ptr; - } - sprintf (path, "%s/%sboot", bootdir, dkbasename); - if (!xbsd_get_bootstrap (path, buffer, (int) xbsd_dlabel.d_secsize)) - return; - - /* We need a backup of the disklabel (xbsd_dlabel might have changed). */ - d = &buffer[BSD_LABELSECTOR * SECTOR_SIZE]; - bcopy (d, &dl, sizeof (struct xbsd_disklabel)); - - /* The disklabel will be overwritten by 0's from bootxx anyway */ - bzero (d, sizeof (struct xbsd_disklabel)); - - sprintf (path, "%s/boot%s", bootdir, dkbasename); - if (!xbsd_get_bootstrap (path, &buffer[xbsd_dlabel.d_secsize], - (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize)) - return; - - e = d + sizeof (struct xbsd_disklabel); - for (p=d; p < e; p++) - if (*p) - { - fprintf (stderr, "Bootstrap overlaps with disk label!\n"); - exit ( EXIT_FAILURE ); - } - - bcopy (&dl, d, sizeof (struct xbsd_disklabel)); - -#if defined (i386) || defined (sparc) - sector = get_start_sect(xbsd_part); -#elif defined (__alpha__) - sector = 0; - alpha_bootblock_checksum (buffer); -#endif - - if (ext2_llseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1) - fatal (unable_to_seek); - if (BSD_BBSIZE != write (fd, buffer, BSD_BBSIZE)) - fatal (unable_to_write); - -#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); -#endif - - sync_disks (); -} - -static void -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); -} - -static int -xbsd_get_part_index (int max) -{ - char prompt[40]; - char l; - - sprintf (prompt, "Partition (a-%c): ", 'a' + max - 1); - do - l = tolower (read_char (prompt)); - while (l < 'a' || l > 'a' + max - 1); - return l - 'a'; -} - -static int -xbsd_check_new_partition (int *i) -{ - int t; - - if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) - { - for (t=0; t < BSD_MAXPARTITIONS; t++) - if (xbsd_dlabel.d_partitions[t].p_size == 0) - break; - - if (t == BSD_MAXPARTITIONS) - { - fprintf (stderr, "The maximum number of partitions has been created\n"); - return 0; - } - } - *i = xbsd_get_part_index (BSD_MAXPARTITIONS); - - if (*i >= xbsd_dlabel.d_npartitions) - xbsd_dlabel.d_npartitions = (*i) + 1; - - if (xbsd_dlabel.d_partitions[*i].p_size != 0) - { - fprintf (stderr, "This partition already exists.\n"); - return 0; - } - return 1; -} - -static void -xbsd_list_types (void) -{ - list_types (xbsd_fstypes); -} - -static u_short -xbsd_dkcksum (struct xbsd_disklabel *lp) -{ - register u_short *start, *end; - register u_short sum = 0; - - start = (u_short *)lp; - end = (u_short *)&lp->d_partitions[lp->d_npartitions]; - while (start < end) - sum ^= *start++; - return (sum); -} - -static int -xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) -{ - struct hd_geometry geometry; - struct xbsd_partition *pp; - - if (ioctl (fd, HDIO_GETGEO, &geometry) == -1) - { - perror ("ioctl"); - return 0; - } - bzero (d, sizeof (struct xbsd_disklabel)); - - d -> d_magic = BSD_DISKMAGIC; - - if (strncmp (disk_device, "/dev/sd", 7) == 0) - d -> d_type = BSD_DTYPE_SCSI; - else - d -> d_type = BSD_DTYPE_ST506; - -#if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */ - d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex; -#endif - -#if defined (i386) || defined (sparc) - d -> d_flags = BSD_D_DOSPART; -#else - d -> d_flags = 0; -#endif - d -> d_secsize = SECTOR_SIZE; /* bytes/sector */ - d -> d_nsectors = geometry.sectors; /* sectors/track */ - d -> d_ntracks = geometry.heads; /* tracks/cylinder (heads) */ - d -> d_ncylinders = geometry.cylinders; - d -> d_secpercyl = geometry.sectors * geometry.heads; /* sectors/cylinder */ - d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders; - - d -> d_rpm = 3600; - d -> d_interleave = 1; - d -> d_trackskew = 0; - d -> d_cylskew = 0; - d -> d_headswitch = 0; - d -> d_trkseek = 0; - - d -> d_magic2 = BSD_DISKMAGIC; - d -> d_bbsize = BSD_BBSIZE; - d -> d_sbsize = BSD_SBSIZE; - -#if defined (i386) || defined (sparc) - d -> d_npartitions = 4; - pp = &d -> d_partitions[2]; /* Partition C should be the NetBSD partition */ - 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; - pp -> p_size = d -> d_secperunit; - pp -> p_fstype = BSD_FS_UNUSED; -#elif defined (__alpha__) - d -> d_npartitions = 3; - pp = &d -> d_partitions[2]; /* Partition C should be the whole disk */ - pp -> p_offset = 0; - pp -> p_size = d -> d_secperunit; - pp -> p_fstype = BSD_FS_UNUSED; -#endif - - return 1; -} - -static int -xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d) -{ - int t, sector; - -#if defined (i386) || defined (sparc) - sector = (p ? get_start_sect(p) : 0); -#elif defined (__alpha__) - sector = 0; -#endif - - if (ext2_llseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1) - fatal (unable_to_seek); - if (BSD_BBSIZE != read (fd, buffer, BSD_BBSIZE)) - fatal (unable_to_read); - - bcopy (&buffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET], - d, sizeof (struct xbsd_disklabel)); - - for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) - { - d -> d_partitions[t].p_size = 0; - d -> d_partitions[t].p_offset = 0; - d -> d_partitions[t].p_fstype = BSD_FS_UNUSED; - } - if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC) - return 0; - - if (d -> d_npartitions > BSD_MAXPARTITIONS) - fprintf (stderr, "Warning: too many partitions (%d, maximum is %d).\n", - d -> d_npartitions, BSD_MAXPARTITIONS); - return 1; -} - -static int -xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d) -{ - int sector; - -#if defined (i386) || defined (sparc) - sector = get_start_sect(p) + BSD_LABELSECTOR; -#elif defined (__alpha__) - sector = BSD_LABELSECTOR; -#endif - - d -> d_checksum = 0; - d -> d_checksum = xbsd_dkcksum (d); - - /* This is necessary if we want to write the bootstrap later, - otherwise we'd write the old disklabel with the bootstrap. - */ - bcopy (d, &buffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET], - sizeof (struct xbsd_disklabel)); - -#if defined (__alpha__) && BSD_LABELSECTOR == 0 - alpha_bootblock_checksum (buffer); - if (ext2_llseek (fd, 0, SEEK_SET) == -1) - fatal (unable_to_seek); - if (BSD_BBSIZE != write (fd, buffer, BSD_BBSIZE)) - fatal (unable_to_write); -#else - if (ext2_llseek (fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1) - fatal (unable_to_seek); - if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel))) - fatal (unable_to_write); -#endif - - sync_disks (); - - return 1; -} - -static void -sync_disks (void) -{ - printf ("\nSyncing disks.\n"); - sync (); - sleep (4); -} - -#if defined (i386) || defined (sparc) -static int -xbsd_translate_fstype (int linux_type) -{ - switch (linux_type) - { - case 0x01: /* DOS 12-bit FAT */ - case 0x04: /* DOS 16-bit <32M */ - case 0x06: /* DOS 16-bit >=32M */ - case 0xe1: /* DOS access */ - case 0xe3: /* DOS R/O */ - case 0xf2: /* DOS secondary */ - return BSD_FS_MSDOS; - case 0x07: /* OS/2 HPFS */ - return BSD_FS_HPFS; - default: - return BSD_FS_OTHER; - } -} - -static void -xbsd_link_part (void) -{ - int k, i; - - k = get_partition (1, partitions); - - if (!xbsd_check_new_partition (&i)) - return; - - 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); -} -#endif - -#if defined (__alpha__) - -#if 0 -typedef unsigned long long u_int64_t; -#endif - -void -alpha_bootblock_checksum (char *boot) -{ - u_int64_t *dp, sum; - int i; - - dp = (u_int64_t *)boot; - sum = 0; - for (i = 0; i < 63; i++) - sum += dp[i]; - dp[63] = sum; -} -#endif /* __alpha__ */ diff --git a/disk-utils/fdisklabel.h b/disk-utils/fdisklabel.h deleted file mode 100644 index 06435f4d1..000000000 --- a/disk-utils/fdisklabel.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 1987, 1988 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <linux/types.h> /* for __u32 etc */ - -#ifndef BSD_DISKMAGIC /* perhaps from <linux/genhd.h> */ -#define BSD_DISKMAGIC ((__u32) 0x82564557) -#endif - -#ifndef BSD_MAXPARTITIONS -#define BSD_MAXPARTITIONS 8 -#endif - -#define BSD_LINUX_BOOTDIR "/usr/ucb/mdec" - -#if defined (i386) || defined (sparc) -#define BSD_LABELSECTOR 1 -#define BSD_LABELOFFSET 0 -#elif defined (__alpha__) -#define BSD_LABELSECTOR 0 -#define BSD_LABELOFFSET 64 -#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 */ - __s16 d_subtype; /* controller/d_type specific */ - char d_typename[16]; /* type name, e.g. "eagle" */ - char d_packname[16]; /* pack identifier */ - /* disk geometry: */ - __u32 d_secsize; /* # of bytes per sector */ - __u32 d_nsectors; /* # of data sectors per track */ - __u32 d_ntracks; /* # of tracks per cylinder */ - __u32 d_ncylinders; /* # of data cylinders per unit */ - __u32 d_secpercyl; /* # of data sectors per cylinder */ - __u32 d_secperunit; /* # of data sectors per unit */ - /* - * Spares (bad sector replacements) below - * are not counted in d_nsectors or d_secpercyl. - * Spare sectors are assumed to be physical sectors - * which occupy space at the end of each track and/or cylinder. - */ - __u16 d_sparespertrack; /* # of spare sectors per track */ - __u16 d_sparespercyl; /* # of spare sectors per cylinder */ - /* - * Alternate cylinders include maintenance, replacement, - * configuration description areas, etc. - */ - __u32 d_acylinders; /* # of alt. cylinders per unit */ - - /* hardware characteristics: */ - /* - * d_interleave, d_trackskew and d_cylskew describe perturbations - * in the media format used to compensate for a slow controller. - * Interleave is physical sector interleave, set up by the formatter - * or controller when formatting. When interleaving is in use, - * logically adjacent sectors are not physically contiguous, - * but instead are separated by some number of sectors. - * It is specified as the ratio of physical sectors traversed - * per logical sector. Thus an interleave of 1:1 implies contiguous - * layout, while 2:1 implies that logical sector 0 is separated - * by one sector from logical sector 1. - * d_trackskew is the offset of sector 0 on track N - * relative to sector 0 on track N-1 on the same cylinder. - * Finally, d_cylskew is the offset of sector 0 on cylinder N - * relative to sector 0 on cylinder N-1. - */ - __u16 d_rpm; /* rotational speed */ - __u16 d_interleave; /* hardware sector interleave */ - __u16 d_trackskew; /* sector 0 skew, per track */ - __u16 d_cylskew; /* sector 0 skew, per cylinder */ - __u32 d_headswitch; /* head switch time, usec */ - __u32 d_trkseek; /* track-to-track seek, usec */ - __u32 d_flags; /* generic flags */ -#define NDDATA 5 - __u32 d_drivedata[NDDATA]; /* drive-type specific information */ -#define NSPARE 5 - __u32 d_spare[NSPARE]; /* reserved for future use */ - __u32 d_magic2; /* the magic number (again) */ - __u16 d_checksum; /* xor of data incl. partitions */ - /* filesystem and partition information: */ - __u16 d_npartitions; /* number of partitions in following */ - __u32 d_bbsize; /* size of boot area at sn0, bytes */ - __u32 d_sbsize; /* max size of fs superblock, bytes */ - struct xbsd_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 */ -}; - -/* d_type values: */ -#define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */ -#define BSD_DTYPE_MSCP 2 /* MSCP */ -#define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */ -#define BSD_DTYPE_SCSI 4 /* SCSI */ -#define BSD_DTYPE_ESDI 5 /* ESDI interface */ -#define BSD_DTYPE_ST506 6 /* ST506 etc. */ -#define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */ -#define BSD_DTYPE_HPFL 8 /* HP Fiber-link */ -#define BSD_DTYPE_FLOPPY 10 /* floppy */ - -/* d_subtype values: */ -#define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */ -#define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */ -#define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */ - -#ifdef DKTYPENAMES -static char *xbsd_dktypenames[] = { - "unknown", - "SMD", - "MSCP", - "old DEC", - "SCSI", - "ESDI", - "ST506", - "HP-IB", - "HP-FL", - "type 9", - "floppy", - 0 -}; -#define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1) -#endif - -/* - * Filesystem type and version. - * Used to interpret other filesystem-specific - * per-partition information. - */ -#define BSD_FS_UNUSED 0 /* unused */ -#define BSD_FS_SWAP 1 /* swap */ -#define BSD_FS_V6 2 /* Sixth Edition */ -#define BSD_FS_V7 3 /* Seventh Edition */ -#define BSD_FS_SYSV 4 /* System V */ -#define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */ -#define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */ -#define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */ -#define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */ -#define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */ -#define BSD_FS_HPFS 11 /* OS/2 high-performance file system */ -#define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */ -#define BSD_FS_ISOFS BSD_FS_ISO9660 -#define BSD_FS_BOOT 13 /* partition contains bootstrap */ -#define BSD_FS_ADOS 14 /* AmigaDOS fast file system */ -#define BSD_FS_HFS 15 /* Macintosh HFS */ - -/* this is annoying, but it's also the way it is :-( */ -#ifdef __alpha__ -#define BSD_FS_EXT2 8 /* MS-DOS file system */ -#else -#define BSD_FS_MSDOS 8 /* MS-DOS file system */ -#endif - -#ifdef DKTYPENAMES -static struct systypes xbsd_fstypes[] = { - {BSD_FS_UNUSED, "unused"}, - {BSD_FS_SWAP, "swap"}, - {BSD_FS_V6, "Version 6"}, - {BSD_FS_V7, "Version 7"}, - {BSD_FS_SYSV, "System V"}, - {BSD_FS_V71K, "4.1BSD"}, - {BSD_FS_V8, "Eighth Edition"}, - {BSD_FS_BSDFFS, "4.2BSD"}, -#ifdef __alpha__ - {BSD_FS_EXT2, "ext2"}, -#else - {BSD_FS_MSDOS, "MS-DOS"}, -#endif - {BSD_FS_BSDLFS, "4.4LFS"}, - {BSD_FS_OTHER, "unknown"}, - {BSD_FS_HPFS, "HPFS"}, - {BSD_FS_ISO9660,"ISO-9660"}, - {BSD_FS_BOOT, "boot"}, - {BSD_FS_ADOS, "ADOS"}, - {BSD_FS_HFS, "HFS"}, - { 0, NULL } -}; -#define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1) - -#endif - -/* - * flags shared by various drives: - */ -#define BSD_D_REMOVABLE 0x01 /* removable media */ -#define BSD_D_ECC 0x02 /* supports ECC */ -#define BSD_D_BADSECT 0x04 /* supports bad sector forw. */ -#define BSD_D_RAMDISK 0x08 /* disk emulator */ -#define BSD_D_CHAIN 0x10 /* can do back-back transfers */ -#define BSD_D_DOSPART 0x20 /* within MSDOS partition */ diff --git a/disk-utils/fdisksunlabel.c b/disk-utils/fdisksunlabel.c deleted file mode 100644 index a5a87b8d4..000000000 --- a/disk-utils/fdisksunlabel.c +++ /dev/null @@ -1,661 +0,0 @@ -/* - * 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 deleted file mode 100644 index 037e437c6..000000000 --- a/disk-utils/fdisksunlabel.h +++ /dev/null @@ -1,73 +0,0 @@ -#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/fdprm b/disk-utils/fdprm index 2a59da018..a9282e1e6 100644 --- a/disk-utils/fdprm +++ b/disk-utils/fdprm @@ -24,3 +24,5 @@ 1680/1440 3360 21 2 80 0 0x0C 0x00 0xCF 0x6C # ????? # Add user-specific formats here +cbm1581 1600 10 2 80 2 0x2A 0x02 0xDF 0x2E +800/720 1600 10 2 80 0 0x2A 0x02 0xDF 0x2E diff --git a/disk-utils/frag.8 b/disk-utils/frag.8 deleted file mode 100644 index c2f67b581..000000000 --- a/disk-utils/frag.8 +++ /dev/null @@ -1,47 +0,0 @@ -.\" Copyright 1992,1993,1994 Rickard E. Faith (faith@cs.unc.edu) -.\" May be distributed under the GNU General Public License -.TH FRAG 8 "8 January 1994" "Linux 0.99" "Linux Programmer's Manual" -.SH NAME -frag \- simple fragmentation checker -.SH SYNOPSIS -.B /usr/sbin/frag -.B "[ \-s [ \-s ]]" -filename ... -.SH DESCRIPTION -.B frag -will report the file system fragmentation on a specified -.IR filename . -If the -.I filename -is a directory, -.B frag -will recursively descend the directory. -.SH OPTIONS -.TP -.B \-s -Silent (may be set to 1 or 2). The first -.B \-s -eliminates the file by file statistics, and just prints the -examined directories and a summary. The second -.B \-s -eliminates the printing of the directories, and just prints a -summary. This option is useful when -.B frag -is used on a directory. -.SH "SEE ALSO" -.BR mkfs (8), -.BR fsck (8), -.BR mkefs (8), -.BR efsck (8) -.SH BUGS -.B frag -will get caught in an infinite loop in the /proc filesystem. -.SH AUTHORS -V1.0 by Werner Almesberger -.br -V1.1 by Steffen Zahn, adding directory recursion -.br -V1.2 by Rob Hooft, adding hole counts -.br -V1.3 by Steffen Zahn, ignore symlinks, -don't cross filesys borders, get filesystem block size at runtime diff --git a/disk-utils/frag.c b/disk-utils/frag.c deleted file mode 100644 index 0098e02f2..000000000 --- a/disk-utils/frag.c +++ /dev/null @@ -1,311 +0,0 @@ -/* frag.c - simple fragmentation checker - V1.0 by Werner Almesberger - V1.1 by Steffen Zahn, adding directory recursion - V1.2 by Rob Hooft, adding hole counts - V1.3 by Steffen Zahn, email: szahn%masterix@emndev.siemens.co.at - 14 Nov 93 - - ignore symlinks, - - don't cross filesys borders - - get filesystem block size at runtime - V1.4 by Michael Bischoff <mbi@mo.math.nat.tu-bs.de> to handle - indirect blocks better, but only for ext2fs - (applied by faith@cs.unc.edu, Sat Feb 4 22:06:27 1995) - - TODO: - handle hard links - */ - -#include <stdio.h> -#include <unistd.h> -#include <fcntl.h> -#include <limits.h> -#include <stdlib.h> -#include <string.h> -#include <dirent.h> -#include <sys/stat.h> -#include <sys/vfs.h> -#include <linux/fs.h> /* for FIBMAP */ - -typedef struct StackElem { - struct StackElem *backref, *next; - char name[NAME_MAX]; - char dir_seen; - char from_cmd_line; -} StackElem; - -StackElem *top = NULL; - - -void discard( void ) -{ - StackElem *se = top; - if( se == NULL ) - return ; - top = se->next; - free(se); -} - -void push( StackElem * se ) -{ - se -> next = top; - top = se; -} - -char *p2s( StackElem *se, char *path ) -{ - char *s; - if( se->backref!=NULL ) { - path = p2s( se->backref, path ); - if( path[-1]!='/' ) - *path++ = '/'; - } - s = se->name; - while( *s ) - *path++ = *s++; - return path; -} - -char *path2str( StackElem *se, char *path ) -{ - *(p2s( se, path ))=0; - return path; -} - -void *xmalloc( size_t size ) -{ - void *p; - if( (p=malloc(size))==NULL ) { - fprintf(stderr,"\nvirtual memory exhausted.\n"); - exit(1); - } - return p; -} - -int main(int argc,char **argv) -{ - int fd,last_phys_block, - fragments_in_file, blocks_in_file, - blocks,current_phys_block, - this_fragment, largest_fragment, i; - long sum_blocks=0, sum_frag_blocks=0, sum_files=0, sum_frag_files=0; - long num_hole=0, sum_hole=0, hole; - struct stat st; - struct statfs stfs; - StackElem *se, *se1; - char path[PATH_MAX], pathlink[PATH_MAX], *p; - DIR *dir; - struct dirent *de; - char silent_flag=0; - dev_t local_fs; - int block_size; - - if (argc < 2) - { - fprintf(stderr,"usage: %s [-s [-s]] filename ...\n",argv[0]); - exit(1); - } - argc--; argv++; - while (argc>0) - { - p = *argv; - if( *p=='-' ) - while( *++p ) - switch( *p ) - { - case 's': - silent_flag++; /* may be 1 or 2 */ - break; - default: - fprintf(stderr,"\nunknown flag %c\n", *p ); - exit(1); - } - else - { - se = xmalloc( sizeof(StackElem) ); - se->backref=NULL; se->dir_seen=0; se->from_cmd_line=1; - strcpy( se->name, p ); - push(se); - } - argc--; argv++; - } - while ( top != NULL) - { - se = top; - if( se->dir_seen ) - discard(); - else - { - path2str( se, path ); - if( readlink( path, pathlink, sizeof(pathlink) )>=0 ) - { /* ignore symlinks */ - if(silent_flag<1) - { - printf("symlink %s\n", path ); - } - discard(); - } - else if( stat( path,&st) < 0) - { - perror( path ); - discard(); - } - else if( !se->from_cmd_line && (local_fs!=st.st_dev) ) - { /* do not cross filesystem borders */ - if(silent_flag<2) - { - printf("different filesystem %s\n", path ); - } - discard(); - } - else - { - if( se->from_cmd_line ) - { - local_fs = st.st_dev; - if ( statfs( path, &stfs )<0 ) - { - perror( path ); - block_size = 1024; - } - else - block_size = stfs.f_bsize; - } - if( S_ISREG(st.st_mode)) /* regular file */ - { - if ( (fd = open( path ,O_RDONLY)) < 0 ) - { - perror( path ); - discard(); - } - else - { - last_phys_block = -1; - fragments_in_file = 0; - hole = 0; this_fragment=0; - largest_fragment=0; - blocks_in_file = (st.st_size+block_size-1)/block_size; - for (blocks = 0; blocks < blocks_in_file; blocks++) - { - current_phys_block = blocks; - if (ioctl(fd,FIBMAP,¤t_phys_block) < 0) - { - perror(path); - break; - } - if (current_phys_block) { /* no hole here */ - int indirect; - /* indirect is the number of indirection */ - /* blocks which must be skipped */ - indirect = 0; - /* every 256 blocks there is an indirect block, - the first of these is before block 12 */ - if (blocks >= 12 && (blocks-12) % 256 == 0) - ++indirect; - /* there is a block pointing to the indirect - blocks every 64K blocks */ - if (blocks >= 256+12 && (blocks-256-12) % 65536 == 0) - ++indirect; /* 2nd indirect block */ - /* there is a single triple indirect block */ - if (blocks == 65536 + 256 + 12) - ++indirect; - if (last_phys_block == current_phys_block-1-indirect) - this_fragment++; - else { /* start of first or new fragment */ - if( largest_fragment<this_fragment ) - largest_fragment=this_fragment; - this_fragment=1; - fragments_in_file++; - } - last_phys_block = current_phys_block; - } - else - { - hole++; - } - } - if( largest_fragment<this_fragment ) - largest_fragment=this_fragment; - blocks_in_file-=hole; - /* number of allocated blocks in file */ - if( !silent_flag ) - { - if( fragments_in_file < 2 - || blocks_in_file < 2 ) - i = 0; /* fragmentation 0 % */ - else - i = (fragments_in_file - 1) * 100 / - (blocks_in_file-1); - /* maximum fragmentation 100% - means every block is an fragment */ - printf(" %3d%% %s (%d block(s), %d fragment(s), largest %d", - i, path, blocks_in_file, - fragments_in_file,largest_fragment); - if (hole) - { - printf(", %d hole(s))\n",hole); - } - else - { - printf(")\n"); - } - } - sum_blocks+=blocks_in_file; - if (hole) - num_hole++; - sum_hole+=hole; - sum_files++; - if( fragments_in_file>1 ) - { - sum_frag_blocks+=blocks_in_file-largest_fragment; - sum_frag_files++; - } - discard(); - close(fd); - } - } - else if( S_ISDIR( st.st_mode ) ) /* push dir contents */ - { - if( (dir=opendir( path ))==NULL ) - { - perror(path); - discard(); - } - else - { - if( silent_flag<2 ) - printf("reading %s\n", path); - while( (de=readdir(dir))!=NULL ) - { - if( (strcmp(de->d_name,".")!=0) - && (strcmp(de->d_name,"..")!=0) ) - { - se1 = xmalloc( sizeof(StackElem) ); - se1->backref=se; se1->dir_seen=0; - se1->from_cmd_line=0; - strcpy( se1->name, de->d_name ); - push(se1); - } - } - closedir( dir ); - se->dir_seen=1; - } - } - else /* if( S_ISREG(st.st_mode)) */ - discard(); - } - } /* if( se->dir_seen ) */ - } /* while ( top != NULL) */ - if (sum_files>1) - { - printf("\nsummary:\n"); - printf(" %3ld%% file fragmentation (%ld of %ld files contain fragments)\n", - sum_files<1 ? 0L : sum_frag_files*100/sum_files, - sum_frag_files, sum_files); - printf(" %3ld%% block fragmentation (%ld of %ld blocks are in fragments)\n", - sum_blocks<1 ? 0L : sum_frag_blocks*100/sum_blocks, - sum_frag_blocks, sum_blocks); - if (num_hole>1) - printf(" %ld files contain %ld blocks in holes\n", - num_hole,sum_hole); - } - exit(0); -} diff --git a/disk-utils/fsck.minix.c b/disk-utils/fsck.minix.c index ae1d7b1a8..ba64bf34f 100644 --- a/disk-utils/fsck.minix.c +++ b/disk-utils/fsck.minix.c @@ -317,7 +317,7 @@ int check_zone_nr(unsigned short * nr, int * corrected) return 0; } - +#ifdef HAVE_MINIX2 int check_zone_nr2 (unsigned int *nr, int *corrected) { if (!*nr) @@ -336,6 +336,7 @@ int check_zone_nr2 (unsigned int *nr, int *corrected) } return 0; } +#endif /* * read-block reads block nr into the buffer at addr. @@ -627,11 +628,12 @@ struct minix_inode * get_inode(unsigned int nr) nr); print_current_name(); printf("'\n"); - if (repair) + if (repair) { if (ask("Mark in use",1)) mark_inode(nr); - else + } else { errors_uncorrected = 1; + } } if (S_ISDIR(inode->i_mode)) directory++; @@ -762,7 +764,7 @@ static int add_zone(unsigned short * znr, int * corrected) return block; } - +#ifdef HAVE_MINIX2 static int add_zone2 (unsigned int *znr, int *corrected) { int result; @@ -795,6 +797,7 @@ static int add_zone2 (unsigned int *znr, int *corrected) zone_count[block]--; return block; } +#endif static void add_zone_ind(unsigned short * znr, int * corrected) { @@ -812,7 +815,9 @@ static void add_zone_ind(unsigned short * znr, int * corrected) write_block(block, blk); } -static void add_zone_ind2 (unsigned int *znr, int *corrected) +#ifdef HAVE_MINIX2 +static void +add_zone_ind2 (unsigned int *znr, int *corrected) { static char blk[BLOCK_SIZE]; int i, chg_blk = 0; @@ -827,6 +832,7 @@ static void add_zone_ind2 (unsigned int *znr, int *corrected) if (chg_blk) write_block (block, blk); } +#endif static void add_zone_dind(unsigned short * znr, int * corrected) { @@ -844,6 +850,7 @@ static void add_zone_dind(unsigned short * znr, int * corrected) write_block(block, blk); } +#ifdef HAVE_MINIX2 static void add_zone_dind2 (unsigned int *znr, int *corrected) { @@ -877,6 +884,7 @@ add_zone_tind2 (unsigned int *znr, int *corrected) if (blk_chg) write_block (block, blk); } +#endif void check_zones(unsigned int i) { @@ -945,18 +953,20 @@ void check_file(struct minix_inode * dir, unsigned int offset) name_depth++; inode = get_inode(ino); name_depth--; - if (!offset) + if (!offset) { if (!inode || strcmp(".",name)) { print_current_name(); printf(": bad directory: '.' isn't first\n"); errors_uncorrected = 1; } else return; - if (offset == dirsize) + } + if (offset == dirsize) { if (!inode || strcmp("..",name)) { print_current_name(); printf(": bad directory: '..' isn't second\n"); errors_uncorrected = 1; } else return; + } if (!inode) return; if (name_depth < MAX_DEPTH) @@ -1230,12 +1240,12 @@ int main(int argc, char ** argv) #endif while (argc-- > 1) { argv++; - if (argv[0][0] != '-') + if (argv[0][0] != '-') { if (device_name) usage(); else device_name = argv[0]; - else while (*++argv[0]) + } else while (*++argv[0]) switch (argv[0][0]) { case 'l': list=1; break; case 'a': automatic=1; repair=1; break; diff --git a/disk-utils/llseek.c b/disk-utils/llseek.c deleted file mode 100644 index a9cd5a3ac..000000000 --- a/disk-utils/llseek.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * llseek.c -- stub calling the llseek system call - * - * Copyright (C) 1994 Remy Card. This file may be redistributed - * under the terms of the GNU Public License. - */ - -#include <sys/types.h> - -#include <errno.h> -#include <unistd.h> - -#if defined(__GNUC__) || defined(HAS_LONG_LONG) -typedef long long ext2_loff_t; -#else -typedef long ext2_loff_t; -#endif - -extern ext2_loff_t ext2_llseek (unsigned int, ext2_loff_t, unsigned int); - -#ifdef __linux__ - -#ifdef HAVE_LLSEEK -#include <syscall.h> - -#else /* HAVE_LLSEEK */ - -#ifdef __alpha__ - -#define my_llseek lseek - -#else -#include <linux/unistd.h> /* for __NR__llseek */ - -static int _llseek (unsigned int, unsigned long, - unsigned long, ext2_loff_t *, unsigned int); - -static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high, - unsigned long, offset_low,ext2_loff_t *,result, - unsigned int, origin) - -static ext2_loff_t my_llseek (unsigned int fd, ext2_loff_t offset, - unsigned int origin) -{ - ext2_loff_t result; - int retval; - - retval = _llseek (fd, ((unsigned long long) offset) >> 32, - ((unsigned long long) offset) & 0xffffffff, - &result, origin); - return (retval == -1 ? (ext2_loff_t) retval : result); -} - -#endif /* __alpha__ */ - -#endif /* HAVE_LLSEEK */ - -ext2_loff_t ext2_llseek (unsigned int fd, ext2_loff_t offset, - unsigned int origin) -{ - ext2_loff_t result; - static int do_compat = 0; - - if (!do_compat) { - result = my_llseek (fd, offset, origin); - if (!(result == -1 && errno == ENOSYS)) - return result; - - /* - * Just in case this code runs on top of an old kernel - * which does not support the llseek system call - */ - do_compat = 1; - /* - * Now try ordinary lseek. - */ - } - - 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 */ - -ext2_loff_t ext2_llseek (unsigned int fd, ext2_loff_t offset, - unsigned int origin) -{ - if ((sizeof(off_t) < sizeof(ext2_loff_t)) && - (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) { - errno = EINVAL; - return -1; - } - return lseek (fd, (off_t) offset, origin); -} - -#endif /* linux */ - - diff --git a/disk-utils/mkfs.8 b/disk-utils/mkfs.8 index 57132a483..2dd616484 100644 --- a/disk-utils/mkfs.8 +++ b/disk-utils/mkfs.8 @@ -55,13 +55,8 @@ This is really only useful for testing. .TP .BI -t \ fstype Specifies the type of file system to be built. -If not specified, the type is deduced by searching for -.I filesys -in -.I /etc/fstab -and using the corresponding entry. -If the type can not be deduced, the default file system type -(currently minix) is used. +If not specified, the default file system type +(currently ext2) is used. .TP .B fs-options File system-specific options to be passed to the real file diff --git a/disk-utils/mkfs.minix.c b/disk-utils/mkfs.minix.c index db7aefaea..c34da5326 100644 --- a/disk-utils/mkfs.minix.c +++ b/disk-utils/mkfs.minix.c @@ -624,7 +624,7 @@ int main(int argc, char ** argv) #endif while (argc-- > 1) { argv++; - if (argv[0][0] != '-') + if (argv[0][0] != '-') { if (device_name) { BLOCKS = strtol(argv[0],&tmp,0); if (*tmp) { @@ -634,7 +634,7 @@ int main(int argc, char ** argv) } } else device_name = argv[0]; - else { + } else { if(argv[0][1] == 'l') { listfile = argv[1]; argv++; diff --git a/disk-utils/mkswap.8 b/disk-utils/mkswap.8 index 1e14167b8..2df606c57 100644 --- a/disk-utils/mkswap.8 +++ b/disk-utils/mkswap.8 @@ -1,83 +1,93 @@ -.\" 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 -.\" Modified with suggestions from Linus, Mon Feb 1 21:40:49 1993 -.\" Modified with patches from Kai, Wed Jun 22 21:54:56 1994 -.\" Patches from jaggy@purplet.demon.co.uk (Mike Jagdis), Wed Feb 8 1995 -.\" Added comments from Nick Holloway, Sat Feb 11 1995, faith@cs.unc.edu -.\" " -.TH MKSWAP 8 "February 1995" "Linux 1.0" "Linux Programmer's Manual" +.\" Rewritten for 2.1.117, aeb, 981010. +.\" +.TH MKSWAP 8 "1 December 1998" "Linux 2.1.117" "Linux Programmer's Manual" .SH NAME mkswap \- set up a Linux swap area .SH SYNOPSIS -.B "mkswap [ \-c ]" -.IB device " [" size-in-blocks "]" +.BI "mkswap [\-c] [\-v" N "] [\-f] " device " [" size "]" .SH DESCRIPTION .B mkswap sets up a Linux swap area on a device or in a file. +(After creating the swap area, you need the +.B swapon +command to start using it. Usually swap areas are listed in +.I /etc/fstab +so that they can be taken into use at boot time by a +.B swapon -a +command in some boot script.) + The .I device -is usually of the following form: - -.nf -.RS -/dev/hda[1-8] -/dev/hdb[1-8] -/dev/sda[1-8] -/dev/sdb[1-8] -.RE -.fi +argument will usually be a disk partition (something like +.I /dev/hda4 +or +.IR /dev/sdb7 ) +but can also be a file. +The Linux kernel does not look at partition Id's, but +many installation scripts will assume that partitions +of hex type 82 (LINUX_SWAP) are meant to be swap partitions. The -.I size-in-blocks -parameter is the desired size of the file system, in blocks. This -information is determined automatically by +.I size +parameter is superfluous but retained for backwards compatibility. +(It specifies the desired size of the swap area in 1024-byte blocks. .B mkswap -if it is omitted. Block counts are rounded down so that the total -size is an integer multiple of the machine's page size. Only block -counts in the range MINCOUNT..MAXCOUNT are allowed. If the block count -exceeds the MAXCOUNT, it is truncated to that value and a warning -message is issued. +will use the entire partition or file if it is omitted.) -The MINCOUNT and MAXCOUNT values for a swap area are: +Linux knows about two styles of swap areas, old style and new style. +The last 10 bytes of the first page of the swap area distinguishes +them: old style has `SWAP_SPACE', new style has `SWAPSPACE2' as +signature. -.RS -MINCOUNT = 10 * PAGE_SIZE / 1024 -.br -MAXCOUNT = (PAGE_SIZE - 10) * 8 * PAGE_SIZE / 1024 -.RE +In the old style, the rest of this first page was a bit map, +with a 1 bit for each usable page of the swap area. +Since the first page holds this bit map, the first bit is 0. +Also, the last 10 bytes hold the signature. So, if the page +size is S, an old style swap area can describe at most +8*(S-10)-1 pages used for swapping. +With S=4096 (as on i386), the useful area is at most 133890048 bytes +(almost 128 MB if you believe in 1 MB=2^20 bytes), and the rest is wasted. +On an alpha and sparc64, with S=8192, the useful area is at most +535560992 bytes (almost 512 MB with the same proviso). -For example, on a machine with 4kB pages (e.g., x86), we get: +The old setup wastes most of this bitmap page, because zero bits +denote bad blocks or blocks past the end of the swap space, +and a simple integer suffices to indicate the size of the swap space, +while the bad blocks, if any, can simply be listed. Nobody wants +to use a swap space with hundreds of bad blocks. (I would not even +use a swap space with 1 bad block.) +In the new style swap area this is precisely what is done. +The maximum useful size of a swap area is now (2^31 - 2*S) bytes, +roughly 2 GB. -.RS -MINCOUNT = 10 * 4096 / 1024 = 40 -.br -MAXCOUNT = (4096 - 10) * 8 * 4096 / 1024 = 130752 -.RE +Note that before 2.1.117 the kernel allocated one byte for each page, +while it now allocates two bytes, so that taking a swap area of 2 GB +in use might require 2 MB of kernel memory. -As each block is 1kB large, the swap area in this example could have a -size that is anywhere in the range from 40kB up to 127.6875MB. +Presently, Linux allows 8 swap areas. The areas in use can be seen +in the file +.I /proc/swaps +(since 2.1.25). -If you don't know the page size that your machine uses, you may be -able to look it up with "cat /proc/cpuinfo". +.B mkswap +refuses areas smaller than 10 pages. -The reason for the limit on MAXCOUNT is that a single page is used to -hold the swap bitmap at the start of the swap area, where each bit -represents a single page. The reason for the -10, is that the -signature is "SWAP-SPACE" -- 10 characters. +If you don't know the page size that your machine uses, you may be +able to look it up with "cat /proc/cpuinfo" (or you may not - +the contents of this file depend on architecture and kernel version). To setup a swap file, it is necessary to create that file before running -.B mkswap . -A sequence of commands similar to the following is reasonable for this -purpose: +.B mkswap , +e.g. using a command like .nf .RS -# dd if=/dev/zero of=swapfile bs=1024 count=8192 -# mkswap swapfile 8192 -# sync -# swapon swapfile +# dd if=/dev/zero of=swapfile bs=1024 count=65536 .RE .fi @@ -88,19 +98,34 @@ to create the file is not acceptable). .SH OPTIONS .TP .B \-c -Check the device for bad blocks before creating the file system. If any -are found, the count is printed. This option is meant to be used for swap -partitions -.BR only , -and should -.B not -be used for regular files! To make sure that regular files do not contain -bad blocks, the partition that contains the regular file should have been -created with -.BR "mkfs -c" . +Check the device (if it is a block device) for bad blocks +before creating the swap area. +If any are found, the count is printed. +.TP +.B \-f +On SPARC, force creation of the swap area. +Without this option +.B mkswap +will refuse to create a v0 swap on a device with a valid SPARC superblock, +as that probably means one is going to erase the partition table. +.TP +.B \-v0 +Create an old style swap area. +.TP +.B \-v1 +Create a new style swap area. + +.LP +If no \-v option is given, +.B mkswap +will default to old style if the size of the swap area does not +exceed the maximum size of an old style swap area, and also if +the current kernel is older than 2.1.117 (and also if PAGE_SIZE +is less than 2048). +The new style header does not touch the first block, so may be +preferable (also if the swap area is small), in case you have +a boot loader or disk label there. + .SH "SEE ALSO" -.BR fsck (8), -.BR mkfs (8), -.BR fdisk (8) -.SH AUTHOR -Linus Torvalds (torvalds@cs.helsinki.fi) +.BR fdisk (8), +.BR swapon (8) diff --git a/disk-utils/mkswap.c b/disk-utils/mkswap.c index 49447f2af..b3402366c 100644 --- a/disk-utils/mkswap.c +++ b/disk-utils/mkswap.c @@ -8,15 +8,21 @@ /* * 20.12.91 - time began. Got VM working yesterday by doing this by hand. * - * Usuage: mkswap [-c] device [size-in-blocks] + * Usuage: mkswap [-c] [-vN] [-f] device [size-in-blocks] * - * -c for readablility checking (use it unless you are SURE!) + * -c for readability checking. (Use it unless you are SURE!) + * -vN for swap areas version N. (Only N=0,1 known today.) + * -f for forcing swap creation even if it would smash partition table. * - * The device may be a block device or a image of one, but this isn't + * The device may be a block device or an image of one, but this isn't * enforced (but it's not much fun on a character device :-). * * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995. + * + * Version 1 swap area code (for kernel 2.1.117), aeb, 981010. + * + * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb. */ #include <stdio.h> @@ -24,26 +30,85 @@ #include <string.h> #include <fcntl.h> #include <stdlib.h> -#include <sys/ioctl.h> +#include <sys/ioctl.h> /* for _IO */ +#include <sys/utsname.h> #include <sys/stat.h> -#include <asm/page.h> +#include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */ +#ifndef _IO +/* pre-1.3.45 */ #define BLKGETSIZE 0x1260 - -#ifndef __linux__ -# define volatile +#else +/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */ +#define BLKGETSIZE _IO(0x12,96) #endif -#define TEST_BUFFER_PAGES 8 - static char * program_name = "mkswap"; static char * device_name = NULL; static int DEV = -1; static long PAGES = 0; static int check = 0; static int badpages = 0; +static int version = -1; + +#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) + +static int +linux_version_code(void) { + struct utsname my_utsname; + int p, q, r; + + if (uname(&my_utsname) == 0) { + p = atoi(strtok(my_utsname.release, ".")); + q = atoi(strtok(NULL, ".")); + r = atoi(strtok(NULL, ".")); + return MAKE_VERSION(p,q,r); + } + return 0; +} + +/* + * The definition of the union swap_header uses the constant PAGE_SIZE. + * Unfortunately, on some architectures this depends on the hardware model, + * and can only be found at run time -- we use getpagesize(). + */ + +static int pagesize; +static int *signature_page; -static int signature_page[PAGE_SIZE/sizeof(int)]; +struct swap_header_v1 { + char bootbits[1024]; /* Space for disklabel etc. */ + unsigned int version; + unsigned int last_page; + unsigned int nr_badpages; + unsigned int padding[125]; + unsigned int badpages[1]; +} *p; + +static void +init_signature_page() { + pagesize = getpagesize(); + +#ifdef PAGE_SIZE + if (pagesize != PAGE_SIZE) + fprintf(stderr, "Assuming pages of size %d\n", pagesize); +#endif + signature_page = (int *) malloc(pagesize); + memset(signature_page,0,pagesize); + p = (struct swap_header_v1 *) signature_page; +} + +static void +write_signature(char *sig) { + char *sp = (char *) signature_page; + + strncpy(sp+pagesize-10, sig, 10); +} + +#define V0_MAX_PAGES (8 * (pagesize - 10)) +#define V1_MAX_PAGES ((0x7fffffff / pagesize) - 1) + +#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int)) static void bit_set (unsigned int *addr, unsigned int nr) { @@ -66,41 +131,56 @@ static int bit_test_and_clear (unsigned int *addr, unsigned int nr) return (r & m) != 0; } -/* - * Volatile to let gcc know that this doesn't return. When trying - * to compile this under minix, volatile gives a warning, as - * exit() isn't defined as volatile under minix. - */ -volatile void fatal_error(const char * fmt_string) +void fatal_error(const char * fmt_string) { fprintf(stderr,fmt_string,program_name,device_name); exit(1); } -#define usage() fatal_error("Usage: %s [-c] /dev/name [blocks]\n") +#define usage() fatal_error("Usage: %s [-c] [-v0|-v1] /dev/name [blocks]\n") #define die(str) fatal_error("%s: " str "\n") -void check_blocks(void) -{ +void +page_ok(int page) { + if (version==0) + bit_set(signature_page, page); +} + +void +page_bad(int page) { + if (version == 0) + bit_test_and_clear(signature_page, page); + else { + if (badpages == MAX_BADPAGES) + die("too many bad pages"); + p->badpages[badpages] = page; + } + badpages++; +} + +void +check_blocks(void) { unsigned int current_page; int do_seek = 1; - static char buffer[PAGE_SIZE]; + char *buffer; + buffer = malloc(pagesize); + if (!buffer) + die("Out of memory"); current_page = 0; while (current_page < PAGES) { if (!check) { - bit_set(signature_page,current_page++); + page_ok(current_page++); continue; } - if (do_seek && lseek(DEV,current_page*PAGE_SIZE,SEEK_SET) != - current_page*PAGE_SIZE) + if (do_seek && lseek(DEV,current_page*pagesize,SEEK_SET) != + current_page*pagesize) die("seek failed in check_blocks"); - if ((do_seek = (PAGE_SIZE != read(DEV, buffer, PAGE_SIZE)))) { - bit_test_and_clear(signature_page,current_page++); - badpages++; + if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) { + page_bad(current_page++); continue; } - bit_set(signature_page,current_page++); + page_ok(current_page++); } if (badpages) printf("%d bad page%s\n",badpages,(badpages>1)?"s":""); @@ -117,12 +197,13 @@ static long valid_offset (int fd, int offset) return 1; } -static int count_blocks (int fd) +static int +find_size (int fd) { - int high, low; + unsigned int high, low; low = 0; - for (high = 1; valid_offset (fd, high); high *= 2) + for (high = 1; high > 0 && valid_offset (fd, high); high *= 2) low = high; while (low < high - 1) { @@ -133,26 +214,27 @@ static int count_blocks (int fd) else high = mid; } - valid_offset (fd, 0); return (low + 1); } -static int get_size(const char *file) +/* return size in pages, to avoid integer overflow */ +static int +get_size(const char *file) { int fd; int size; - fd = open(file, O_RDWR); + fd = open(file, O_RDONLY); if (fd < 0) { perror(file); exit(1); } if (ioctl(fd, BLKGETSIZE, &size) >= 0) { - close(fd); - return (size * 512); + int sectors_per_page = pagesize/512; + size /= sectors_per_page; + } else { + size = find_size(fd) / pagesize; } - - size = count_blocks(fd); close(fd); return size; } @@ -161,28 +243,41 @@ int main(int argc, char ** argv) { char * tmp; struct stat statbuf; + int maxpages; int goodpages; + int offset; + int force = 0; - memset(signature_page,0,PAGE_SIZE); if (argc && *argv) program_name = *argv; + + init_signature_page(); /* get pagesize */ + while (argc-- > 1) { argv++; - if (argv[0][0] != '-') + if (argv[0][0] != '-') { if (device_name) { - PAGES = strtol(argv[0],&tmp,0)>>(PAGE_SHIFT-10); + int blocks_per_page = pagesize/1024; + PAGES = strtol(argv[0],&tmp,0)/blocks_per_page; if (*tmp) usage(); } else device_name = argv[0]; - else while (*++argv[0]) - switch (argv[0][0]) { - case 'c': check=1; break; - default: usage(); + } else { + switch (argv[0][1]) { + case 'c': + check=1; + break; + case 'f': + force=1; + break; + case 'v': + version=atoi(argv[0]+2); + break; + default: + usage(); } - } - if (device_name && !PAGES) { - PAGES = get_size(device_name) / PAGE_SIZE; + } } if (!device_name) { fprintf(stderr, @@ -190,17 +285,38 @@ int main(int argc, char ** argv) program_name); usage(); } + if (!PAGES) { + PAGES = get_size(device_name); + } + + if (version == -1) { + if (PAGES <= V0_MAX_PAGES) + version = 0; + else if (linux_version_code() < MAKE_VERSION(2,1,117)) + version = 0; + else if (pagesize < 2048) + version = 0; + else + version = 1; + } + if (version != 0 && version != 1) { + fprintf(stderr, "%s: error: unknown version %d\n", + program_name, version); + usage(); + } if (PAGES < 10) { fprintf(stderr, "%s: error: swap area needs to be at least %ldkB\n", - program_name, (long)(10 * PAGE_SIZE / 1024)); + program_name, (long)(10 * pagesize / 1024)); usage(); } - if (PAGES > 8 * (PAGE_SIZE - 10)) { - PAGES = 8 * (PAGE_SIZE - 10); + maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES); + if (PAGES > maxpages) { + PAGES = maxpages; fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n", - program_name, PAGES * PAGE_SIZE / 1024); + program_name, PAGES * pagesize / 1024); } + DEV = open(device_name,O_RDWR); if (DEV < 0 || fstat(DEV, &statbuf) < 0) { perror(device_name); @@ -210,19 +326,56 @@ int main(int argc, char ** argv) check=0; else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) die("Will not try to make swapdevice on '%s'"); - check_blocks(); - if (!bit_test_and_clear(signature_page,0)) + +#ifdef __sparc__ + if (!force && version == 0) { + /* Don't overwrite partition table unless forced */ + unsigned char *buffer = (unsigned char *)signature_page; + unsigned short *q, sum; + + if (read(DEV, buffer, 512) != 512) + die("fatal: first page unreadable"); + if (buffer[508] == 0xDA && buffer[509] == 0xBE) { + q = (unsigned short *)(buffer + 510); + for (sum = 0; q >= (unsigned short *) buffer;) + sum ^= *q--; + if (!sum) { + fprintf(stderr, "\ +%s: Device '%s' contains a valid Sun disklabel.\n\ +This probably means creating v0 swap would destroy your partition table\n\ +No swap created. If you really want to create swap v0 on that device, use\n\ +the -f option to force it.\n", + program_name, device_name); + exit(1); + } + } + } +#endif + + if (version == 0 || check) + check_blocks(); + if (version == 0 && !bit_test_and_clear(signature_page,0)) die("fatal: first page unreadable"); + if (version == 1) { + p->version = version; + p->last_page = PAGES-1; + p->nr_badpages = badpages; + } + goodpages = PAGES - badpages - 1; if (goodpages <= 0) die("Unable to set up swap-space: unreadable"); - printf("Setting up swapspace, size = %ld bytes\n", - (long)(goodpages*PAGE_SIZE)); - strncpy((char*)signature_page+PAGE_SIZE-10, "SWAP-SPACE", 10); - if (lseek(DEV, 0, SEEK_SET)) + printf("Setting up swapspace version %d, size = %ld bytes\n", + version, (long)(goodpages*pagesize)); + write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2"); + + offset = ((version == 0) ? 0 : 1024); + if (lseek(DEV, offset, SEEK_SET) != offset) die("unable to rewind swap-device"); - if (PAGE_SIZE != write(DEV, signature_page, PAGE_SIZE)) + if (write(DEV,(char*)signature_page+offset, pagesize-offset) + != pagesize-offset) die("unable to write signature page"); + /* * A subsequent swapon() will fail if the signature * is not actually on disk. (This is a kernel bug.) diff --git a/disk-utils/setfdprm.c b/disk-utils/setfdprm.c index fee55300d..62234f3ac 100644 --- a/disk-utils/setfdprm.c +++ b/disk-utils/setfdprm.c @@ -103,7 +103,7 @@ gap rate spec1 fmt_gap\n",name); exit(1); } -void +int main(int argc,char **argv) { int fd; @@ -153,4 +153,5 @@ main(int argc,char **argv) else find_params(cmd,fd,argv[2]); /* not reached */ + return 0; } diff --git a/disk-utils/sfdisk.8 b/disk-utils/sfdisk.8 deleted file mode 100644 index 33f10dabd..000000000 --- a/disk-utils/sfdisk.8 +++ /dev/null @@ -1,497 +0,0 @@ -.\" Copyright 1995 Andries E. Brouwer (aeb@cwi.nl) -.\" May be distributed under the GNU General Public License -.\" The `DOS 6.x Warning' was taken from the old fdisk.8, which says -.\" -- Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu) -.\" -- May be distributed under the GNU General Public License -.\" The `DRDOS Warning' was taken from a net post by Stephen Tweedie. -.\" -.TH SFDISK 8 "1 September 1995" "Linux 1.3.23" "Linux Programmer's Manual" -.SH NAME -sfdisk \- Partition table manipulator for Linux -.SH SYNOPSIS -.BR sfdisk " [options] device" -.br -.BR "sfdisk \-s " [partition] -.SH DESCRIPTION -.B sfdisk -has four (main) uses: list the size of a partition, list the partitions -on a device, check the partitions on a device, and - very dangerous - -repartition a device. - -.SS "List Sizes" -.BI "sfdisk \-s " partition -gives the size of -.I partition -in blocks. This may be useful in connection with programs like -.B mkswap -or so. Here -.I partition -is usually something like -.I /dev/hda1 -or -.IR /dev/sdb12 , -but may also be an entire disk, like -.IR /dev/xda . -.br -.RS -.nf -.if t .ft CW -% sfdisk \-s /dev/hda9 -81599 -% -.if t .ft R -.fi -.RE -If the partition argument is omitted, -.B sfdisk -will list the sizes of all disks, and the total: -.br -.RS -.nf -.if t .ft CW -% sfdisk \-s -/dev/hda: 208896 -/dev/hdb: 1025136 -/dev/hdc: 1031063 -/dev/sda: 8877895 -/dev/sdb: 1758927 -total: 12901917 blocks -% -.if t .ft R -.fi -.RE - -.SS "List Partitions" -The second type of invocation: -.BI "sfdisk \-l " "[options] device" -will list the partitions on this device. -If the device argument is omitted, the partitions on all hard disks -are listed. -.br -.nf -.if t .ft CW -% sfdisk \-l /dev/hdc - -Disk /dev/hdc: 16 heads, 63 sectors, 2045 cylinders -Units = cylinders of 516096 bytes, blocks of 1024 bytes, counting from 0 - - Device Boot Start End #cyls #blocks Id System -/dev/hdc1 0+ 406 407\- 205096+ 83 Linux native -/dev/hdc2 407 813 407 205128 83 Linux native -/dev/hdc3 814 2044 1231 620424 83 Linux native -/dev/hdc4 0 \- 0 0 0 Empty -% -.if t .ft R -.fi -The trailing \- and + signs indicate that rounding has taken place, -and that the actual value is slightly less (more). -To see the exact values, ask for a listing with sectors as unit. - -.SS "Check partitions" -The third type of invocation: -.BI "sfdisk \-V " device -will apply various consistency checks to the partition tables on -.IR device . -It prints `OK' or complains. The \-V option can be used together -with \-l. In a shell script one might use -.BI "sfdisk \-V \-q " device -which only returns a status. - -.SS "Create partitions" -The fourth type of invocation: -.BI "sfdisk " device -will cause -.B sfdisk -to read the specification for the desired partitioning of -.I device -from its standard input, and then to change the partition tables -on that disk. Thus, it is possible to use -.B sfdisk -from a shell script. When -.B sfdisk -determines that its standard input is a terminal, it will be -conversational; otherwise it will abort on any error. -.LP -BE EXTREMELY CAREFUL - ONE TYPING MISTAKE AND ALL YOUR DATA IS LOST -.LP -As a precaution, one can save the sectors changed by -.BR sfdisk : -.RS -.nf -.if t .ft CW -% sfdisk /dev/hdd \-O hdd-partition-sectors.save -% -.if t .ft R -.fi -.RE -.LP -Then, if you discover that you did something stupid before anything -else has been written to disk, it may be possible to recover -the old situation with -.RS -.nf -.if t .ft CW -% sfdisk /dev/hdd \-I hdd-partition-sectors.save -% -.if t .ft R -.fi -.RE - -There are many options. - -.SH OPTIONS -.TP -.BR \-v " or " \-\-version -Print version number of -.B sfdisk -and exit immediately. -.TP -.BR \-? " or " \-\-help -Print a usage message and exit immediately. -.TP -.BR \-T " or " \-\-list-types -Print the recognized types (system Id's). -.TP -.BR \-s " or " \-\-show\-size -List the size of a partition. -.TP -.BR \-g " or " \-\-show\-geometry -List the kernel's idea of the geometry of the indicated disk(s). -.TP -.BR \-l " or " \-\-list -List the partitions of a device. -.TP -.BR \-d -Dump the partitions of a device in a format useful as input -to sfdisk. For example, -.br -.nf -.if t .ft CW - % sfdisk -d /dev/hda > hda.out - % sfdisk /dev/hda < hda.out -.if t .ft R -.fi -will correct the bad last extended partition that the OS/2 -fdisk creates. -.TP -.BR \-V " or " \-\-verify -Test whether partitions seem correct. (See above.) -.TP -.BR \-i " or " \-\-increment -Number cylinders etc. starting from 1 instead of 0. -.TP -.BI \-N " number" -Change only the single partition indicated. For example: -.br -.nf -.if t .ft CW - % sfdisk /dev/hdb \-N5 - ,,,* - % -.if t .ft R -.fi -will make the fifth partition on /dev/hdb bootable (`active') -and change nothing else. (Probably this fifth partition -is called /dev/hdb5, but you are free to call it something else, -like `/my_equipment/disks/2/5' or so). -.TP -.BI \-A " number" -Make the indicated partition(s) active, and all others inactive. -.TP -.BI \-c " or " \-\-id " number [Id]" -If no Id argument given: print the partition Id of the indicated -partition. If an Id argument is present: change the type (Id) of -the indicated partition to the given value. -This option has the two very long forms \-\-print\-id and \-\-change\-id. -For example: -.br -.nf -.if t .ft CW - % sfdisk --print-id /dev/hdb 5 - 6 - % sfdisk --change-id /dev/hdb 5 83 - OK -.if t .ft R -.fi -first reports that /dev/hdb5 has Id 6, and then changes that into 83. -.TP -.BR \-uS " or " \-uB " or " \-uC " or " \-uM -Accept or report in units of sectors (blocks, cylinders, megabytes, -respectively). The default is cylinders, at least when the geometry -is known. -.TP -.BR \-x " or " \-\-show\-extended -Also list non-primary extended partitions on output, -and expect descriptors for them on input. -.TP -.BI \-C " cylinders" -Specify the number of cylinders, possibly overriding what the kernel thinks. -.TP -.BI \-H " heads" -Specify the number of heads, possibly overriding what the kernel thinks. -.TP -.BI \-S " sectors" -Specify the number of sectors, possibly overriding what the kernel thinks. -.TP -.BR \-f " or " \-\-force -Do what I say, even if it is stupid. -.TP -.BR \-q " or " \-\-quiet -Suppress warning messages. -.TP -.BR \-L " or " \-\-Linux -Do not complain about things irrelevant for Linux. -.TP -.BR \-D " or " \-\-DOS -For DOS-compatibility: waste a little space. -(More precisely: if a partition cannot contain sector 0, -e.g. because that is the MBR of the device, or contains -the partition table of an extended partition, then -.B sfdisk -would make it start the next sector. However, when this -option is given it skips to the start of the next track, -wasting for example 33 sectors (in case of 34 sectors/track), -just like certain versions of DOS do.) -Certain Disk Managers and boot loaders (such as OSBS, but not -LILO or the OS/2 Boot Manager) also live in this empty space, -so maybe you want this option if you use one. -.TP -.BR \-\-IBM " or " \-\-leave\-last -Certain IBM diagnostic programs assume that they can use the -last cylinder on a disk for disk-testing purposes. If you think -you might ever run such programs, use this option to tell -.B sfdisk -that it should not allocate the last cylinder. -Sometimes the last cylinder contains a bad sector table. -.TP -.B \-n -Go through all the motions, but do not actually write to disk. -.TP -.B \-R -Only execute the BLKRRPART ioctl (to make the kernel re-read -the partition table). This can be useful for checking in advance -that the final BLKRRPART will be successful, and also when you -changed the partition table `by hand' (e.g., using dd from a backup). -If the kernel complains (`device busy for revalidation (usage = 2)') -then something still uses the device, and you still have to unmount -some file system, or say swapoff to some swap partition. -.TP -.B \-\-no\-reread -When starting a repartitioning of a disk, sfdisk checks that this disk -is not mounted, or in use as a swap device, and refuses to continue -if it is. This option suppresses the test. (On the other hand, the \-f -option would force sfdisk to continue even when this test fails.) -.TP -.BI \-O " file" -Just before writing the new partition, output the sectors -that are going to be overwritten to -.I file -(where hopefully -.I file -resides on another disk, or on a floppy). -.TP -.BI \-I " file" -After destroying your filesystems with an unfortunate -.B sfdisk -command, you would have been able to restore the old situation -if only you had preserved it using the \-O flag. - -.SH THEORY -Block 0 of a disk (the Master Boot Record) contains among -other things four partition descriptors. The partitions -described here are called -.I primary -partitions. -.LP -A partition descriptor has 6 fields: -.br -.nf -.RS -struct partition { - unsigned char bootable; /* 0 or 0x80 */ - hsc begin_hsc; - unsigned char id; - hsc end_hsc; - unsigned int starting_sector; - unsigned int nr_of_sectors; -} -.RE -.fi -.LP -The two hsc fields indicate head, sector and cylinder of the -begin and the end of the partition. Since each hsc field only -takes 3 bytes, only 24 bits are available, which does not -suffice for big disks (say > 8GB). In fact, due to the wasteful -representation (that uses a byte for the number of heads, which -is typically 16), problems already start with 0.5GB. -However Linux does not use these fields, and problems can arise -only at boot time, before Linux has been started. For more -details, see the -.B lilo -documentation. -.LP -Each partition has a type, its `Id', and if this type is 5 -.IR "" "(`" "extended partition" "')" -the starting sector of the partition -again contains 4 partition descriptors. MSDOS only uses the -first two of these: the first one an actual data partition, -and the second one again an extended partition (or empty). -In this way one gets a chain of extended partitions. -Other operating systems have slightly different conventions. -Linux also accepts type 85 as equivalent to 5 - this can be -useful if one wants to have extended partitions under Linux past -the 1024 cylinder boundary, without DOS FDISK hanging. -(If there is no good reason, you should just use 5, which is -understood by other systems.) -.LP -Partitions that are not primary or extended are called -.IR logical . -Often, one cannot boot from logical partitions (because the -process of finding them is more involved than just looking -at the MBR). -Note that of an extended partition only the Id and the start -are used. There are various conventions about what to write -in the other fields. One should not try to use extended partitions -for data storage or swap. - -.SH "INPUT FORMAT" -.B sfdisk -reads lines of the form -.br -.RS -<start> <size> <id> <bootable> <c,h,s> <c,h,s> -.RE -where each line fills one partition descriptor. -.LP -Fields are separated by whitespace, or comma or semicolon possibly -followed by whitespace; initial and trailing whitespace is ignored. -Numbers can be octal, decimal or hexadecimal, decimal is default. -When a field is absent or empty, a default value is used. -.LP -The <c,h,s> parts can (and probably should) be omitted - -.B sfdisk -computes them from <start> and <size> and the disk geometry -as given by the kernel or specified using the \-H, \-S, \-C flags. -.LP -Bootable is specified as [*|\-], with as default not-bootable. -(The value of this field is irrelevant for Linux - when Linux -runs it has been booted already - but might play a role for -certain boot loaders and for other operating systems. -For example, when there are several primary DOS partitions, -DOS assigns C: to the first among these that is bootable.) -.LP -Id is given in hex, without the 0x prefix, or is [E|S|L|X], where -L (LINUX_NATIVE (83)) is the default, S is LINUX_SWAP (82), E -is EXTENDED_PARTITION (5), and X is LINUX_EXTENDED (85). -.LP -The default value of start is the first nonassigned sector/cylinder/... -.LP -The default value of size is as much as possible (until next -partition or end-of-disk). -.LP -However, for the four partitions inside an extended partition, -the defaults are: Linux partition, Extended partition, Empty, Empty. -.LP -But when the \-N option (change a single partition only) is given, -the default for each field is its previous value. - -.SH EXAMPLE -The command -.RS -.nf -.if t .ft CW -sfdisk /dev/hdc << EOF -0,407 -,407 -; -; -EOF -.if t .ft R -.fi -.RE -will partition /dev/hdc just as indicated above. - -With the \-x option, the number of input lines must be a multiple of 4: -you have to list the two empty partitions that you never want -using two blank lines. Without the \-x option, you give one line -for the partitions inside a extended partition, instead of four, -and terminate with end-of-file (^D). -(And -.B sfdisk -will assume that your input line represents the first of four, -that the second one is extended, and the 3rd and 4th are empty.) - -.SH "DOS 6.x WARNING" - -The DOS 6.x FORMAT command looks for some information in the first -sector of the data area of the partition, and treats this information -as more reliable than the information in the partition table. DOS -FORMAT expects DOS FDISK to clear the first 512 bytes of the data area -of a partition whenever a size change occurs. DOS FORMAT will look at -this extra information even if the /U flag is given -- we consider -this a bug in DOS FORMAT and DOS FDISK. -.LP -The bottom line is that if you use sfdisk to change the size of a -DOS partition table entry, then you must also use -.B dd -to zero the first 512 bytes of that partition before using DOS FORMAT to -format the partition. For example, if you were using sfdisk to make a DOS -partition table entry for /dev/hda1, then (after exiting sfdisk 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. - -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 sfdisk program. - -.SH "DRDOS WARNINGS" - -Stephen Tweedie reported (930515): `Most reports of superblock -corruption turn out to be due to bad partitioning, with one filesystem -overrunning the start of the next and corrupting its superblock. -I have even had this problem with the supposedly-reliable DRDOS. This -was quite possibly due to DRDOS-6.0's FDISK command. Unless I created -a blank track or cylinder between the DRDOS partition and the -immediately following one, DRDOS would happily stamp all over the -start of the next partition. Mind you, as long as I keep a little -free disk space after any DRDOS partition, I don't have any other -problems with the two coexisting on the one drive.' - -A. V. Le Blanc writes in README.esfdisk: `Dr. DOS 5.0 and 6.0 has been -reported to have problems cooperating with Linux, and with this version -of efdisk in particular. This efdisk sets the system type -to hexadecimal 81. Dr. DOS seems to confuse -this with hexadecimal 1, a DOS code. If you use Dr. DOS, use the -efdisk command 't' to change the system code of any Linux partitions -to some number less than hexadecimal 80; I suggest 41 and 42 for -the moment.' - -A. V. Le Blanc writes in his README.fdisk: `DR-DOS 5.0 and 6.0 -are reported to have difficulties with partition ID codes of 80 or more. -The Linux `fdisk' used to set the system type -of new partitions to hexadecimal 81. DR-DOS seems to confuse this with -hexadecimal 1, a DOS code. The values 82 for swap and 83 for file -systems should not cause problems with DR-DOS. If they do, you may use -the `fdisk' command `t' to change the system code of any Linux -partitions to some number less than hexadecimal 80; I suggest 42 and 43 -for the moment.' - -In fact, it seems that only 4 bits are significant for the DRDOS FDISK, -so that for example 11 and 21 are listed as DOS 2.0. However, DRDOS -itself seems to use the full byte. I have not been able to reproduce -any corruption with DRDOS or its fdisk. - -.SH BUGS -A corresponding interactive -.B cfdisk -(with curses interface) is still lacking. -.LP -There are too many options. - -.SH AUTHOR -A. E. Brouwer (aeb@cwi.nl) diff --git a/disk-utils/sfdisk.c b/disk-utils/sfdisk.c deleted file mode 100644 index 8fbe778fe..000000000 --- a/disk-utils/sfdisk.c +++ /dev/null @@ -1,2857 +0,0 @@ -/* - * sfdisk version 3.0 - aeb - 950813 - * - * Copyright (C) 1995 Andries E. Brouwer (aeb@cwi.nl) - * - * This program is free software. You can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation: either Version 1 - * or (at your option) any later version. - * - * A.V. Le Blanc (LeBlanc@mcc.ac.uk) wrote Linux fdisk 1992-1994, - * patched by various people (faith@cs.unc.edu, martin@cs.unc.edu, - * leisner@sdsp.mc.xerox.com, esr@snark.thyrsus.com, aeb@cwi.nl) - * 1993-1995, with version numbers (as far as I have seen) 0.93 - 2.0e. - * This program had (head,sector,cylinder) as basic unit, and was - * (therefore) broken in several ways for the use on larger disks - - * for example, my last patch (from 2.0d to 2.0e) was required - * to allow a partition to cross cylinder 8064, and to write an - * extended partition past the 4GB mark. - * - * The current program is a rewrite from scratch, and I started a - * version numbering at 3.0. - * Andries Brouwer, aeb@cwi.nl, 950813 - * - * Well, a good user interface is still lacking. On the other hand, - * many configurations cannot be handled by any other fdisk. - * I changed the name to sfdisk to prevent confusion. - aeb, 970501 - */ - -#define PROGNAME "sfdisk" -#define VERSION "3.07" -#define DATE "980518" - -#include <stdio.h> -#include <stdlib.h> /* atoi, free */ -#include <stdarg.h> /* varargs */ -#include <unistd.h> /* read, write */ -#include <fcntl.h> /* O_RDWR */ -#include <errno.h> /* ERANGE */ -#include <string.h> /* index() */ -#include <ctype.h> -#include <getopt.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <linux/unistd.h> /* _syscall */ -#include <linux/hdreg.h> /* HDIO_GETGEO */ -#include <linux/fs.h> /* BLKGETSIZE */ - -#define SIZE(a) (sizeof(a)/sizeof(a[0])) - -/* - * Table of contents: - * A. About seeking - * B. About sectors - * C. About heads, sectors and cylinders - * D. About system Ids - * E. About partitions - * F. The standard input - * G. The command line - * H. Listing the current situation - * I. Writing the new situation - */ -int exit_status = 0; - -int force = 0; /* 1: do what I say, even if it is stupid ... */ -int quiet = 0; /* 1: suppress all warnings */ -int Linux = 0; /* 1: suppress warnings irrelevant for Linux */ -int DOS = 0; /* 1: shift extended partitions by #sectors, not 1 */ -int dump = 0; /* 1: list in a format suitable for later input */ -int verify = 0; /* 1: check that listed partition is reasonable */ -int no_write = 0; /* 1: do not actually write to disk */ -int no_reread = 0; /* 1: skip the BLKRRPART ioctl test at startup */ -int leave_last = 0; /* 1: don't allocate the last cylinder */ -int opt_list = 0; -char *save_sector_file = NULL; -char *restore_sector_file = NULL; - -void -warn(char *s, ...) { - va_list p; - - va_start(p, s); - fflush(stdout); - if (!quiet) - vfprintf (stderr, s, p); - va_end(p); -} - -void -error(char *s, ...) { - va_list p; - - va_start(p, s); - fflush(stdout); - fprintf(stderr, "\n" PROGNAME ": "); - vfprintf(stderr, s, p); - va_end(p); -} - -void -fatal(char *s, ...) { - va_list p; - - va_start(p, s); - fflush(stdout); - fprintf(stderr, "\n" PROGNAME ": "); - vfprintf(stderr, s, p); - va_end(p); - exit(1); -} - -/* - * A. About seeking - */ - -/* - * sseek: seek to specified sector - return 0 on failure - * - * For >4GB disks lseek needs a > 32bit arg, and we have to use llseek. - * On the other hand, a 32 bit sector number is OK until 2TB. - * The routines _llseek and sseek below are the only ones that - * know about the loff_t type. - */ -#ifndef __alpha__ -static -_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, - loff_t *, res, uint, wh); -#endif - -int -sseek(char *dev, unsigned int fd, unsigned long s) { - loff_t in, out; - in = ((loff_t) s << 9); - out = 1; - -#ifndef __alpha__ - if (_llseek (fd, in>>32, in & 0xffffffff, &out, SEEK_SET) != 0) { -#else - if ((out = lseek(fd, in, SEEK_SET)) != in) { -#endif - perror("llseek"); - error("seek error on %s - cannot seek to %lu\n", dev, s); - return 0; - } - - if (in != out) { - error("seek error: wanted 0x%08x%08x, got 0x%08x%08x\n", - (uint)(in>>32), (uint)(in & 0xffffffff), - (uint)(out>>32), (uint)(out & 0xffffffff)); - return 0; - } - return 1; -} - -/* - * B. About sectors - */ - -/* - * We preserve all sectors read in a chain - some of these will - * have to be modified and written back. - */ -struct sector { - struct sector *next; - unsigned long sectornumber; - int to_be_written; - char data[512]; -} *sectorhead; - -void -free_sectors(void) { - struct sector *s; - - while (sectorhead) { - s = sectorhead; - sectorhead = s->next; - free(s); - } -} - -struct sector * -get_sector(char *dev, int fd, unsigned long sno) { - struct sector *s; - - for(s = sectorhead; s; s = s->next) - if(s->sectornumber == sno) - return s; - - if (!sseek(dev, fd, sno)) - return 0; - - if (!(s = (struct sector *) malloc(sizeof(struct sector)))) - fatal("out of memory - giving up\n"); - - if (read(fd, s->data, sizeof(s->data)) != sizeof(s->data)) { - perror("read"); - error("read error on %s - cannot read sector %lu\n", dev, sno); - free(s); - return 0; - } - - s->next = sectorhead; - sectorhead = s; - s->sectornumber = sno; - s->to_be_written = 0; - - return s; -} - -int -msdos_signature (struct sector *s) { - if (*(unsigned short *) (s->data + 0x1fe) != 0xaa55) { - error("ERROR: sector %lu does not have an msdos signature\n", - s->sectornumber); - return 0; - } - return 1; -} - -int -write_sectors(char *dev, int fd) { - struct sector *s; - - for (s = sectorhead; s; s = s->next) - if (s->to_be_written) { - if (!sseek(dev, fd, s->sectornumber)) - return 0; - if (write(fd, s->data, sizeof(s->data)) != sizeof(s->data)) { - perror("write"); - error("write error on %s - cannot write sector %lu\n", - dev, s->sectornumber); - return 0; - } - s->to_be_written = 0; - } - return 1; -} - -void -ulong_to_chars(unsigned long u, char *uu) { - int i; - - for(i=0; i<4; i++) { - uu[i] = (u & 0xff); - u >>= 8; - } -} - -unsigned long -chars_to_ulong(unsigned char *uu) { - int i; - unsigned long u = 0; - - for(i=3; i>=0; i--) - u = (u << 8) | uu[i]; - return u; -} - -int -save_sectors(char *dev, int fdin) { - struct sector *s; - char ss[516]; - int fdout; - - fdout = open(save_sector_file, O_WRONLY | O_CREAT, 0444); - if (fdout < 0) { - perror(save_sector_file); - error("cannot open partition sector save file (%s)\n", - save_sector_file); - return 0; - } - - for (s = sectorhead; s; s = s->next) - if (s->to_be_written) { - ulong_to_chars(s->sectornumber, ss); - if (!sseek(dev, fdin, s->sectornumber)) - return 0; - if (read(fdin, ss+4, 512) != 512) { - perror("read"); - error("read error on %s - cannot read sector %lu\n", - dev, s->sectornumber); - return 0; - } - if (write(fdout, ss, sizeof(ss)) != sizeof(ss)) { - perror("write"); - error("write error on %s\n", save_sector_file); - return 0; - } - } - return 1; -} - -void reread_disk_partition(char *dev, int fd); - -int -restore_sectors(char *dev) { - int fdin, fdout, ct; - struct stat statbuf; - char *ss0, *ss; - unsigned long sno; - - if (stat(restore_sector_file, &statbuf) < 0) { - perror(restore_sector_file); - error("cannot stat partition restore file (%s)\n", - restore_sector_file); - return 0; - } - if (statbuf.st_size % 516) { - error("partition restore file has wrong size - not restoring\n"); - return 0; - } - if (!(ss = (char *) malloc(statbuf.st_size))) { - error("out of memory?\n"); - return 0; - } - fdin = open(restore_sector_file, O_RDONLY); - if (fdin < 0) { - perror(restore_sector_file); - error("cannot open partition restore file (%s)\n", - restore_sector_file); - return 0; - } - if (read(fdin, ss, statbuf.st_size) != statbuf.st_size) { - perror("read"); - error("error reading %s\n", restore_sector_file); - return 0; - } - - fdout = open(dev, O_WRONLY); - if (fdout < 0) { - perror(dev); - error("cannot open device %s for writing\n", dev); - return 0; - } - - ss0 = ss; - ct = statbuf.st_size/516; - while(ct--) { - sno = chars_to_ulong(ss); - if (!sseek(dev, fdout, sno)) - return 0; - if (write(fdout, ss+4, 512) != 512) { - perror(dev); - error("error writing sector %lu on %s\n", sno, dev); - return 0; - } - ss += 516; - } - free(ss0); - - reread_disk_partition(dev, fdout); - - return 1; -} - -/* - * C. About heads, sectors and cylinders - */ - -/* - * <linux/hdreg.h> defines HDIO_GETGEO and - * struct hd_geometry { - * unsigned char heads; - * unsigned char sectors; - * unsigned short cylinders; - * unsigned long start; - * }; - */ - -unsigned long cylindersize; -unsigned long heads, sectors, cylinders; -unsigned long specified_heads, specified_sectors, specified_cylinders; - -void -get_cylindersize(char *dev, int fd, int silent) { - struct hd_geometry g; - int ioctl_ok = 0; - - heads = sectors = cylinders = 0; - - if (!ioctl(fd, HDIO_GETGEO, &g)) { - ioctl_ok = 1; - - heads = g.heads; - sectors = g.sectors; - cylinders = g.cylinders; - } - - if (specified_heads) - heads = specified_heads; - if (specified_sectors) - sectors = specified_sectors; - if (specified_cylinders) - cylinders = specified_cylinders; - - cylindersize = heads * sectors; - - if (ioctl_ok) { - if (g.start && !force) { - warn( - "Warning: start=%d - this looks like a partition rather than\n" - "the entire disk. Using fdisk on it is probably meaningless.\n" - "[Use the --force option if you really want this]\n", g.start); - exit(1); - } - if (heads != g.heads) - warn("Warning: HDIO_GETGEO says that there are %d heads\n", - g.heads); - if (sectors != g.sectors) - warn("Warning: HDIO_GETGEO says that there are %d sectors\n", - g.sectors); - if (cylinders != g.cylinders) - warn("Warning: HDIO_GETGEO says that there are %d cylinders\n", - g.cylinders); - } else if (!silent) - if (!heads || !sectors || !cylinders) - printf("Disk %s: cannot get geometry\n", dev); - if (sectors > 63) - warn("Warning: unlikely number of sectors (%d) - usually at most 63\n" - "This will give problems with all software that uses C/H/S addressing.\n", - sectors); - if (!silent) - printf("\nDisk %s: %lu heads, %lu sectors, %lu cylinders\n", - dev, heads, sectors, cylinders); -} - -typedef struct { unsigned char h,s,c; } chs; /* has some c bits in s */ -chs zero_chs = { 0,0,0 }; - -typedef struct { unsigned long h,s,c; } longchs; -longchs zero_longchs; - -chs -longchs_to_chs (longchs aa) { - chs a; - - if (aa.h < 256 && aa.s < 64 && aa.c < 1024) { - a.h = aa.h; - a.s = aa.s | ((aa.c >> 2) & 0xc0); - a.c = (aa.c & 0xff); - } else if (heads && sectors) { - a.h = heads - 1; - a.s = sectors | 0xc0; - a.c = 0xff; - } else - a = zero_chs; - return a; -} - -longchs -chs_to_longchs (chs a) { - longchs aa; - - aa.h = a.h; - aa.s = (a.s & 0x3f); - aa.c = (a.s & 0xc0); - aa.c = (aa.c << 2) + a.c; - return aa; -} - -longchs -ulong_to_longchs (unsigned long sno) { - longchs aa; - - if (heads && sectors && cylindersize) { - aa.s = 1 + sno % sectors; - aa.h = (sno / sectors) % heads; - aa.c = sno / cylindersize; - return aa; - } else { - return zero_longchs; - } -} - -unsigned long -longchs_to_ulong (longchs aa) { - return (aa.c*cylindersize + aa.h*sectors + aa.s - 1); -} - -chs -ulong_to_chs (unsigned long sno) { - return longchs_to_chs(ulong_to_longchs(sno)); -} - -unsigned long -chs_to_ulong (chs a) { - return longchs_to_ulong(chs_to_longchs(a)); -} - -int -is_equal_chs (chs a, chs b) { - return (a.h == b.h && a.s == b.s && a.c == b.c); -} - -int -chs_ok (chs a, char *v, char *w) { - longchs aa = chs_to_longchs(a); - int ret = 1; - - if (is_equal_chs(a, zero_chs)) - return 1; - if (heads && aa.h >= heads) { - warn("%s of partition %s has impossible value for head: " - "%d (should be in 0-%d)\n", w, v, aa.h, heads-1); - ret = 0; - } - if (sectors && (aa.s == 0 || aa.s > sectors)) { - warn("%s of partition %s has impossible value for sector: " - "%d (should be in 1-%d)\n", w, v, aa.s, sectors); - ret = 0; - } - if (cylinders && aa.c >= cylinders) { - warn("%s of partition %s has impossible value for cylinders: " - "%d (should be in 0-%d)\n", w, v, aa.c, cylinders-1); - ret = 0; - } - return ret; -} - -/* - * D. About system Ids - */ - -#define EMPTY_PARTITION 0 -#define EXTENDED_PARTITION 5 -#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> - * and SFS and several other sources. - */ -struct systypes { - unsigned char type; - char *name; -} sys_types[] = { - {0, "Empty"}, - {1, "DOS 12-bit FAT"}, /* Primary DOS with 12-bit FAT */ - {2, "XENIX /"}, /* XENIX / filesystem */ - {3, "XENIX /usr"}, /* XENIX /usr filesystem */ - {4, "DOS 16-bit FAT <32M"}, /* Primary DOS with 16-bit FAT */ - {5, "DOS Extended"}, /* DOS 3.3+ extended partition */ - {6, "DOS 16-bit FAT >=32M"}, - {7, "HPFS / NTFS"}, - {8, "AIX boot or SplitDrive"}, - {9, "AIX data or Coherent"}, - {0x0a, "OS/2 Boot Manager"}, - {0x0b, "Win95 FAT32"}, - {0x0c, "Win95 FAT32 (LBA)"}, - {0x0e, "Win95 FAT16 (LBA)"}, - {0x0f, "Win95 Extended (LBA)"}, - {0x10, "OPUS"}, - {0x11, "Hidden DOS FAT12"}, - {0x12, "Compaq diagnostics"}, - {0x14, "Hidden DOS FAT16"}, - {0x16, "Hidden DOS FAT16 (big)"}, - {0x17, "Hidden HPFS/NTFS"}, - {0x18, "AST Windows swapfile"}, - {0x24, "NEC DOS"}, - {0x3c, "PartitionMagic recovery"}, - {0x40, "Venix 80286"}, - {0x41, "Linux/MINIX (sharing disk with DRDOS)"}, - {0x42, "SFS or Linux swap (sharing disk with DRDOS)"}, - {0x43, "Linux native (sharing disk with DRDOS)"}, - {0x50, "DM (disk manager)"}, - {0x51, "DM6 Aux1 (or Novell)"}, - {0x52, "CP/M or Microport SysV/AT"}, - {0x53, "DM6 Aux3"}, - {0x54, "DM6"}, - {0x55, "EZ-Drive (disk manager)"}, - {0x56, "Golden Bow (disk manager)"}, - {0x5c, "Priam Edisk (disk manager)"}, - {0x61, "SpeedStor"}, - {0x63, "GNU HURD or Mach or Sys V/386 (such as ISC UNIX)"}, - {0x64, "Novell Netware 286"}, - {0x65, "Novell Netware 386"}, - {0x70, "DiskSecure Multi-Boot"}, - {0x75, "PC/IX"}, - {0x77, "QNX4.x"}, - {0x78, "QNX4.x 2nd part"}, - {0x79, "QNX4.x 3rd part"}, - {0x80, "MINIX until 1.4a"}, - {0x81, "MINIX / old Linux"}, - {0x82, "Linux swap"}, - {0x83, "Linux native"}, - {0x84, "OS/2 hidden C: drive"}, - {0x85, "Linux extended"}, - {0x86, "NTFS volume set"}, - {0x87, "NTFS volume set"}, - {0x93, "Amoeba"}, - {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"}, - {0xc1, "DRDOS/sec (FAT-12)"}, - {0xc4, "DRDOS/sec (FAT-16, < 32M)"}, - {0xc6, "DRDOS/sec (FAT-16, >= 32M)"}, - {0xc7, "Syrinx"}, - {0xdb, "CP/M or Concurrent CP/M or Concurrent DOS or CTOS"}, - {0xe1, "DOS access or SpeedStor 12-bit FAT extended partition"}, - {0xe3, "DOS R/O or SpeedStor"}, - {0xe4, "SpeedStor 16-bit FAT extended partition < 1024 cyl."}, - {0xf1, "SpeedStor"}, - {0xf2, "DOS 3.3+ secondary"}, - {0xf4, "SpeedStor large partition"}, - {0xfe, "SpeedStor >1024 cyl. or LANstep"}, - {0xff, "Xenix Bad Block Table"} -}; - - -const char * -sysname(unsigned char type) { - struct systypes *s; - - for (s = sys_types; s - sys_types < SIZE(sys_types); s++) - if (s->type == type) - return s->name; - return "Unknown"; -} - -void -list_types(void) { - struct systypes *s; - - printf("Id Name\n\n"); - for (s = sys_types; s - sys_types < SIZE(sys_types); s++) - printf("%2x %s\n", s->type, s->name); -} - -int -is_extended(unsigned char type) { - return (type == EXTENDED_PARTITION - || type == LINUX_EXTENDED - || type == WIN98_EXTENDED); -} - -int -is_bsd(unsigned char type) { - return (type == BSD_PARTITION); -} - -/* - * E. About partitions - */ - -/* MS/DOS partition */ - -struct partition { - unsigned char bootable; /* 0 or 0x80 */ - chs begin_chs; - unsigned char sys_type; - chs end_chs; - unsigned int start_sect; /* starting sector counting from 0 */ - unsigned int nr_sects; /* nr of sectors in partition */ -}; - -/* Unfortunately, partitions are not aligned, and non-Intel machines - are unhappy with non-aligned integers. So, we need a copy by hand. */ -int -copy_to_int(unsigned char *cp) { - unsigned int m; - - m = *cp++; - m += (*cp++ << 8); - m += (*cp++ << 16); - m += (*cp++ << 24); - return m; -} - -void -copy_from_int(int m, char *cp) { - *cp++ = (m & 0xff); m >>= 8; - *cp++ = (m & 0xff); m >>= 8; - *cp++ = (m & 0xff); m >>= 8; - *cp++ = (m & 0xff); -} - -void -copy_to_part(char *cp, struct partition *p) { - p->bootable = *cp++; - p->begin_chs.h = *cp++; - p->begin_chs.s = *cp++; - p->begin_chs.c = *cp++; - p->sys_type = *cp++; - p->end_chs.h = *cp++; - p->end_chs.s = *cp++; - p->end_chs.c = *cp++; - p->start_sect = copy_to_int(cp); - p->nr_sects = copy_to_int(cp+4); -} - -void -copy_from_part(struct partition *p, char *cp) { - *cp++ = p->bootable; - *cp++ = p->begin_chs.h; - *cp++ = p->begin_chs.s; - *cp++ = p->begin_chs.c; - *cp++ = p->sys_type; - *cp++ = p->end_chs.h; - *cp++ = p->end_chs.s; - *cp++ = p->end_chs.c; - copy_from_int(p->start_sect, cp); - copy_from_int(p->nr_sects, cp+4); -} - -/* Roughly speaking, Linux doesn't use any of the above fields except - for partition type, start sector and number of sectors. (However, - see also linux/drivers/scsi/fdomain.c.) - The only way partition type is used (in the kernel) is the comparison - for equality with EXTENDED_PARTITION (and these Disk Manager types). */ - -struct part_desc { - unsigned long start; - unsigned long size; - 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 * -outer_extended_partition(struct part_desc *p) { - while (p->ep) - p = p->ep; - return p; -} - -int -is_parent(struct part_desc *pp, struct part_desc *p) { - while (p) { - if (pp == p) - return 1; - p = p->ep; - } - return 0; -} - -struct disk_desc { - struct part_desc partitions[128]; - int partno; -} oldp, newp; - -/* determine where on the disk this information goes */ -void -add_sector_and_offset(struct disk_desc *z) { - int pno; - struct part_desc *p; - - for (pno = 0; pno < z->partno; pno++) { - p = &(z->partitions[pno]); - p->offset = 0x1be + (pno%4)*sizeof(struct partition); - p->sector = (p->ep ? p->ep->start : 0); - } -} - -/* tell the kernel to reread the partition tables */ -int reread_ioctl(int fd) { - if(ioctl(fd, BLKRRPART)) { - perror("BLKRRPART"); - return -1; - } - return 0; -} - -/* reread after writing */ -void -reread_disk_partition(char *dev, int fd) { - printf("Re-reading the partition table ...\n"); - fflush(stdout); - sync(); - sleep(3); /* superfluous since 1.3.20 */ - - if(reread_ioctl(fd)) - printf("The command to re-read the partition table failed\n" - "Reboot your system now, before using mkfs\n"); - - if (close(fd)) { - perror(dev); - printf("Error closing %s\n", dev); - } - printf("\n"); -} - -/* find Linux name of this partition, assuming that it will have a name */ -int -index_to_linux(int pno, struct disk_desc *z) { - int i, ct = 1; - struct part_desc *p = &(z->partitions[0]); - for (i=0; i<pno; i++,p++) - if(i < 4 || (p->size > 0 && !is_extended(p->p.sys_type))) - ct++; - return ct; -} - -int -linux_to_index(int lpno, struct disk_desc *z) { - int i, ct = 0; - struct part_desc *p = &(z->partitions[0]); - for (i=0; i<z->partno && ct < lpno; i++,p++) - if((i < 4 || (p->size > 0 && !is_extended(p->p.sys_type))) - && ++ct == lpno) - return i; - return -1; -} - -int -asc_to_index(char *pnam, struct disk_desc *z) { - int pnum, pno; - - if (*pnam == '#') { - pno = atoi(pnam+1); - } else { - pnum = atoi(pnam); - pno = linux_to_index(pnum, z); - } - if (!(pno >= 0 && pno < z->partno)) - fatal("%s: no such partition\n", pnam); - return pno; -} - -/* - * List partitions - in terms of sectors, blocks or cylinders - */ -#define F_SECTOR 1 -#define F_BLOCK 2 -#define F_CYLINDER 3 -#define F_MEGABYTE 4 - -int default_format = F_MEGABYTE; -int specified_format = 0; -int show_extended = 0; -int one_only = 0; -int one_only_pno; -int increment = 0; - -void -set_format(char c) { - switch(c) { - default: - printf("unrecognized format - using sectors\n"); - case 'S': specified_format = F_SECTOR; break; - case 'B': specified_format = F_BLOCK; break; - case 'C': specified_format = F_CYLINDER; break; - case 'M': specified_format = F_MEGABYTE; break; - } -} - -unsigned long -unitsize(int format) { - default_format = (cylindersize ? F_CYLINDER : F_MEGABYTE); - if (!format && !(format = specified_format)) - format = default_format; - - switch(format) { - default: - case F_CYLINDER: - if(cylindersize) return cylindersize; - case F_SECTOR: - return 1; - case F_BLOCK: - return 2; - case F_MEGABYTE: - return 2048; - } -} - -unsigned long -get_disksize(int format) { - unsigned long cs = cylinders; - if (cs && leave_last) - cs--; - return (cs * cylindersize) / unitsize(format); -} - -void -out_partition_header(char *dev, int format) { - if (dump) { - printf("# partition table of %s\n", dev); - printf("unit: sectors\n\n"); - return; - } - - default_format = (cylindersize ? F_CYLINDER : F_MEGABYTE); - if (!format && !(format = specified_format)) - format = default_format; - - switch(format) { - default: - printf("unimplemented format - using %s\n", - cylindersize ? "cylinders" : "sectors"); - case F_CYLINDER: - if (cylindersize) { - printf("Units = cylinders of %lu bytes, blocks of 1024 bytes" - ", counting from %d\n\n", - cylindersize<<9, increment); - printf(" Device Boot Start End #cyls #blocks Id System\n"); - break; - } - /* fall through */ - case F_SECTOR: - printf("Units = sectors of 512 bytes, counting from %d\n\n", - increment); - printf(" Device Boot Start End #sectors Id System\n"); - break; - case F_BLOCK: - printf("Units = blocks of 1024 bytes, counting from %d\n\n", - increment); - printf(" Device Boot Start End #blocks Id System\n"); - break; - case F_MEGABYTE: - printf("Units = megabytes of 1048576 bytes, blocks of 1024 bytes" - ", counting from %d\n\n", increment); - printf(" Device Boot Start End MB #blocks Id System\n"); - break; - } -} - -static void -out_rounddown(int width, unsigned long n, unsigned long unit, int inc) { - printf("%*lu", width, inc + n/unit); - if (unit != 1) - putchar((n % unit) ? '+' : ' '); - putchar(' '); -} - -static void -out_roundup(int width, unsigned long n, unsigned long unit, int inc) { - if (n == (unsigned long)(-1)) - printf("%*s", width, "-"); - else - printf("%*lu", width, inc + n/unit); - if (unit != 1) - putchar(((n+1) % unit) ? '-' : ' '); - putchar(' '); -} - -static void -out_roundup_size(int width, unsigned long n, unsigned long unit) { - printf("%*lu", width, (n+unit-1)/unit); - if (unit != 1) - putchar((n % unit) ? '-' : ' '); - putchar(' '); -} - -void -out_partition(char *dev, int format, struct part_desc *p, struct disk_desc *z) { - unsigned long start, end, size; - int pno, lpno; - - if (!format && !(format = specified_format)) - format = default_format; - - pno = p - &(z->partitions[0]); /* our index */ - lpno = index_to_linux(pno, z); /* name of next one that has a name */ - if(pno == linux_to_index(lpno, z)) /* was that us? */ - printf("%8s%-2u", dev, lpno); /* yes */ - else if(show_extended) - printf(" - "); - else - return; - putchar(dump ? ':' : ' '); - - start = p->start; - end = p->start + p->size - 1; - size = p->size; - - if (dump) { - printf(" start=%9lu", start); - printf(", size=%8lu", size); - if (p->ptype == DOS_TYPE) { - printf(", Id=%2x", p->p.sys_type); - if (p->p.bootable == 0x80) - printf(", bootable"); - } - printf("\n"); - return; - } - - if(p->ptype != DOS_TYPE || p->p.bootable == 0) - printf(" "); - else if(p->p.bootable == 0x80) - printf(" * "); - else - printf(" ? "); /* garbage */ - - switch(format) { - case F_CYLINDER: - if (cylindersize) { - out_rounddown(6, start, cylindersize, increment); - out_roundup(6, end, cylindersize, increment); - out_roundup_size(6, size, cylindersize); - out_rounddown(8, size, 2, 0); - break; - } - /* fall through */ - default: - case F_SECTOR: - out_rounddown(9, start, 1, increment); - out_roundup(9, end, 1, increment); - out_rounddown(9, size, 1, 0); - break; - case F_BLOCK: -#if 0 - printf("%8lu,%3lu ", - p->sector/2, ((p->sector & 1) ? 512 : 0) + p->offset); -#endif - out_rounddown(8, start, 2, increment); - out_roundup(8, end, 2, increment); - out_rounddown(8, size, 2, 0); - break; - case F_MEGABYTE: - out_rounddown(5, start, 2048, increment); - out_roundup(5, end, 2048, increment); - out_roundup_size(5, size, 2048); - out_rounddown(8, size, 2, 0); - break; - } - 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 && p->ptype == DOS_TYPE) { - chs a, b; - longchs aa, bb; - a = (size ? ulong_to_chs(start) : zero_chs); - b = p->p.begin_chs; - aa = chs_to_longchs(a); - bb = chs_to_longchs(b); - if(a.s && !is_equal_chs(a, b)) - printf("\t\tstart: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", - aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); - a = (size ? ulong_to_chs(end) : zero_chs); - b = p->p.end_chs; - aa = chs_to_longchs(a); - bb = chs_to_longchs(b); - if(a.s && !is_equal_chs(a, b)) - printf("\t\tend: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", - aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); - if(cylinders && cylinders < 1024 && bb.c > cylinders) - printf("partition ends on cylinder %ld, beyond the end of the disk\n", - bb.c); - } -} - -void -out_partitions(char *dev, struct disk_desc *z) { - int pno, format = 0; - - if (z->partno == 0) - printf("No partitions found\n"); - else { - out_partition_header(dev, format); - for(pno=0; pno < z->partno; pno++) { - out_partition(dev, format, &(z->partitions[pno]), z); - if(show_extended && pno%4==3) - printf("\n"); - } - } -} - -static int -disj(struct part_desc *p, struct part_desc *q) { - return - ((p->start + p->size <= q->start) - || (is_extended(p->p.sys_type) - && q->start + q->size <= p->start + p->size)); -} - -char * -pnumber(struct part_desc *p, struct disk_desc *z) { - static char buf[20]; - int this, next; - struct part_desc *p0 = &(z->partitions[0]); - - this = index_to_linux(p-p0, z); - next = index_to_linux(p-p0+1, z); - - if (next > this) - sprintf(buf, "%d", this); - else - sprintf(buf, "[%d]", this); - return buf; -} - -int -partitions_ok(struct disk_desc *z) { - struct part_desc *partitions = &(z->partitions[0]), *p, *q; - int partno = z->partno; - -#define PNO(p) pnumber(p, z) - - /* Have at least 4 partitions been defined? */ - if (partno < 4) { - if (!partno) - fatal("no partition table present.\n"); - else - fatal("strange, only %d partitions defined.\n", partno); - return 0; - } - - /* Are the partitions of size 0 marked empty? - And do they have start = 0? And bootable = 0? */ - for (p = partitions; p - partitions < partno; p++) - if (p->size == 0) { - if(p->p.sys_type != EMPTY_PARTITION) - warn("Warning: partition %s has size 0 but is not marked Empty\n", - PNO(p)); - else if(p->p.bootable != 0) - warn("Warning: partition %s has size 0 and is bootable\n", - PNO(p)); - else if(p->p.start_sect != 0) - warn("Warning: partition %s has size 0 and nonzero start\n", - PNO(p)); - /* all this is probably harmless, no error return */ - } - - /* 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) { - warn("Warning: partition %s ", PNO(p)); - warn("is not contained in partition %s\n", PNO(q)); - return 0; - } - } - - /* Are the data partitions mutually disjoint? */ - for (p = partitions; p < partitions+partno; p++) - if (p->size && !is_extended(p->p.sys_type)) - for (q = p+1; q < partitions+partno; q++) - if (q->size && !is_extended(q->p.sys_type)) - if(!((p->start > q-> start) ? disj(q,p) : disj(p,q))) { - warn("Warning: partitions %s ", PNO(p)); - warn("and %s overlap\n", PNO(q)); - 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++) - if (p->size) { - if(p->start == 0) { - warn("Warning: partition %s starts at sector 0\n", PNO(p)); - return 0; - } - if (p->size && p->start + p->size > ds) { - warn("Warning: partition %s extends past end of disk\n", PNO(p)); - return 0; - } - } - } - - /* At most one chain of DOS extended partitions ? */ - /* It seems that the OS/2 fdisk has the additional requirement - that the extended partition must be the fourth one */ - { int ect = 0; - for (p = partitions; p < partitions+4; p++) - if (p->p.sys_type == EXTENDED_PARTITION) - ect++; - if (ect > 1 && !Linux) { - warn("Among the primary partitions, at most one can be extended\n"); - warn(" (although this is not a problem under Linux)\n"); - return 0; - } - } - - /* - * Do all partitions start at a cylinder boundary ? - * (this is not required for Linux) - * The first partition starts after MBR. - * Logical partitions start slightly after the containing extended partn. - */ - if (cylindersize) { - for(p = partitions; p < partitions+partno; p++) - if (p->size) { - if(p->start % cylindersize != 0 - && (!p->ep || p->start / cylindersize != p->ep->start / cylindersize) - && (p->p.start_sect >= cylindersize)) { - warn("Warning: partition %s does not start " - "at a cylinder boundary\n", PNO(p)); - if (!Linux) - return 0; - } - if((p->start + p->size) % cylindersize) { - warn("Warning: partition %s does not end " - "at a cylinder boundary\n", PNO(p)); - if (!Linux) - return 0; - } - } - } - - /* Usually, one can boot only from primary partitions. */ - /* In fact, from a unique one only. */ - /* do not warn about bootable extended partitions - - often LILO is there */ - { int pno = -1; - for(p = partitions; p < partitions+partno; p++) - if (p->p.bootable) { - if (pno == -1) - pno = p - partitions; - else if (p - partitions < 4) { - warn("Warning: more than one primary partition is marked " - "bootable (active)\n" - "This does not matter for LILO, but the DOS MBR will " - "not boot this disk.\n"); - break; - } - if (p - partitions >= 4) { - warn("Warning: usually one can boot from primary partitions " - "only\n" "LILO disregards the `bootable' flag.\n"); - break; - } - } - if (pno == -1 || pno >= 4) - warn("Warning: no primary partition is marked bootable (active)\n" - "This does not matter for LILO, but the DOS MBR will " - "not boot this disk.\n"); - } - - /* Is chs as we expect? */ - 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; - b = p->p.begin_chs; - aa = chs_to_longchs(a); - bb = chs_to_longchs(b); - if (!chs_ok(b, PNO(p), "start")) - return 0; - if(a.s && !is_equal_chs(a, b)) - warn("partition %s: start: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", - PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); - a = p->size ? ulong_to_chs(p->start + p->size - 1) : zero_chs; - b = p->p.end_chs; - aa = chs_to_longchs(a); - bb = chs_to_longchs(b); - if (!chs_ok(b, PNO(p), "end")) - return 0; - if(a.s && !is_equal_chs(a, b)) - warn("partition %s: end: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", - PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); - if(cylinders && cylinders < 1024 && bb.c > cylinders) - warn("partition %s ends on cylinder %ld, beyond the end of the disk\n", - PNO(p), bb.c); - } - - return 1; - -#undef PNO -} - -static void -extended_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) { - char *cp; - struct sector *s; - unsigned long start, here, next; - int i, moretodo = 1; - struct partition p; - struct part_desc *partitions = &(z->partitions[0]); - int pno = z->partno; - - here = start = ep->start; - - while (moretodo) { - moretodo = 0; - - if (!(s = get_sector(dev, fd, here))) - break; - - if (!msdos_signature(s)) - break; - - cp = s->data + 0x1be; - - if (pno+4 >= SIZE(z->partitions)) { - printf("too many partitions - ignoring those past nr (%d)\n", - pno-1); - break; - } - - next = 0; - - for (i=0; i<4; i++,cp += sizeof(struct partition)) { - partitions[pno].sector = here; - partitions[pno].offset = cp - s->data; - partitions[pno].ep = ep; - copy_to_part(cp,&p); - if (is_extended(p.sys_type)) { - if (next) - printf("tree of partitions?\n"); - partitions[pno].start = next = start + p.start_sect; - moretodo = 1; - } else { - partitions[pno].start = here + p.start_sect; - } - partitions[pno].size = p.nr_sects; - partitions[pno].ptype = DOS_TYPE; - partitions[pno].p = p; - pno++; - } - here = next; - } - - 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; - char *cp; - struct partition pt; - struct sector *s; - struct part_desc *partitions = &(z->partitions[0]); - int pno = z->partno; - - if (!(s = get_sector(dev, fd, start))) - return 0; - - if (!msdos_signature(s)) - return 0; - - cp = s->data + 0x1be; - copy_to_part(cp,&pt); - - /* If I am not mistaken, recent kernels will hide this from us, - so we will never actually see traces of a Disk Manager */ - if (pt.sys_type == DM6_PARTITION - || pt.sys_type == EZD_PARTITION - || pt.sys_type == DM6_AUX1PARTITION - || pt.sys_type == DM6_AUX3PARTITION) { - printf("detected Disk Manager - unable to handle that\n"); - return 0; - } - { unsigned int sig = *(unsigned short *)(s->data + 2); - if (sig <= 0x1ae - && *(unsigned short *)(s->data + sig) == 0x55aa - && (1 & *(unsigned char *)(s->data + sig + 2))) { - printf("DM6 signature found - giving up\n"); - return 0; - } - } - - for (pno=0; pno<4; pno++,cp += sizeof(struct partition)) { - partitions[pno].sector = start; - partitions[pno].offset = cp - s->data; - copy_to_part(cp,&pt); - partitions[pno].start = start + pt.start_sect; - partitions[pno].size = pt.nr_sects; - partitions[pno].ep = 0; - partitions[pno].p = pt; - } - - z->partno = pno; - - 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"); - continue; - } - 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; -} - -static int -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) - && !sun_partition(dev, fd, 0, z) - && !amiga_partition(dev, fd, 0, z)) { - printf(" %s: unrecognized partition\n", dev); - return; - } -} - -int -write_partitions(char *dev, int fd, struct disk_desc *z) { - struct sector *s; - struct part_desc *partitions = &(z->partitions[0]), *p; - int pno = z->partno; - - if (no_write) { - printf("-n flag was given: Nothing changed\n"); - exit(0); - } - - for (p = partitions; p < partitions+pno; p++) { - s = get_sector(dev, fd, p->sector); - if (!s) return 0; - s->to_be_written = 1; - copy_from_part(&(p->p), s->data + p->offset); - *(unsigned short *)(&(s->data[0x1fe])) = 0xaa55; - } - if (save_sector_file) { - if (!save_sectors(dev, fd)) { - fatal("Failed saving the old sectors - aborting\n"); - return 0; - } - } - if (!write_sectors(dev, fd)) { - error("Failed writing the partition on %s\n", dev); - return 0; - } - return 1; -} - -/* - * F. The standard input - */ - -/* - * Input format: - * <start> <size> <type> <bootable> <c,h,s> <c,h,s> - * Fields are separated by whitespace or comma or semicolon possibly - * followed by whitespace; initial and trailing whitespace is ignored. - * Numbers can be octal, decimal or hexadecimal, decimal is default - * The <c,h,s> parts can (and probably should) be omitted. - * Bootable is specified as [*|-], with as default not-bootable. - * Type is given in hex, without the 0x prefix, or is [E|S|L|X], where - * L (LINUX_NATIVE (83)) is the default, S is LINUX_SWAP (82), and E - * is EXTENDED_PARTITION (5), X is LINUX_EXTENDED (85). - * The default value of start is the first nonassigned sector/cylinder/... - * The default value of size is as much as possible (until next - * partition or end-of-disk). - * .: end of chain of extended partitions. - * - * On interactive input an empty line means: all defaults. - * Otherwise empty lines are ignored. - */ - -int eof, eob; - -struct dumpfld { - int fldno; - char *fldname; - int is_bool; -} dumpflds[] = { - { 0, "start", 0 }, - { 1, "size", 0 }, - { 2, "Id", 0 }, - { 3, "bootable", 1 }, - { 4, "bh", 0 }, - { 5, "bs", 0 }, - { 6, "bc", 0 }, - { 7, "eh", 0 }, - { 8, "es", 0 }, - { 9, "ec", 0 } -}; - -/* - * Read a line, split it into fields - * - * (some primitive handwork, but a more elaborate parser seems - * unnecessary) - */ -#define RD_EOF (-1) -#define RD_CMD (-2) - -int -read_stdin(unsigned char **fields, unsigned char *line, int fieldssize, int linesize) { - unsigned char *lp, *ip; - int c, fno; - - /* boolean true and empty string at start */ - line[0] = '*'; - line[1] = 0; - for (fno=0; fno < fieldssize; fno++) - fields[fno] = line + 1; - fno = 0; - - /* read a line from stdin */ - lp = fgets(line+2, linesize, stdin); - if (lp == NULL) { - eof = 1; - return RD_EOF; - } - if (!(lp = index(lp, '\n'))) - fatal("long or incomplete input line - quitting\n"); - *lp = 0; - - /* remove comments, if any */ - if ((lp = index(line+2, '#')) != 0) - *lp = 0; - - /* recognize a few commands - to be expanded */ - if (!strcmp(line+2, "unit: sectors")) { - specified_format = F_SECTOR; - return RD_CMD; - } - - /* dump style? - then bad input is fatal */ - if ((ip = index(line+2, ':')) != 0) { - struct dumpfld *d; - - nxtfld: - ip++; - while(isspace(*ip)) - ip++; - if (*ip == 0) - return fno; - for(d = dumpflds; d-dumpflds < SIZE(dumpflds); d++) { - if(!strncmp(ip, d->fldname, strlen(d->fldname))) { - ip += strlen(d->fldname); - while(isspace(*ip)) - ip++; - if (d->is_bool) - fields[d->fldno] = line; - else if (*ip == '=') { - while(isspace(*++ip)) ; - fields[d->fldno] = ip; - while(isalnum(*ip)) /* 0x07FF */ - ip++; - } else - fatal("input error: `=' expected after %s field\n", - d->fldname); - if (fno <= d->fldno) - fno = d->fldno + 1; - if(*ip == 0) - return fno; - if(*ip != ',' && *ip != ';') - fatal("input error: unexpected character %c after %s field\n", - *ip, d->fldname); - *ip = 0; - goto nxtfld; - } - } - fatal("unrecognized input: %s\n", ip); - } - - /* split line into fields */ - lp = ip = line+2; - fields[fno++] = lp; - while((c = *ip++) != 0) { - if (!lp[-1] && (c == '\t' || c == ' ')) - ; - else if (c == '\t' || c == ' ' || c == ',' || c == ';') { - *lp++ = 0; - if (fno < fieldssize) - fields[fno++] = lp; - continue; - } else - *lp++ = c; - } - - if (lp == fields[fno-1]) - fno--; - return fno; -} - -/* read a number, use default if absent */ -int -get_ul(char *u, unsigned long *up, unsigned long def, int base) { - char *nu; - - if (*u) { - errno = 0; - *up = strtoul(u, &nu, base); - if (errno == ERANGE) { - printf("number too big\n"); - return -1; - } - if (*nu) { - printf("trailing junk after number\n"); - return -1; - } - } else - *up = def; - return 0; -} - -/* There are two common ways to structure extended partitions: - as nested boxes, and as a chain. Sometimes the partitions - must be given in order. Sometimes all logical partitions - must lie inside the outermost extended partition. -NESTED: every partition is contained in the surrounding partitions - and is disjoint from all others. -CHAINED: every data partition is contained in the surrounding partitions - and disjoint from all others, but extended partitions may lie outside - (insofar as allowed by all_logicals_inside_outermost_extended). -ONESECTOR: all data partitions are mutually disjoint; extended partitions - each use one sector only (except perhaps for the outermost one). -*/ -int partitions_in_order = 0; -int all_logicals_inside_outermost_extended = 1; -enum { NESTED, CHAINED, ONESECTOR } boxes = NESTED; - -/* find the default value for <start> - assuming entire units */ -unsigned long -first_free(int pno, int is_extended, struct part_desc *ep, int format, - unsigned long mid, struct disk_desc *z) { - unsigned long ff, fff; - unsigned long unit = unitsize(format); - struct part_desc *partitions = &(z->partitions[0]), *pp = 0; - - /* if containing ep undefined, look at its container */ - if (ep && ep->p.sys_type == EMPTY_PARTITION) - ep = ep->ep; - - if (ep) { - if (boxes == NESTED || (boxes == CHAINED && !is_extended)) - pp = ep; - else if (all_logicals_inside_outermost_extended) - pp = outer_extended_partition(ep); - } -#if 0 - ff = pp ? (pp->start + unit - 1) / unit : 0; -#else - /* rounding up wastes almost an entire cylinder - round down - and leave it to compute_start_sect() to fix the difference */ - ff = pp ? pp->start / unit : 0; -#endif - /* MBR and 1st sector of an extended partition are never free */ - if (unit == 1) - ff++; - - again: - for(pp = partitions; pp < partitions+pno; pp++) { - if (!is_parent(pp, ep) && pp->size > 0) { - if ((partitions_in_order || pp->start / unit <= ff - || (mid && pp->start / unit <= mid)) - && (fff = (pp->start + pp->size + unit - 1) / unit) > ff) { - ff = fff; - goto again; - } - } - } - - return ff; -} - -/* find the default value for <size> - assuming entire units */ -unsigned long -max_length(int pno, int is_extended, struct part_desc *ep, int format, - unsigned long start, struct disk_desc *z) { - unsigned long fu; - unsigned long unit = unitsize(format); - struct part_desc *partitions = &(z->partitions[0]), *pp = 0; - - /* if containing ep undefined, look at its container */ - if (ep && ep->p.sys_type == EMPTY_PARTITION) - ep = ep->ep; - - if (ep) { - if (boxes == NESTED || (boxes == CHAINED && !is_extended)) - pp = ep; - else if (all_logicals_inside_outermost_extended) - pp = outer_extended_partition(ep); - } - fu = pp ? (pp->start + pp->size) / unit : get_disksize(format); - - for(pp = partitions; pp < partitions+pno; pp++) - if (!is_parent(pp, ep) && pp->size > 0 - && pp->start / unit >= start && pp->start / unit < fu) - fu = pp->start / unit; - - return (fu > start) ? fu - start : 0; -} - -/* compute starting sector of a partition inside an extended one */ -/* ep is 0 or points to surrounding extended partition */ -int -compute_start_sect(struct part_desc *p, struct part_desc *ep) { - unsigned long base; - int inc = (DOS && sectors) ? sectors : 1; - int delta; - - if (ep && p->start + p->size >= ep->start + 1) - delta = p->start - ep->start - inc; - else if (p->start == 0 && p->size > 0) - delta = -inc; - else - delta = 0; - if (delta < 0) { - p->start -= delta; - p->size += delta; - if (is_extended(p->p.sys_type) && boxes == ONESECTOR) - p->size = inc; - else if ((int)(p->size) <= 0) { - warn("no room for partition descriptor\n"); - return 0; - } - } - base = (!ep ? 0 - : (is_extended(p->p.sys_type) ? - outer_extended_partition(ep) : ep)->start); - p->ep = ep; - if (p->p.sys_type == EMPTY_PARTITION && p->size == 0) { - p->p.start_sect = 0; - p->p.begin_chs = zero_chs; - p->p.end_chs = zero_chs; - } else { - p->p.start_sect = p->start - base; - p->p.begin_chs = ulong_to_chs(p->start); - p->p.end_chs = ulong_to_chs(p->start + p->size - 1); - } - p->p.nr_sects = p->size; - return 1; -} - -/* build the extended partition surrounding a given logical partition */ -int -build_surrounding_extended(struct part_desc *p, struct part_desc *ep, - struct disk_desc *z) { - int inc = (DOS && sectors) ? sectors : 1; - int format = F_SECTOR; - struct part_desc *p0 = &(z->partitions[0]), *eep = ep->ep; - - if (boxes == NESTED) { - ep->start = first_free(ep-p0, 1, eep, format, p->start, z); - ep->size = max_length(ep-p0, 1, eep, format, ep->start, z); - if (ep->start > p->start || ep->start + ep->size < p->start + p->size) { - warn("cannot build surrounding extended partition\n"); - return 0; - } - } else { - ep->start = p->start; - if(boxes == CHAINED) - ep->size = p->size; - else - ep->size = inc; - } - - ep->p.nr_sects = ep->size; - ep->p.bootable = 0; - ep->p.sys_type = EXTENDED_PARTITION; - if (!compute_start_sect(ep, eep) || !compute_start_sect(p, ep)) { - ep->p.sys_type = EMPTY_PARTITION; - ep->size = 0; - return 0; - } - - return 1; -} - -int -read_line(int pno, struct part_desc *ep, char *dev, int interactive, - struct disk_desc *z) { - unsigned char line[1000]; - unsigned char *fields[11]; - int fno, pct = pno%4; - struct part_desc p, *orig; - unsigned long ff, ff1, ul, ml, ml1, def; - int format, lpno, is_extd; - - if (eof || eob) - return -1; - - lpno = index_to_linux(pno, z); - - if (interactive) { - if (pct == 0 && (show_extended || pno == 0)) - warn("\n"); - warn("%8s%d: ", dev, lpno); - } - - /* read input line - skip blank lines when reading from a file */ - do { - fno = read_stdin(fields, line, SIZE(fields), SIZE(line)); - } while(fno == RD_CMD || (fno == 0 && !interactive)); - if (fno == RD_EOF) { - return -1; - } else if (fno > 10 && *(fields[10]) != 0) { - printf("too many input fields\n"); - return 0; - } - - if (fno == 1 && !strcmp(fields[0], ".")) { - eob = 1; - return -1; - } - - /* use specified format, but round to cylinders if F_MEGABYTE specified */ - format = 0; - if (cylindersize && specified_format == F_MEGABYTE) - format = F_CYLINDER; - - orig = (one_only ? &(oldp.partitions[pno]) : 0); - - p = zero_part_desc; - p.ep = ep; - - /* first read the type - we need to know whether it is extended */ - /* stop reading when input blank (defaults) and all is full */ - is_extd = 0; - if (fno == 0) { /* empty line */ - if (orig && is_extended(orig->p.sys_type)) - is_extd = 1; - ff = first_free(pno, is_extd, ep, format, 0, z); - ml = max_length(pno, is_extd, ep, format, ff, z); - if (ml == 0 && is_extd == 0) { - is_extd = 1; - ff = first_free(pno, is_extd, ep, format, 0, z); - ml = max_length(pno, is_extd, ep, format, ff, z); - } - if (ml == 0 && pno >= 4) { - /* no free blocks left - don't read any further */ - warn("No room for more\n"); - return -1; - } - } - if (fno < 3 || !*(fields[2])) - ul = orig ? orig->p.sys_type : - (is_extd || (pno > 3 && pct == 1 && show_extended)) - ? EXTENDED_PARTITION : LINUX_NATIVE; - else if(!strcmp(fields[2], "L")) - ul = LINUX_NATIVE; - else if(!strcmp(fields[2], "S")) - ul = LINUX_SWAP; - else if(!strcmp(fields[2], "E")) - ul = EXTENDED_PARTITION; - else if(!strcmp(fields[2], "X")) - ul = LINUX_EXTENDED; - else if (get_ul(fields[2], &ul, LINUX_NATIVE, 16)) - return 0; - if (ul > 255) { - warn("Illegal type\n"); - return 0; - } - p.p.sys_type = ul; - is_extd = is_extended(ul); - - /* find start */ - ff = first_free(pno, is_extd, ep, format, 0, z); - ff1 = ff * unitsize(format); - def = orig ? orig->start : (pno > 4 && pct > 1) ? 0 : ff1; - if (fno < 1 || !*(fields[0])) - p.start = def; - else { - if (get_ul(fields[0], &ul, def / unitsize(0), 0)) - return 0; - p.start = ul * unitsize(0); - p.start -= (p.start % unitsize(format)); - } - - /* find length */ - ml = max_length(pno, is_extd, ep, format, p.start / unitsize(format), z); - ml1 = ml * unitsize(format); - def = orig ? orig->size : (pno > 4 && pct > 1) ? 0 : ml1; - if (fno < 2 || !*(fields[1])) - p.size = def; - else { - if (get_ul(fields[1], &ul, def / unitsize(0), 0)) - return 0; - p.size = ul * unitsize(0) + unitsize(format) - 1; - p.size -= (p.size % unitsize(format)); - } - if (p.size > ml1) { - warn("Warning: exceeds max allowable size (%lu)\n", ml1 / unitsize(0)); - if (!force) - return 0; - } - if (p.size == 0 && pno >= 4 && (fno < 2 || !*(fields[1]))) { - warn("Warning: empty partition\n"); - if (!force) - return 0; - } - p.p.nr_sects = p.size; - - if (p.size == 0 && !orig) { - if(fno < 1 || !*(fields[0])) - p.start = 0; - if(fno < 3 || !*(fields[2])) - p.p.sys_type = EMPTY_PARTITION; - } - - if (p.start < ff1 && p.size > 0) { - warn("Warning: bad partition start (earliest %lu)\n", - (ff1 + unitsize(0) - 1) / unitsize(0)); - if (!force) - return 0; - } - - if (fno < 4 || !*(fields[3])) - ul = (orig ? orig->p.bootable : 0); - else if (!strcmp(fields[3], "-")) - ul = 0; - else if (!strcmp(fields[3], "*") || !strcmp(fields[3], "+")) - ul = 0x80; - else { - warn("unrecognized bootable flag - choose - or *\n"); - return 0; - } - p.p.bootable = ul; - - if (ep && ep->p.sys_type == EMPTY_PARTITION) { - if(!build_surrounding_extended(&p, ep, z)) - return 0; - } else - if(!compute_start_sect(&p, ep)) - return 0; - - { longchs aa = chs_to_longchs(p.p.begin_chs), bb; - - if (fno < 5) { - bb = aa; - } else if (fno < 7) { - warn("partial c,h,s specification?\n"); - return 0; - } else if(get_ul(fields[4], &bb.c, aa.c, 0) || - get_ul(fields[5], &bb.h, aa.h, 0) || - get_ul(fields[6], &bb.s, aa.s, 0)) - return 0; - p.p.begin_chs = longchs_to_chs(bb); - } - { longchs aa = chs_to_longchs(p.p.end_chs), bb; - - if (fno < 8) { - bb = aa; - } else if (fno < 10) { - warn("partial c,h,s specification?\n"); - return 0; - } else if(get_ul(fields[7], &bb.c, aa.c, 0) || - get_ul(fields[8], &bb.h, aa.h, 0) || - get_ul(fields[9], &bb.s, aa.s, 0)) - return 0; - p.p.end_chs = longchs_to_chs(bb); - } - - if (pno > 3 && p.size && show_extended && p.p.sys_type != EMPTY_PARTITION - && (is_extended(p.p.sys_type) != (pct == 1))) { - warn("Extended partition not where expected\n"); - if (!force) - return 0; - } - - z->partitions[pno] = p; - if (pno >= z->partno) - z->partno += 4; /* reqd for out_partition() */ - - if (interactive) - out_partition(dev, 0, &(z->partitions[pno]), z); - - return 1; -} - -/* ep either points to the extended partition to contain this one, - or to the empty partition that may become extended or is 0 */ -int -read_partition(char *dev, int interactive, int pno, struct part_desc *ep, - struct disk_desc *z) { - struct part_desc *p = &(z->partitions[pno]); - int i; - - if (one_only) { - *p = oldp.partitions[pno]; - if (one_only_pno != pno) - goto ret; - } else if (!show_extended && pno > 4 && pno%4) - goto ret; - - while (!(i = read_line(pno, ep, dev, interactive, z))) - if (!interactive) - fatal("bad input\n"); - if (i < 0) { - p->ep = ep; - return 0; - } - - ret: - p->ep = ep; - if (pno >= z->partno) - z->partno += 4; - return 1; -} - -void -read_partition_chain(char *dev, int interactive, struct part_desc *ep, - struct disk_desc *z) { - int i, base; - - eob = 0; - while (1) { - base = z->partno; - if (base+4 > SIZE(z->partitions)) { - printf("too many partitions\n"); - break; - } - for (i=0; i<4; i++) - if (!read_partition(dev, interactive, base+i, ep, z)) - return; - for (i=0; i<4; i++) { - ep = &(z->partitions[base+i]); - if (is_extended(ep->p.sys_type) && ep->size) - break; - } - if (i == 4) { - /* nothing found - maybe an empty partition is going - to be extended */ - if (one_only || show_extended) - break; - ep = &(z->partitions[base+1]); - if (ep->size || ep->p.sys_type != EMPTY_PARTITION) - break; - } - } -} - -void -read_input(char *dev, int interactive, struct disk_desc *z) { - int i; - struct part_desc *partitions = &(z->partitions[0]), *ep; - - for (i=0; i < SIZE(z->partitions); i++) - partitions[i] = zero_part_desc; - z->partno = 0; - - if (interactive) - warn(" -Input in the following format; absent fields get a default value. -<start> <size> <type [E,S,L,X,hex]> <bootable [-,*]> <c,h,s> <c,h,s> -Usually you only need to specify <start> and <size> (and perhaps <type>). -"); - eof = 0; - - for (i=0; i<4; i++) - read_partition(dev, interactive, i, 0, z); - for (i=0; i<4; i++) { - ep = partitions+i; - if (is_extended(ep->p.sys_type) && ep->size) - read_partition_chain(dev, interactive, ep, z); - } - add_sector_and_offset(z); -} - -/* - * G. The command line - */ - -static void version(void) { - printf(PROGNAME " version " VERSION " (aeb@cwi.nl, " DATE ")\n"); -} - -static void -usage(void) { - version(); - printf("Usage: - " PROGNAME " [options] device ... -device: something like /dev/hda or /dev/sda -useful options: - -s [or --show-size]: list size of a partition - -c [or --id]: print or change partition Id - -l [or --list]: list partitions of each device - -d [or --dump]: idem, but in a format suitable for later input - -i [or --increment]: number cylinders etc. from 1 instead of from 0 - -uS, -uB, -uC, -uM: accept/report in units of sectors/blocks/cylinders/MB - -T [or --list-types]:list the known partition types - -D [or --DOS]: for DOS-compatibility: waste a little space - -R [or --re-read]: make kernel reread partition table - -N# : change only the partition with number # - -n : do not actually write to disk - -O file : save the sectors that will be overwritten to file - -I file : restore these sectors again - -v [or --version]: print version - -? [or --help]: print this message -dangerous options: - -g [or --show-geometry]: print the kernel's idea of the geometry - -x [or --show-extended]: also list extended partitions on output - or expect descriptors for them on input - -L [or --Linux]: do not complain about things irrelevant for Linux - -q [or --quiet]: suppress warning messages - You can override the detected geometry using: - -C# [or --cylinders #]:set the number of cylinders to use - -H# [or --heads #]: set the number of heads to use - -S# [or --sectors #]: set the number of sectors to use - You can disable all consistency checking with: - -f [or --force]: do what I say, even if it is stupid -"); - exit(1); -} - -static void -activate_usage(char *progn) { - printf("Usage: - %s device list active partitions on device - %s device n1 n2 ... activate partitions n1 ..., inactivate the rest - %s device activate partition n, inactivate the other ones -", progn, progn, PROGNAME " -An"); - exit(1); -} - -static void -unhide_usage(char *progn) { - exit(1); -} - -static char short_opts[] = "cdfgilnqsu:vx?1A::C:DH:I:LN:O:RS:TU::V"; - -#define PRINT_ID 0400 -#define CHANGE_ID 01000 - -static const struct option long_opts[] = { - { "change-id", no_argument, NULL, 'c' + CHANGE_ID }, - { "print-id", no_argument, NULL, 'c' + PRINT_ID }, - { "id", no_argument, NULL, 'c' }, - { "dump", no_argument, NULL, 'd' }, - { "force", no_argument, NULL, 'f' }, - { "show-geometry", no_argument, NULL, 'g' }, - { "increment", no_argument, NULL, 'i' }, - { "list", no_argument, NULL, 'l' }, - { "quiet", no_argument, NULL, 'q' }, - { "show-size", no_argument, NULL, 's' }, - { "unit", required_argument, NULL, 'u' }, - { "version", no_argument, NULL, 'v' }, - { "show-extended", no_argument, NULL, 'x' }, - { "help", no_argument, NULL, '?' }, - { "one-only", no_argument, NULL, '1' }, - { "cylinders", required_argument, NULL, 'C' }, - { "heads", required_argument, NULL, 'H' }, - { "sectors", required_argument, NULL, 'S' }, - { "activate", optional_argument, NULL, 'A' }, - { "DOS", no_argument, NULL, 'D' }, - { "Linux", no_argument, NULL, 'L' }, - { "re-read", no_argument, NULL, 'R' }, - { "list-types", no_argument, NULL, 'T' }, - { "unhide", optional_argument, NULL, 'U' }, - { "no-reread", no_argument, NULL, 160 }, - { "IBM", no_argument, NULL, 161 }, - { "leave-last", no_argument, NULL, 161 }, -/* undocumented flags - not all completely implemented */ - { "in-order", no_argument, NULL, 128 }, - { "not-in-order", no_argument, NULL, 129 }, - { "inside-outer", no_argument, NULL, 130 }, - { "not-inside-outer", no_argument, NULL, 131 }, - { "nested", no_argument, NULL, 132 }, - { "chained", no_argument, NULL, 133 }, - { "onesector", no_argument, NULL, 134 }, - { NULL, 0, NULL, 0 } -}; - -/* default devices to list */ -static struct devd { - char *pref, *letters; -} defdevs[] = { - { "hd", "abcdefgh" }, - { "sd", "abcde" }, - { "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); -void do_fdisk(char *dev); -void do_reread(char *dev); -void do_change_id(char *dev, char *part, char *id); -void do_unhide(char **av, int ac, char *arg); -void do_activate(char **av, int ac, char *arg); - -int total_size; - -int -main(int argc, char **argv) { - char *progn; - int c; - char *dev; - int opt_size = 0; - int opt_out_geom = 0; - int opt_reread = 0; - int activate = 0; - int do_id = 0; - int unhide = 0; - int fdisk = 0; - char *activatearg = 0; - char *unhidearg = 0; - - if (argc < 1) - fatal("no command?\n"); - if ((progn = rindex(argv[0], '/')) == NULL) - progn = argv[0]; - else - progn++; - if (!strcmp(progn, "activate")) - activate = 1; /* equivalent to `fdisk -A' */ -#if 0 /* not important enough to deserve a name */ - else if (!strcmp(progn, "unhide")) - unhide = 1; /* equivalent to `fdisk -U' */ -#endif - else - fdisk = 1; - - while ((c = getopt_long (argc, argv, short_opts, long_opts, NULL)) != -1) { - switch (c) { - case 'f': - force = 1; break; /* does not imply quiet */ - case 'g': - opt_out_geom = 1; break; - case 'i': - increment = 1; break; - case 'c': - case 'c' + PRINT_ID: - case 'c' + CHANGE_ID: - do_id = c; break; - case 'd': - dump = 1; /* fall through */ - case 'l': - opt_list = 1; break; - case 'n': - no_write = 1; break; - case 'q': - quiet = 1; break; - case 's': - opt_size = 1; break; - case 'u': - set_format(*optarg); break; - case 'v': - version(); - exit(0); - case 'x': - show_extended = 1; break; - case 'A': - activatearg = optarg; - activate = 1; break; - case 'C': - specified_cylinders = atoi(optarg); break; - case 'D': - DOS = 1; break; - case 'H': - specified_heads = atoi(optarg); break; - case 'L': - Linux = 1; break; - case 'N': - one_only = atoi(optarg); break; - case 'I': - restore_sector_file = optarg; break; - case 'O': - save_sector_file = optarg; break; - case 'R': - opt_reread = 1; break; - case 'S': - specified_sectors = atoi(optarg); break; - case 'T': - list_types(); - exit(0); - case 'U': - unhidearg = optarg; - unhide = 1; break; - case 'V': - verify = 1; break; - case '?': - default: - usage(); break; - - /* undocumented flags */ - case 128: - partitions_in_order = 1; break; - case 129: - partitions_in_order = 0; break; - case 130: - all_logicals_inside_outermost_extended = 1; break; - case 131: - all_logicals_inside_outermost_extended = 0; break; - case 132: - boxes = NESTED; break; - case 133: - boxes = CHAINED; break; - case 134: - boxes = ONESECTOR; break; - - /* more flags */ - case 160: - no_reread = 1; break; - case 161: - leave_last = 1; break; - } - } - - if (optind == argc && (opt_list || opt_out_geom || opt_size || verify)) { - struct devd *dp; - char *lp; - char device[10]; - - total_size = 0; - - for(dp = defdevs; dp-defdevs < SIZE(defdevs); dp++) { - 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) - do_size(device, 1); - if (opt_list || verify) - do_list(device, 1); - } - } - - if (opt_size) - printf("total: %d blocks\n", total_size); - - exit(exit_status); - } - - if (optind == argc) { - if (activate) - activate_usage(fdisk ? "fdisk -A" : progn); - else if (unhide) - unhide_usage(fdisk ? "fdisk -U" : progn); - else - usage(); - } - - if (opt_list || opt_out_geom || opt_size || verify) { - while (optind < argc) { - if (opt_out_geom) - do_geom(argv[optind], 0); - if (opt_size) - do_size(argv[optind], 0); - if (opt_list || verify) - do_list(argv[optind], 0); - optind++; - } - exit(exit_status); - } - - if (activate) { - do_activate(argv+optind, argc-optind, activatearg); - exit(exit_status); - } - if (unhide) { - do_unhide(argv+optind, argc-optind, unhidearg); - exit(exit_status); - } - if (do_id) { - if ((do_id & PRINT_ID) != 0 && optind != argc-2) - fatal("usage: fdisk --print-id device partition-number\n"); - else if ((do_id & CHANGE_ID) != 0 && optind != argc-3) - fatal("usage: fdisk --change-id device partition-number Id\n"); - else if (optind != argc-3 && optind != argc-2) - fatal("usage: fdisk --id device partition-number [Id]\n"); - do_change_id(argv[optind], argv[optind+1], - (optind == argc-2) ? 0 : argv[optind+2]); - exit(exit_status); - } - - if (optind != argc-1) - fatal("can specify only one device (except with -l or -s)\n"); - dev = argv[optind]; - - if (opt_reread) - do_reread(dev); - else if (restore_sector_file) - restore_sectors(dev); - else - do_fdisk(dev); - - return 0; -} - -/* - * H. Listing the current situation - */ - -int -my_open (char *dev, int rw, int silent) { - int fd, mode; - - mode = (rw ? O_RDWR : O_RDONLY); - fd = open(dev, mode); - if (fd < 0 && !silent) { - perror(dev); - fatal("cannot open %s %s\n", dev, rw ? "read-write" : "for reading"); - } - return fd; -} - -void -do_list (char *dev, int silent) { - int fd; - struct disk_desc *z; - - fd = my_open(dev, 0, silent); - if (fd < 0) - return; - - z = &oldp; - - free_sectors(); - get_cylindersize(dev, fd, dump ? 1 : opt_list ? 0 : 1); - get_partitions(dev, fd, z); - - if (opt_list) - out_partitions(dev, z); - - if (verify) { - if (partitions_ok(z)) - warn("%s: OK\n", dev); - else - exit_status = 1; - } -} - -void -do_geom (char *dev, int silent) { - int fd; - struct hd_geometry g; - - fd = my_open(dev, 0, silent); - if (fd < 0) - return; - - /* get_cylindersize(dev, fd, silent); */ - if (!ioctl(fd, HDIO_GETGEO, &g)) - printf("%s: %d cylinders, %d heads, %d sectors/track\n", - dev, g.cylinders, g.heads, g.sectors); - else - printf("%s: unknown geometry\n", dev); -} - -/* for compatibility with earlier fdisk: provide option -s */ -void -do_size (char *dev, int silent) { - int fd, size; - - fd = my_open(dev, 0, silent); - if (fd < 0) - return; - - if(ioctl(fd, BLKGETSIZE, &size)) { - if(!silent) { - perror(dev); - fatal("BLKGETSIZE ioctl failed for %s\n", dev); - } - return; - } - - size /= 2; /* convert sectors to blocks */ - if (silent) - printf("%s: %9d\n", dev, size); - else - printf("%d\n", size); - - total_size += size; -} - -/* - * Activate: usually one wants to have a single primary partition - * to be active. OS/2 fdisk makes non-bootable logical partitions - * active - I don't know what that means to OS/2 Boot Manager. - * - * Call: activate /dev/hda 2 5 7 make these partitions active - * and the remaining ones inactive - * Or: fdisk -A /dev/hda 2 5 7 - * - * If only a single partition must be active, one may also use the form - * fdisk -A2 /dev/hda - * - * With "activate /dev/hda" or "fdisk -A /dev/hda" the active partitions - * are listed but not changed. To get zero active partitions, use - * "activate /dev/hda none" or "fdisk -A /dev/hda none". - * Use something like `echo ",,,*" | fdisk -N2 /dev/hda' to only make - * /dev/hda2 active, without changing other partitions. - * - * A warning will be given if after the change not precisely one primary - * partition is active. - * - * The present syntax was chosen to be (somewhat) compatible with the - * activate from the LILO package. - */ -void -set_active (struct disk_desc *z, char *pnam) { - int pno; - - pno = asc_to_index(pnam, z); - z->partitions[pno].p.bootable = 0x80; -} - -void -do_activate (char **av, int ac, char *arg) { - char *dev = av[0]; - int fd; - int rw, i, pno, lpno; - struct disk_desc *z; - - z = &oldp; - - rw = (!no_write && (arg || ac > 1)); - fd = my_open(dev, rw, 0); - - free_sectors(); - get_cylindersize(dev, fd, 1); - get_partitions(dev, fd, z); - - if (!arg && ac == 1) { - /* list active partitions */ - for (pno=0; pno < z->partno; pno++) { - if (z->partitions[pno].p.bootable) { - lpno = index_to_linux(pno, z); - if (pno == linux_to_index(lpno, z)) - printf("%s%d\n", dev, lpno); - else - printf("%s#%d\n", dev, pno); - if (z->partitions[pno].p.bootable != 0x80) - warn("bad active byte: 0x%x instead of 0x80\n", - z->partitions[pno].p.bootable); - } - } - } else { - /* clear `active byte' everywhere */ - for (pno=0; pno < z->partno; pno++) - z->partitions[pno].p.bootable = 0; - - /* then set where desired */ - if (ac == 1) - set_active(z, arg); - else for(i=1; i<ac; i++) - set_active(z, av[i]); - - /* then write to disk */ - if(write_partitions(dev, fd, z)) - warn("Done\n\n"); - else - exit_status = 1; - } - i = 0; - for (pno=0; pno < z->partno && pno < 4; pno++) - if (z->partitions[pno].p.bootable) - i++; - if (i != 1) - warn("You have %d active primary partitions. This does not matter for LILO,\n" - "but the DOS MBR will only boot a disk with 1 active partition.\n", i); -} - -void -set_unhidden (struct disk_desc *z, char *pnam) { - int pno; - unsigned char id; - - pno = asc_to_index(pnam, z); - id = z->partitions[pno].p.sys_type; - if (id == 0x11 || id == 0x14 || id == 0x16 || id == 0x17) - id -= 0x10; - else - fatal("partition %s has id %x and is not hidden\n", pnam, id); - z->partitions[pno].p.sys_type = id; -} - -/* - * maybe remove and make part of --change-id - */ -void -do_unhide (char **av, int ac, char *arg) { - char *dev = av[0]; - int fd, rw, i; - struct disk_desc *z; - - z = &oldp; - - rw = !no_write; - fd = my_open(dev, rw, 0); - - free_sectors(); - get_cylindersize(dev, fd, 1); - get_partitions(dev, fd, z); - - /* unhide where desired */ - if (ac == 1) - set_unhidden(z, arg); - else for(i=1; i<ac; i++) - set_unhidden(z, av[i]); - - /* then write to disk */ - if(write_partitions(dev, fd, z)) - warn("Done\n\n"); - else - exit_status = 1; -} - -void do_change_id(char *dev, char *pnam, char *id) { - int fd, rw, pno; - struct disk_desc *z; - unsigned long i; - - z = &oldp; - - rw = !no_write; - fd = my_open(dev, rw, 0); - - free_sectors(); - get_cylindersize(dev, fd, 1); - get_partitions(dev, fd, z); - - pno = asc_to_index(pnam, z); - if (id == 0) { - printf("%x\n", z->partitions[pno].p.sys_type); - return; - } - i = strtoul(id, NULL, 16); - if (i > 255) - fatal("Bad Id %x\n", i); - z->partitions[pno].p.sys_type = i; - - if(write_partitions(dev, fd, z)) - warn("Done\n\n"); - else - exit_status = 1; -} - -void -do_reread(char *dev) { - int fd; - - fd = my_open(dev, 0, 0); - if(reread_ioctl(fd)) - printf("This disk is currently in use.\n"); -} - -/* - * I. Writing the new situation - */ - -void -do_fdisk(char *dev){ - int fd; - int c, answer; - struct stat statbuf; - int interactive = isatty(0); - struct disk_desc *z; - - if (stat(dev, &statbuf) < 0) { - perror(dev); - fatal("Fatal error: cannot find %s\n", dev); - } - if (!S_ISBLK(statbuf.st_mode)) { - warn("Warning: %s is not a block device\n", dev); - } - fd = my_open(dev, !no_write, 0); - - if(!no_write && !no_reread) { - warn("Checking that no-one is using this disk right now ...\n"); - if(reread_ioctl(fd)) { - printf(" -This disk is currently in use - repartitioning is probably a bad idea. -Umount all file systems, and swapoff all swap partitions on this disk. -Use the --no-reread flag to suppress this check.\n"); - if (!force) { - printf("Use the --force flag to overrule all checks.\n"); - exit(1); - } - } else - warn("OK"); - } - - z = &oldp; - - free_sectors(); - get_cylindersize(dev, fd, 0); - get_partitions(dev, fd, z); - - printf("Old situation:\n"); - out_partitions(dev, z); - - if (one_only && (one_only_pno = linux_to_index(one_only, z)) < 0) - fatal("Partition %d does not exist, cannot change it\n", one_only); - - z = &newp; - - while(1) { - - read_input(dev, interactive, z); - - printf("New situation:\n"); - out_partitions(dev, z); - - if (!partitions_ok(z) && !force) { - if(!interactive) - fatal("I don't like these partitions - nothing changed.\n" - "(If you really want this, use the --force option.)\n"); - else - printf("I don't like this - probably you should answer No\n"); - } - ask: - if (interactive) { - if (no_write) - printf("Are you satisfied with this? [ynq] "); - else - printf("Do you want to write this to disk? [ynq] "); - answer = c = getchar(); - while (c != '\n' && c != EOF) - c = getchar(); - if (c == EOF) - printf("\nfdisk: premature end of input\n"); - if (c == EOF || answer == 'q' || answer == 'Q') { - fatal("Quitting - nothing changed\n"); - } else if (answer == 'n' || answer == 'N') { - continue; - } else if (answer == 'y' || answer == 'Y') { - break; - } else { - printf("Please answer one of y,n,q\n"); - goto ask; - } - } else - break; - } - - if(write_partitions(dev, fd, z)) - printf("Successfully wrote the new partition table\n\n"); - else - exit_status = 1; - - reread_disk_partition(dev, fd); - - warn("If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)\n" - "to zero the first 512 bytes: dd if=/dev/zero of=/dev/foo7 bs=512 count=1\n" - "(See fdisk(8).)\n"); - - sync(); /* superstition */ - sleep(3); - exit(exit_status); -} diff --git a/disk-utils/sfdisk.examples b/disk-utils/sfdisk.examples deleted file mode 100644 index 13e671d48..000000000 --- a/disk-utils/sfdisk.examples +++ /dev/null @@ -1,264 +0,0 @@ -Examples of the use of sfdisk 3.0 (to partition a disk) -Input lines have fields <start>,<size>,<type>... - see sfdisk.8. -Usually no <start> is given, and input lines start with a comma. - -Before doing anything with a disk, make sure it is not in use; -unmount all its file systems, and say swapoff to its swap partitions. -(The final BLKRRPART ioctl will fail if anything else still uses -the disk, and you will have to reboot. It is easier to first make -sure that nothing uses the disk, e.g., by testing: - % umount /dev/sdb1 - % sfdisk -R /dev/sdb - BLKRRPART: Device or resource busy - * Device busy for revalidation (usage=2) - % swapoff /dev/sdb3 - % sfdisk -R /dev/sdb - * sdb: sdb1 < sdb5 sdb6 > sdb3 - % -Note that the starred messages are kernel messages, that may be -logged somewhere, or written to some other console. -In sfdisk 3.01 sfdisk automatically does this check, unless told not to.) - -1. One big partition: - sfdisk /dev/hda << EOF - ; - EOF - -(If there was garbage on the disk before, you may get error messages -like: `ERROR: sector 0 does not have an msdos signature' -and `/dev/hda: unrecognized partition'. This does not matter -if you write an entirely fresh partition table anyway.) - -The output will be: ------------------------------------------------------------------------ -Old situation: -... -New situation: -Units = cylinders of 208896 bytes, blocks of 1024 bytes, counting from 0 - - Device Boot Start End #cyls #blocks Id System -/dev/hda1 0+ 1023 1024- 208895+ 83 Linux native -Successfully wrote the new partition table - hda: hda1 ------------------------------------------------------------------------ -Writing and rereading the partition table takes a few seconds - -don't be alarmed if nothing happens for six seconds or so. - - -2. Three primary partitions: two of size 50MB and the rest: - sfdisk /dev/hda -uM << EOF - ,50 - ,50 - ; - EOF ------------------------------------------------------------------------ -New situation: -Units = megabytes of 1048576 bytes, blocks of 1024 bytes, counting from 0 - - Device Boot Start End MB #blocks Id System -/dev/hda1 0+ 50- 51- 51203+ 83 Linux native -/dev/hda2 50+ 100- 51- 51204 83 Linux native -/dev/hda3 100+ 203 104- 106488 83 Linux native -Successfully wrote the new partition table - hda: hda1 hda2 hda3 ------------------------------------------------------------------------ -/dev/hda1 is one block (in fact only half a block) shorter than -/dev/hda2 because its start had to be shifted away from zero in -order to leave room for the Master Boot Record (MBR). - - -3. A 1MB OS2 Boot Manager partition, a 50MB DOS partition, - and three extended partitions (DOS D:, Linux swap, Linux): - sfdisk /dev/hda -uM << EOF - ,1,a - ,50,6 - ,,E - ; - ,20,4 - ,16,S - ; - EOF ------------------------------------------------------------------------ - Device Boot Start End MB #blocks Id System -/dev/hda1 0+ 1- 2- 1223+ a OS/2 Boot Manager -/dev/hda2 1+ 51- 51- 51204 6 DOS 16-bit FAT >=32M -/dev/hda3 51+ 203 153- 156468 5 Extended -/dev/hda4 0 - 0 0 0 Empty -/dev/hda5 51+ 71- 21- 20603+ 4 DOS 16-bit FAT <32M -/dev/hda6 71+ 87- 17- 16523+ 82 Linux swap -/dev/hda7 87+ 203 117- 119339+ 83 Linux native -Successfully wrote the new partition table - hda: hda1 hda2 hda3 < hda5 hda6 hda7 > ------------------------------------------------------------------------ -All these rounded numbers look better in cylinder units: - % sfdisk -l /dev/hda ------------------------------------------------------------------------ - Device Boot Start End #cyls #blocks Id System -/dev/hda1 0+ 5 6- 1223+ a OS/2 Boot Manager -/dev/hda2 6 256 251 51204 6 DOS 16-bit FAT >=32M -/dev/hda3 257 1023 767 156468 5 Extended -/dev/hda4 0 - 0 0 0 Empty -/dev/hda5 257+ 357 101- 20603+ 4 DOS 16-bit FAT <32M -/dev/hda6 358+ 438 81- 16523+ 82 Linux swap -/dev/hda7 439+ 1023 585- 119339+ 83 Linux native ------------------------------------------------------------------------ -But still - why does /dev/hda5 not start on a cylinder boundary? -Because it is contained in an extended partition that does. -Of the chain of extended partitions, usually only the first is -shown. (The others have no name under Linux anyway.) But -these additional extended partitions can be made visible: - % sfdisk -l -x /dev/hda ------------------------------------------------------------------------ - Device Boot Start End #cyls #blocks Id System -/dev/hda1 0+ 5 6- 1223+ a OS/2 Boot Manager -/dev/hda2 6 256 251 51204 6 DOS 16-bit FAT >=32M -/dev/hda3 257 1023 767 156468 5 Extended -/dev/hda4 0 - 0 0 0 Empty - -/dev/hda5 257+ 357 101- 20603+ 4 DOS 16-bit FAT <32M - - 358 1023 666 135864 5 Extended - - 257 256 0 0 0 Empty - - 257 256 0 0 0 Empty - -/dev/hda6 358+ 438 81- 16523+ 82 Linux swap - - 439 1023 585 119340 5 Extended - - 358 357 0 0 0 Empty - - 358 357 0 0 0 Empty - -/dev/hda7 439+ 1023 585- 119339+ 83 Linux native - - 439 438 0 0 0 Empty - - 439 438 0 0 0 Empty - - 439 438 0 0 0 Empty ------------------------------------------------------------------------ - -Why the empty 4th input line? The description of the extended partitions -starts after that of the four primary partitions. -You force an empty partition with a ",0" input line, but here all -space was divided already, so the fourth partition became empty -automatically. - -How did I know about 4,6,a,E,S? Well, E,S,L stand for Extended, -Swap and Linux. The other values are hexadecimal and come from -the table: - % sfdisk -T - Id Name - - 0 Empty - 1 DOS 12-bit FAT - 2 XENIX root - 3 XENIX usr - 4 DOS 16-bit FAT <32M - 5 Extended - 6 DOS 16-bit FAT >=32M - 7 OS/2 HPFS or QNX or Advanced UNIX - 8 AIX data - 9 AIX boot or Coherent - a OS/2 Boot Manager - ... - - -4. Preserving the sectors changed by sfdisk. - % sfdisk -O save-hdd-partition-sectors /dev/hda - ... - will write the sectors overwritten by sfdisk to file. - If you notice that you trashed some partition, you may - be able to restore things by - % sfdisk -I save-hdd-partition-sectors /dev/hda - % - -5. Preserving some old partitions. - % sfdisk -N2 /dev/hda - ... - will only change the partition /dev/hda2, and leave the rest - unchanged. The most obvious application is to change an Id: - % sfdisk -N7 /dev/hda - ,,63 - % ------------------------------------------------------------------------ -Old situation: - - Device Boot Start End #cyls #blocks Id System -/dev/hda1 0+ 5 6- 1223+ a OS/2 Boot Manager -... -/dev/hda6 358+ 438 81- 16523+ 82 Linux swap -/dev/hda7 439+ 1023 585- 119339+ 83 Linux native - -New situation: - - Device Boot Start End #cyls #blocks Id System -/dev/hda1 0+ 5 6- 1223+ a OS/2 Boot Manager -... -/dev/hda6 358+ 438 81- 16523+ 82 Linux swap -/dev/hda7 439+ 1023 585- 119339+ 63 GNU HURD ------------------------------------------------------------------------ - Note that changing a logical partition into an empty partition - will decrease the number of all subsequent logical partitions. - -6. Deleting a partition. -At first I thought of having an option -X# for deleting partitions, -but there are several ways in which a partition can be deleted, and -it is probably better to handle this just as a general change. - % sfdisk -d /dev/hda > ohda -will write the current tables on the file `ohda'. ------------------------------------------------------------------------ -% cat ohda -# partition table of /dev/hda -unit: sectors - -/dev/hda1 : start= 1, size= 40799, Id= 5 -/dev/hda2 : start= 40800, size= 40800, Id=83 -/dev/hda3 : start= 81600, size= 336192, Id=83 -/dev/hda4 : start= 0, size= 0, Id= 0 -/dev/hda5 : start= 2, size= 40798, Id=83 ------------------------------------------------------------------------ -In order to delete the partition on /dev/hda3, edit this file -and feed the result to sfdisk again. ------------------------------------------------------------------------ -% emacs ohda -% cat ohda -# partition table of /dev/hda -unit: sectors - -/dev/hda1 : start= 1, size= 40799, Id= 5 -/dev/hda2 : start= 40800, size= 40800, Id=83 -/dev/hda3 : start= 0, size= 0, Id= 0 -/dev/hda4 : start= 0, size= 0, Id= 0 -/dev/hda5 : start= 2, size= 40798, Id=83 -% sfdisk /dev/hda < ohda -Old situation: -Units = cylinders of 208896 bytes, blocks of 1024 bytes, counting from 0 - - Device Boot Start End #cyls #blocks Id System -/dev/hda1 0+ 99 100- 20399+ 5 Extended -/dev/hda2 100 199 100 20400 83 Linux native -/dev/hda3 200 1023 824 168096 83 Linux native -/dev/hda4 0 - 0 0 0 Empty -/dev/hda5 0+ 99 100- 20399 83 Linux native -New situation: -Units = sectors of 512 bytes, counting from 0 - - Device Boot Start End #sectors Id System -/dev/hda1 1 40799 40799 5 Extended -/dev/hda2 40800 81599 40800 83 Linux native -/dev/hda3 0 - 0 0 Empty -/dev/hda4 0 - 0 0 Empty -/dev/hda5 2 40799 40798 83 Linux native -Successfully wrote the new partition table -% sfdisk -l -V /dev/hda - -Disk /dev/hda: 12 heads, 34 sectors, 1024 cylinders -Units = cylinders of 208896 bytes, blocks of 1024 bytes, counting from 0 - - Device Boot Start End #cyls #blocks Id System -/dev/hda1 0+ 99 100- 20399+ 5 Extended -/dev/hda2 100 199 100 20400 83 Linux native -/dev/hda3 0 - 0 0 0 Empty -/dev/hda4 0 - 0 0 0 Empty -/dev/hda5 0+ 99 100- 20399 83 Linux native -/dev/hda: OK ------------------------------------------------------------------------ -This is a good way of making changes: dump the current status -to file, edit the file, and feed it to sfdisk. -Preserving the file on some other disk could be useful: -if ever the MBR gets thrashed it can be used to restore -the old situation. |