Notes on the libfdisk library (as of June 18, 1997) --------------------------------------------------- Contents -------- (1) Background Information on Partitioning (2) Libfdisk Programming Notes Section 1 - Background Information on Partitioning --------------------------------------------------- Hard drives are normally partitioned which each serve a different function (root, /usr, /tmp, /var, etc). There are some basic facts one needs to be aware of before writing software to manipulate these partitions. Some quick terminology: Geometry - describes the logical layout of data on a hard drive, in terms of cylinders, heads, and sectors. Cylinder - fundamental unit to control size of a partition Head - there are several heads per cylinder Sector - basic component of a hard drive, made of 512 bytes Partition - subcomponent of a hard drive, composed of a whole number of cylinders. Partition Table - A partition table can hold 4 partition definitions Master Boot Record (MBR) - The first partition table on a drive occurs are sector 1, head 0, cylinder 0, the first sector on the disk. It contains a boot loader as well. Primary Partition - the 4 partitions in the MBR are the primary partitions. Extended Partition - To get past the limitation of 4 primary partitions, and extended partition is created. It can contains an unlimited number of logical partitions. Logical Partition - Just like a normal partition, except it is located in an extended partition. Some basic rules/facts: Partitions are defined by a partition table, which consists of the last 66 bytes of a sector. The first part of the sector can possibly contain a boot loader. The MBR always contains a boot loader, normally created by LILO. The partition table in the MBR defines the 4 primary partitions. These are numbered '1' through '4'. A partition table entry looks like (in libfdisk the type is RawPartition) struct RawPartition { unsigned char active; unsigned char start_head; unsigned char start_sec; unsigned char start_cyl; unsigned char type; unsigned char end_head; unsigned char end_sec; unsigned char end_cyl; unsigned int start; unsigned int size; }; The fields are: active - if 0x80, DOS will boot from this partition. 0 otherwise. start_head -\ start_sec -|---- Define start of partition start_cyl -/ end_head -\ end_sec -|---- Define end of partition end_cyl -/ start - 'linear' sector of start of partition size - partition size in sectors Of note - The start cylinder is actually 10 bits, two of which are stored in the up 2 bits of the sector. So the range of values for each component is 1 <= sector <= 63 0 <= heads <= 255 0 <= cylinder <= 1023 Note that sectors start with 1, not zero. This is historical. Note also that IDE drives can only accept a head up to 63, so this limits the range of heads you can send to the drive. One of the primary partitions can of type 5, which means it is an extended partition. This is like a normal primary partition, except at the start of it is a partition table. This table defines how the space WITHIN the expended partition is partitioned. It can contain another extended partition, etc etc. These extended partitions form a linked list. The non-extended partitions within extended partitions are called 'logical' partition. They are numbered suequentially in the linked list starting from '5'. To understand this, here is the example output from the command 'fdisk -l': Disk /dev/hdb: 64 heads, 63 sectors, 620 cylinders Units = cylinders of 4032 * 512 bytes Device Boot Begin Start End Blocks Id System /dev/hdb1 1 1 51 102784+ 83 Linux native /dev/hdb2 52 52 84 66528 82 Linux swap /dev/hdb3 85 85 620 1080576 5 Extended /dev/hdb5 85 85 288 411232+ 83 Linux native /dev/hdb6 289 289 542 512032+ 83 Linux native /dev/hdb7 543 543 620 157216+ 83 Linux native This disk has a geometry of 64 heads, 63 sectors, 620 cylinders. Partitions are defined in terms of cylinders, which are 64 heads/cyl * 63 sect/head, or 4032 sectors each. There are 3 primary partitions, one of which is an extended partition. There are 3 logical partitions as well. Graphically, the disks looks like: [PT = Partition Table, MBR = Master Boot Record] Sector # ---------------------------------- 0 |MBR PT| |--------------------------------| | | ~ ~ | | 63 |--------------------------------| /dev/hdb1 | | | Primary partition, type 83 | | | ~ ~ ~ ~ | | 205632 |--------------------------------| /dev/hdb2 | | | Primary partition, type 82 | | | ~ ~ ~ ~ | | 338688 |--------------------------------| /dev/hdb3 ------------- | PT| ^ |--------------------------------| | ~ ~ | | | | 338751 |--------------------------------| /dev/hdb5 | | | | | Logical partition, type 83 | | | | | ~ ~ | ~ ~ | | | | 1161216 |--------------------------------| --------- | | PT | ^ E |--------------------------------| | x ~ ~ | t | | | e 1161279 |--------------------------------| /dev/hdb6 | n | | E d | Logical partition, type 83 | x e | | t d ~ ~ e | ~ ~ n | | | d | | | e | 2185344 |--------------------------------| --- d | | PT | ^ | | |--------------------------------| | | | ~ ~ E | | | | x | | 2185407 |--------------------------------| /dev/hdb7 t | | | | e | | | Logical partition, type 83 | n | | ~ ~ d | | ~ ~ e | | | | d | | | | | | | | | V V V end of disk |--------------------------------| ------------- Note that the three extended partitions are nested within each other. ---------- End of Section 1------------------------ Section 2 - Libfdisk Programming Notes --------------------------------------------------- Data Types (libfdisk.h): ------------------------- These are mostly internal use only: RawPartition - exact representation of entry in partition table RawPartitionTable - 4 RawPartition's These apps usually use: Partition - abstracted representation of a partition. Apps should normally use this, not RawPartition PartitionTable - Holds 4 Partition's plus other data ExtendedPartitionTable - Holds contents of an extended partiton HardDrive - completely describes hard drive Functions: ---------- In general, these routines return 0 on success. A value < 0 means a serious error occurred and errno has the error. Values > 0 mean an libfdisk error occurred, like you passed a logical partition number < 5. There should be a standard list of these errors, but this does not exist yet. Read the function to see how it is done. Raw low level i/o (rawio.[ch]) ----------------------------------- These routines should not generally be used by an application, with these exceptions: fdiskOpenDevice(char *name, HardDrive **hd) fdiskCloseDevice(HardDrive *hd) These open a device and create a HardDrive structure describing it. This HardDrive structure will be used by the programmer for practically all other function calls in libfdisk. fdiskOpenDevice MUST be called before you can do anything else! Other functions are: fdiskSectorToCHS() - convert absolute sector num to cyl/head/sector fdiskReadPartitionTable () -| fdiskWritePartitionTable () -+-- read/write a RawPartitionTable to disk fdiskReadMBR () -| fdiskWriteBR () -+-- read/write the MBR RawPartitionTable to disk fdiskSetAttrPrimary() - set various attributes of a primary partition fdiskRemovePrimary() - remove primary partition from disk Extended Partition Ops (extended.[ch]) ------------------------------------------- These routines manipulate extended partitions. The primary partitions are defined in a statically allocated structure in the HardDrive data type, whereas extended partitions form a linked list rooted at the HardDrive data type. These routines should not generally be called by an application. fdiskIsExtended() - returns 1 if partition type is extended, 0 otherwise fdiskInsertExtended() - insert extended partition into linked link fdiskRemoveExtended() - remove "" "" from "" "" fdiskRenumberLogical() - go thru linked list, number partitions sequentially fdiskInsertLogical() - add logical partition to given extended partition fdiskRemoveLogical() - remove "" "" from "" "" "" fdiskSetAttrLogical() - set attributes of selected logical partition fdiskFindLogical() - find a given logical partition (>=5) in linked list. User Operations ---------------------- These operations are what and app should generally be using. They use partition #'s, which are 1-4 for primary partitions, and >=5 for logical partitions. These operations attempt to hide the difference between extended and primary partitions. These application just manipulates the number, location, and sizes of a list of partitions. When the manipulation is finished, the application can then dump the new configuration to disk. fdiskReadPartitions() -| fdiskWritePartitions() -+-- Read/Write all partitions from a disk fdiskInsertPartition() -| fdiskRemovePartition() -+-- Insert/Remove a partition from disk fdiskSetAttrPartition() - change attributes of a partition Following need to be written: fdiskVerifyPartitions() - do a check that current table makes sense fdiskPrintPartitions() - output string buffer of current partitions fdiskPartitionType() - convert partition type to a human read. string