diff options
Diffstat (limited to 'fdisk')
-rw-r--r-- | fdisk/.gitignore | 3 | ||||
-rw-r--r-- | fdisk/Makefile.am | 94 | ||||
-rw-r--r-- | fdisk/cfdisk.8 | 452 | ||||
-rw-r--r-- | fdisk/cfdisk.c | 2854 | ||||
-rw-r--r-- | fdisk/common.h | 15 | ||||
-rw-r--r-- | fdisk/fdisk.8 | 283 | ||||
-rw-r--r-- | fdisk/fdisk.c | 2116 | ||||
-rw-r--r-- | fdisk/fdisk.h | 253 | ||||
-rw-r--r-- | fdisk/fdiskaixlabel.c | 67 | ||||
-rw-r--r-- | fdisk/fdiskaixlabel.h | 27 | ||||
-rw-r--r-- | fdisk/fdiskbsdlabel.c | 847 | ||||
-rw-r--r-- | fdisk/fdiskbsdlabel.h | 246 | ||||
-rw-r--r-- | fdisk/fdiskdoslabel.c | 682 | ||||
-rw-r--r-- | fdisk/fdiskdoslabel.h | 57 | ||||
-rw-r--r-- | fdisk/fdiskmaclabel.c | 83 | ||||
-rw-r--r-- | fdisk/fdiskmaclabel.h | 39 | ||||
-rw-r--r-- | fdisk/fdisksgilabel.c | 879 | ||||
-rw-r--r-- | fdisk/fdisksgilabel.h | 137 | ||||
-rw-r--r-- | fdisk/fdisksunlabel.c | 643 | ||||
-rw-r--r-- | fdisk/fdisksunlabel.h | 97 | ||||
-rw-r--r-- | fdisk/gpt.c | 216 | ||||
-rw-r--r-- | fdisk/gpt.h | 8 | ||||
-rw-r--r-- | fdisk/i386_sys_types.c | 110 | ||||
-rw-r--r-- | fdisk/partname.c | 49 | ||||
-rw-r--r-- | fdisk/sfdisk.8 | 603 | ||||
-rw-r--r-- | fdisk/sfdisk.c | 3242 | ||||
-rw-r--r-- | fdisk/utils.c | 290 |
27 files changed, 0 insertions, 14392 deletions
diff --git a/fdisk/.gitignore b/fdisk/.gitignore deleted file mode 100644 index c20d140e7..000000000 --- a/fdisk/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -cfdisk -fdisk -sfdisk diff --git a/fdisk/Makefile.am b/fdisk/Makefile.am deleted file mode 100644 index e9be84111..000000000 --- a/fdisk/Makefile.am +++ /dev/null @@ -1,94 +0,0 @@ -include $(top_srcdir)/config/include-Makefile.am - -fdisk_common = \ - common.h \ - gpt.c \ - gpt.h \ - i386_sys_types.c \ - $(top_srcdir)/lib/blkdev.c \ - $(top_srcdir)/lib/mbsalign.c \ - $(top_srcdir)/lib/strutils.c \ - $(top_srcdir)/lib/randutils.c \ - $(top_srcdir)/lib/wholedisk.c - -if LINUX -fdisk_common += $(top_srcdir)/lib/linux_version.c -endif - -if !ARCH_M68K - -sbin_PROGRAMS = fdisk -dist_man_MANS = fdisk.8 -fdisk_SOURCES = \ - utils.c \ - fdisk.c \ - fdisk.h \ - fdiskaixlabel.c \ - fdiskaixlabel.h \ - fdiskbsdlabel.c \ - fdiskbsdlabel.h \ - fdiskmaclabel.c \ - fdiskmaclabel.h \ - fdisksgilabel.c \ - fdisksgilabel.h \ - fdisksunlabel.c \ - fdisksunlabel.h \ - fdiskdoslabel.c \ - fdiskdoslabel.h \ - partname.c \ - $(fdisk_common) \ - $(top_srcdir)/lib/canonicalize.c - -cflags_blkid = $(AM_CFLAGS) -ldadd_blkid = - -if BUILD_LIBBLKID -ldadd_blkid += $(ul_libblkid_la) -cflags_blkid += -I$(ul_libblkid_incdir) -endif - -if HAVE_STATIC_FDISK -sbin_PROGRAMS += fdisk.static -fdisk_static_SOURCES = $(fdisk_SOURCES) -fdisk_static_LDFLAGS = -all-static -fdisk_static_CFLAGS = $(cflags_blkid) -fdisk_static_LDADD = $(ldadd_blkid) -endif - -fdisk_CFLAGS = $(cflags_blkid) -fdisk_LDADD = $(ldadd_blkid) - -if !ARCH_SPARC - -sbin_PROGRAMS += sfdisk -dist_man_MANS += sfdisk.8 -sfdisk_SOURCES = \ - partname.c \ - sfdisk.c \ - $(fdisk_common) \ - $(top_srcdir)/lib/canonicalize.c - -if HAVE_STATIC_SFDISK -sbin_PROGRAMS += sfdisk.static -sfdisk_static_SOURCES = $(sfdisk_SOURCES) -sfdisk_static_LDFLAGS = -all-static -endif - -if USE_SLANG -sbin_PROGRAMS += cfdisk -dist_man_MANS += cfdisk.8 -cfdisk_SOURCES = cfdisk.c $(fdisk_common) -cfdisk_CFLAGS = $(cflags_blkid) -cfdisk_LDADD = -lslang $(ldadd_blkid) -else -if HAVE_NCURSES -sbin_PROGRAMS += cfdisk -dist_man_MANS += cfdisk.8 -cfdisk_SOURCES = cfdisk.c $(fdisk_common) -cfdisk_CFLAGS = $(cflags_blkid) -cfdisk_LDADD = @NCURSES_LIBS@ $(ldadd_blkid) -endif -endif - -endif # !ARCH_SPARC -endif # !ARCH_M68K diff --git a/fdisk/cfdisk.8 b/fdisk/cfdisk.8 deleted file mode 100644 index 28ddad668..000000000 --- a/fdisk/cfdisk.8 +++ /dev/null @@ -1,452 +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 "July 2009" "util-linux" "System Administration" -.SH NAME -cfdisk \- display or manipulate disk partition table -.SH SYNOPSIS -.B cfdisk -.RB [ \-agvz ] -.RB [ \-c -.IR cylinders ] -.RB [ \-h -.IR heads ] -.RB [ \-s -.IR sectors-per-track ] -.RB [ \-P -.IR opt ] -.RI [ device ] -.SH DESCRIPTION -.B cfdisk -is a curses-based program for partitioning any hard disk drive. -Typical values of the -.I device -argument are: -.sp -.nf -.RS -/dev/hda [default] -/dev/hdb -/dev/sda -/dev/sdb -/dev/sdc -/dev/sdd -.RE -.fi - -Note that -.B cfdisk -does not align partitions to block device I/O limits. This functionality is -provided by -.BR fdisk (8). - -In order to write the partition table -.B cfdisk -needs something called the `geometry' of the disk: the number -of `heads' and the number of `sectors per track'. Linux does not -use any geometry, so if the disk will not be accessed by other -operating systems, you can safely accept the defaults that -.B cfdisk -chooses for you. The geometry used by -.B cfdisk -is found as follows. First the partition table is examined, -to see what geometry was used by the previous program that -changed it. If the partition table is empty, or contains garbage, -or does not point at a consistent geometry, the kernel is -asked for advice. If nothing works 255 heads and 63 sectors/track -is assumed. The geometry can be overridden on the command line -or by use of the `g' command. When partitioning an empty large modern -disk, picking 255 heads and 63 sectors/track is always a good idea. -There is no need to set the number of cylinders, since -.B cfdisk -knows the disk size. - -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 asterisk -.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 -to 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 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 displayed 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 partitions' 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 asterisk -.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 does not -work in some cases, for example for device-mapper devices. In -particular case you need to inform kernel about new -partitions by -.B partprobe(8), -.B kpartx(8) -or reboot the system. -.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 \-g -Do not use the geometry given by the disk driver, but try to -guess a geometry from the partition table. -.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 "EXIT STATUS" -0: No errors; 1: Invocation error; 2: I/O error; -3: cannot get geometry; 4: bad partition table on disk. -.SH "SEE ALSO" -.BR fdisk (8), -.BR sfdisk (8), -.BR mkfs (8), -.BR parted (8), -.BR partprobe (8), -.BR kpartx(8) -.SH BUGS -The current version does not support multiple disks. -.SH AUTHOR -Kevin E. Martin (martin@cs.unc.edu) - -.SH AVAILABILITY -The cfdisk command is part of the util-linux package and is available from -ftp://ftp.kernel.org/pub/linux/utils/util-linux/. diff --git a/fdisk/cfdisk.c b/fdisk/cfdisk.c deleted file mode 100644 index 967a1034c..000000000 --- a/fdisk/cfdisk.c +++ /dev/null @@ -1,2854 +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 this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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-p: aeb@cwi.nl - * Rebaptised 2.9p, following util-linux versioning. - * - * Recognition of NTFS / HPFS difference inspired by patches - * from Marty Leisner <leisner@sdsp.mc.xerox.com> - * Exit codes by Enrique Zanardi <ezanardi@ull.es>: - * 0: all went well - * 1: command line error, out of memory - * 2: hardware problems [Cannot open/seek/read/write disk drive]. - * 3: ioctl(fd, HDIO_GETGEO,...) failed. (Probably it is not a disk.) - * 4: bad partition table on disk. [Bad primary/logical partition]. - * - * Sat, 23 Jan 1999 19:34:45 +0100 <Vincent.Renardias@ldsol.com> - * Internationalized + provided initial French translation. - * Sat Mar 20 09:26:34 EST 1999 <acme@conectiva.com.br> - * Some more i18n. - * Sun Jul 18 03:19:42 MEST 1999 <aeb@cwi.nl> - * Terabyte-sized disks. - * Sat Jun 30 05:23:19 EST 2001 <nathans@sgi.com> - * XFS label recognition. - * Thu Nov 22 15:42:56 CET 2001 <flavio.stanchina@tin.it> - * ext3 and ReiserFS recognition. - * Sun Oct 12 17:43:43 CEST 2003 <flavio.stanchina@tin.it> - * JFS recognition; ReiserFS label recognition. - * - ****************************************************************************/ - -#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 HAVE_SLANG_H -#include <slang.h> -#elif defined(HAVE_SLANG_SLANG_H) -#include <slang/slang.h> -#endif - -#ifdef HAVE_SLCURSES_H -#include <slcurses.h> -#elif defined(HAVE_SLANG_SLCURSES_H) -#include <slang/slcurses.h> -#elif defined(HAVE_NCURSESW_NCURSES_H) && defined(HAVE_WIDECHAR) -#include <ncursesw/ncurses.h> -#elif defined(HAVE_NCURSES_H) -#include <ncurses.h> -#elif defined(HAVE_NCURSES_NCURSES_H) -#include <ncurses/ncurses.h> -#endif - -#include <signal.h> -#include <math.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/ioctl.h> - -#ifdef HAVE_LIBBLKID -#include <blkid.h> -#endif - -#ifdef HAVE_WIDECHAR -#include <wctype.h> -#endif - -#include "closestream.h" -#include "nls.h" -#include "rpmatch.h" -#include "blkdev.h" -#include "strutils.h" -#include "common.h" -#include "gpt.h" -#include "mbsalign.h" -#include "widechar.h" - -#ifdef __GNU__ -#define DEFAULT_DEVICE "/dev/hd0" -#define ALTERNATE_DEVICE "/dev/sd0" -#elif defined(__FreeBSD__) -#define DEFAULT_DEVICE "/dev/ad0" -#define ALTERNATE_DEVICE "/dev/da0" -#else -#define DEFAULT_DEVICE "/dev/hda" -#define ALTERNATE_DEVICE "/dev/sda" -#endif - -/* With K=1024 we have `binary' megabytes, gigabytes, etc. - Some misguided hackers like that. - With K=1000 we have MB and GB that follow the standards - [SI, ATA, IEEE etc] and the disk manufacturers and the law. */ -#define K 1000 - -#define LINE_LENGTH 80 -#define MAXIMUM_PARTS 60 - -#define SECTOR_SIZE 512 - -#define MAX_HEADS 256 -#define MAX_SECTORS 63 - -#define ACTIVE_FLAG 0x80 -#define PART_TABLE_FLAG0 0x55 -#define PART_TABLE_FLAG1 0xAA - -#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 PRI_OR_LOG -1 -#define PRIMARY -2 -#define LOGICAL -3 - -#define COL_ID_WIDTH 25 - -#define ESC '\033' -#define DEL '\177' -#define BELL '\007' -#define REDRAWKEY '\014' /* ^L */ - -/* Display units */ -#define GIGABYTES 1 -#define MEGABYTES 2 -#define SECTORS 3 -#define CYLINDERS 4 - -#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))) - -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 */ -}; - -int heads = 0; -int sectors = 0; -long long cylinders = 0; -int cylinder_size = 0; /* heads * sectors */ -long long actual_size = 0; /* (in 512-byte sectors) - set using ioctl */ - /* explicitly given user values */ -int user_heads = 0, user_sectors = 0; -long long user_cylinders = 0; - /* kernel values; ignore the cylinders */ -int kern_heads = 0, kern_sectors = 0; - /* partition-table derived values */ -int pt_heads = 0, pt_sectors = 0; - - -static void -set_hsc0(unsigned char *h, unsigned char *s, int *c, long long sector) { - *s = sector % sectors + 1; - sector /= sectors; - *h = sector % heads; - sector /= heads; - *c = sector; -} - -static void -set_hsc(unsigned char *h, unsigned char *s, unsigned char *c, - long long sector) { - int cc; - - if (sector >= 1024*cylinder_size) - sector = 1024*cylinder_size - 1; - set_hsc0(h, s, &cc, sector); - *c = cc & 0xFF; - *s |= (cc >> 2) & 0xC0; -} - -static void -set_hsc_begin(struct partition *p, long long sector) { - set_hsc(& p->head, & p->sector, & p->cyl, sector); -} - -static void -set_hsc_end(struct partition *p, long long sector) { - set_hsc(& p->end_head, & p->end_sector, & p->end_cyl, sector); -} - -#define is_extended(x) ((x) == DOS_EXTENDED || (x) == WIN98_EXTENDED || \ - (x) == LINUX_EXTENDED) - -/* start_sect and nr_sects are stored little endian on all machines */ -/* moreover, they are not aligned correctly */ -static 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); -} - -static unsigned int -read4_little_endian(unsigned char *cp) { - return (unsigned int)(cp[0]) + ((unsigned int)(cp[1]) << 8) - + ((unsigned int)(cp[2]) << 16) - + ((unsigned int)(cp[3]) << 24); -} - -static void -set_start_sect(struct partition *p, unsigned int start_sect) { - store4_little_endian(p->start4, start_sect); -} - -static unsigned int -get_start_sect(struct partition *p) { - return read4_little_endian(p->start4); -} - -static void -set_nr_sects(struct partition *p, unsigned int nr_sects) { - store4_little_endian(p->size4, nr_sects); -} - -static unsigned int -get_nr_sects(struct partition *p) { - return read4_little_endian(p->size4); -} - -#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 char magicflag[2]; - } p; -} partition_table; - -typedef struct { - long long first_sector; /* first sector in partition */ - long long last_sector; /* last sector in partition */ - long 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 12 - char fstype[FSTYPESZ+1]; -} partition_info; - -char *disk_device = DEFAULT_DEVICE; -int fd; -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; -long long logical_sectors[MAXIMUM_PARTS]; - -__sighandler_t old_SIGINT, old_SIGTERM; - -int arrow_cursor = FALSE; -int display_units = MEGABYTES; -int zero_table = FALSE; -int use_partition_table_geometry = 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 = 6; -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 = 68; -int COMMAND_LINE_X = 5; - -static void die_x(int ret); -static void draw_screen(void); - -/* Guaranteed alloc */ -static void * -xmalloc (size_t size) { - void *t; - - if (size == 0) - return NULL; - - t = malloc (size); - if (t == NULL) { - fprintf (stderr, _("%s: Out of memory!\n"), "cfdisk"); - die_x(1); - } - return t; -} - -/* Some libc's have their own basename() */ -static char * -my_basename(char *devname) { - char *s = strrchr(devname, '/'); - return s ? s+1 : devname; -} - -static char * -partition_type_name(unsigned char type) { - struct systypes *s = i386_sys_types; - - while(s->name && s->type != type) - s++; - return s->name; -} - -static 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].fstype) - return p_info[i].fstype; - else - return _(partition_type_name(p_info[i].id)); -} - -static void -fdexit(int ret) { - if (opened) { - if (changed) - fsync(fd); - close(fd); - } - if (changed) { - fprintf(stderr, _("Disk has been changed.\n")); -#if 0 - fprintf(stderr, _("Reboot the system to ensure the partition " - "table is correctly updated.\n")); -#endif - - 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); -} - -/* - * Note that @len is size of @str buffer. - * - * Returns number of read bytes (without \0). - */ -static int -get_string(char *str, int len, char *def) { - size_t cells = 0; - ssize_t i = 0; - int x, y; - int use_def = FALSE; - wint_t c; - - getyx(stdscr, y, x); - clrtoeol(); - - str[i] = 0; - - if (def != NULL) { - mvaddstr(y, x, def); - move(y, x); - use_def = TRUE; - } - - refresh(); - - while (1) { -#if !defined(HAVE_SLCURSES_H) && !defined(HAVE_SLANG_SLCURSES_H) && \ - defined(HAVE_LIBNCURSESW) && defined(HAVE_WIDECHAR) - if (get_wch(&c) == ERR) { -#else - if ((c = getch()) == ERR) { -#endif - if (!isatty(STDIN_FILENO)) - exit(2); - else - break; - } - if (c == '\r' || c == '\n' || c == KEY_ENTER) - break; - - switch (c) { - case ESC: - move(y, x); - clrtoeol(); - refresh(); - return GS_ESCAPE; - case DEL: - case '\b': - case KEY_BACKSPACE: - if (i > 0) { - cells--; - i = mbs_truncate(str, &cells); - if (i < 0) - return GS_ESCAPE; - mvaddch(y, x + cells, ' '); - move(y, x + cells); - } else if (use_def) { - clrtoeol(); - use_def = FALSE; - } else - putchar(BELL); - break; - default: -#if defined(HAVE_LIBNCURSESW) && defined(HAVE_WIDECHAR) - if (i + 1 < len && iswprint(c)) { - wchar_t wc = (wchar_t) c; - char s[MB_CUR_MAX + 1]; - int sz = wctomb(s, wc); - - if (sz > 0 && sz + i < len) { - s[sz] = '\0'; - mvaddnstr(y, x + cells, s, sz); - if (use_def) { - clrtoeol(); - use_def = FALSE; - } - memcpy(str + i, s, sz); - i += sz; - str[i] = '\0'; - cells += wcwidth(wc); - } else - putchar(BELL); - } -#else - if (i + 1 < len && isprint(c)) { - mvaddch(y, x + cells, c); - if (use_def) { - clrtoeol(); - use_def = FALSE; - } - str[i++] = c; - str[i] = 0; - cells++; - } -#endif - else - putchar(BELL); - } - refresh(); - } - - if (use_def) - return GS_DEFAULT; - else - return i; -} - -static 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; -} - -static 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; - } -} - -static void -fatal(char *s, int ret) { - char *err1 = _("FATAL ERROR"); - char *err2 = _("Press any key to exit cfdisk"); - - if (curses_started) { - char *str = xmalloc(strlen(s) + strlen(err1) + strlen(err2) + 10); - - sprintf(str, "%s: %s", err1, s); - if (strlen(str) > (size_t) COLS) - str[COLS] = 0; - mvaddstr(WARNING_START, (COLS-strlen(str))/2, str); - sprintf(str, "%s", err2); - if (strlen(str) > (size_t) COLS) - str[COLS] = 0; - mvaddstr(WARNING_START+1, (COLS-strlen(str))/2, str); - putchar(BELL); /* CTRL-G */ - refresh(); - (void)getch(); - die_x(ret); - } else { - fprintf(stderr, "%s: %s\n", err1, s); - exit(ret); - } -} - -static void -die(int dummy __attribute__((__unused__))) { - die_x(0); -} - -static void -die_x(int ret) { - signal(SIGINT, old_SIGINT); - signal(SIGTERM, old_SIGTERM); -#if defined(HAVE_SLCURSES_H) || defined(HAVE_SLANG_SLCURSES_H) - SLsmg_gotorc(LINES-1, 0); - SLsmg_refresh(); -#else - mvcur(0, COLS-1, LINES-1, 0); -#endif - nl(); - endwin(); - printf("\n"); - fdexit(ret); -} - -static void -read_sector(unsigned char *buffer, long long sect_num) { - if (lseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0) - fatal(_("Cannot seek on disk drive"), 2); - if (read(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(_("Cannot read disk drive"), 2); -} - -static void -write_sector(unsigned char *buffer, long long sect_num) { - if (lseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0) - fatal(_("Cannot seek on disk drive"), 2); - if (write(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE) - fatal(_("Cannot write disk drive"), 2); -} - -#ifdef HAVE_LIBBLKID -static void -get_fsinfo(int i) -{ - blkid_probe pr; - blkid_loff_t offset, size; - const char *data; - - offset = (p_info[i].first_sector + p_info[i].offset) * SECTOR_SIZE; - size = (p_info[i].last_sector - p_info[i].first_sector + 1) * SECTOR_SIZE; - pr = blkid_new_probe(); - if (!pr) - return; - blkid_probe_enable_superblocks(pr, 1); - blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL | - BLKID_SUBLKS_TYPE); - if (blkid_probe_set_device(pr, fd, offset, size)) - goto done; - if (blkid_do_safeprobe(pr)) - goto done; - - if (!blkid_probe_lookup_value(pr, "TYPE", &data, 0)) - strncpy(p_info[i].fstype, data, FSTYPESZ); - - if (!blkid_probe_lookup_value(pr, "LABEL", &data, 0)) - strncpy(p_info[i].volume_label, data, LABELSZ); -done: - blkid_free_probe(pr); -} -#endif - -static 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 */ - } - } -} - -static void -remove_part(int i) { - int p; - - for (p = i; p < num_parts; p++) - p_info[p] = p_info[p+1]; - - num_parts--; - if (cur_part == num_parts) - cur_part--; -} - -static void -insert_empty_part(int i, long long first, long long 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++; -} - -static 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 = actual_size - 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(); -} - -static int -add_part(int num, int id, int flags, long long first, long long last, - long long offset, int want_label, char **errmsg) { - int i, pri = 0, log = 0; - - if (num_parts == MAXIMUM_PARTS) { - *errmsg = _("Too many partitions"); - return -1; - } - - if (first < 0) { - *errmsg = _("Partition begins before sector 0"); - return -1; - } - - if (last < 0) { - *errmsg = _("Partition ends before sector 0"); - return -1; - } - - if (first >= actual_size) { - *errmsg = _("Partition begins after end-of-disk"); - return -1; - } - - if (last >= actual_size) { - *errmsg = _("Partition ends after end-of-disk"); - 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 (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) { - if (last < p_info[i].first_sector) - *errmsg = _("logical partitions not in disk order"); - else if (first + offset <= p_info[i].last_sector && - p_info[i].first_sector + p_info[i].offset <= last) - *errmsg = _("logical partitions overlap"); - else - /* the enlarged logical partition starts at the - partition table sector that defines it */ - *errmsg = _("enlarged logical partitions overlap"); - return -1; - } - - if (i == num_parts || 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(_("Cannot create logical drive here -- would create two extended partitions")); - 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(_("Cannot create logical drive here -- would create two extended partitions")); - 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; - -#ifdef HAVE_LIBBLKID - if (want_label) - get_fsinfo(i); -#endif - check_part_info(); - - return 0; -} - -static 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; -} - -static 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; -} - -/* - * Command menu support by Janne Kukonlehto <jtklehto@phoenix.oulu.fi> - * September 1994 - */ - -/* Constants for menuType parameter of menuSelect function */ -#define MENU_ACCEPT_OTHERS 4 -#define MENU_BUTTON 8 -/* Miscellenous constants */ -#define MENU_SPACING 2 -#define MENU_MAX_ITEMS 256 /* for simpleMenu function */ - -struct MenuItem -{ - int 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. - */ - -static int -menuUpdate( int y, int x, struct MenuItem *menuItems, int itemLength, - char *available, int menuType, int current ) { - int i, lmargin = x; - char *mcd; - - /* Print available buttons */ - move( y, x ); clrtoeol(); - - for( i = 0; menuItems[i].key; i++ ) { - char buff[20]; - int lenName; - const char *mi; - - /* 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 */ - /* Because of a bug in gettext() we must not translate empty strings */ - if (menuItems[i].name[0]) - mi = _(menuItems[i].name); - else - mi = ""; - lenName = strlen( mi ); -#if 0 - if(lenName > itemLength || lenName >= sizeof(buff)) - print_warning(_("Menu item too long. Menu may look odd.")); -#endif - if ((size_t) lenName >= sizeof(buff)) { /* truncate ridiculously long string */ - xstrncpy(buff, mi, sizeof(buff)); - } else if (lenName >= itemLength) { - snprintf(buff, sizeof(buff), - (menuType & MENU_BUTTON) ? "[%s]" : "%s", mi); - } else { - snprintf(buff, sizeof(buff), - (menuType & MENU_BUTTON) ? "[%*s%-*s]" : "%*s%-*s", - (itemLength - lenName) / 2, "", - (itemLength - lenName + 1) / 2 + lenName, mi); - } - mvaddstr( y, x, buff ); - - /* Lowlight after selected item */ - if( current == i ) /*attroff( A_REVERSE )*/ standend (); - - /* Calculate position for the next item */ - x += itemLength + MENU_SPACING; - if( menuType & MENU_BUTTON ) x += 2; - if( x > COLUMNS - lmargin - 12 ) - { - x = lmargin; - y ++ ; - } - } - - /* Print the description of selected item */ - mcd = _(menuItems[current].desc); - mvaddstr( WARNING_START + 1, (COLUMNS - strlen( mcd )) / 2, mcd ); - return y; -} - -/* This function takes a list of menu items, lets the user choose one * - * and returns the keyboard shortcut value of the selected menu item */ - -static 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; - - /* Make sure that the current is one of the available items */ - while( !strchr(available, menuItems[current].key) ) { - current ++ ; - if( !menuItems[current].key ) current = 0; - } - - keypad(stdscr, TRUE); - - /* Repeat until allowable choice has been made */ - while( !key ) { - /* Display the menu and read a command */ - ylast = menuUpdate( y, x, menuItems, itemLength, available, - menuType, current ); - refresh(); - key = getch(); - - if (key == ERR) - if (!isatty(STDIN_FILENO)) - exit(2); - - /* Clear out all prompts and such */ - clear_warning(); - for (i = y; i < ylast; i++) { - move(i, x); - clrtoeol(); - } - move( WARNING_START + 1, 0 ); - clrtoeol(); - - switch (key) { - case KEY_RIGHT: - case '\t': - /* Select next menu item */ - do { - current++; - if (!menuItems[current].key) - current = 0; - } while (!strchr(available, menuItems[current].key)); - key = 0; - break; - case KEY_LEFT: -#ifdef KEY_BTAB - case KEY_BTAB: /* Back tab */ -#endif - /* Select previous menu item */ - do { - current--; - if (current < 0) { - while (menuItems[current + 1].key) - current++; - } - } while (!strchr(available, menuItems[current].key)); - key = 0; - break; - case KEY_ENTER: - case '\n': - case '\r': - /* Enter equals the keyboard shortcut of current menu item */ - key = menuItems[current].key; - break; - } - - /* 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")); - } - } - - keypad(stdscr, FALSE); - - /* 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? */ - -static void -menuContinue(void) { - static struct MenuItem menuContinueBtn[]= - { - { 'c', "", N_("Press a key to continue") }, - { 0, NULL, NULL } - }; - - menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, - menuContinueBtn, 0, "c", MENU_ACCEPT_OTHERS, 0 ); -} - -/* Function menuSelect takes way too many parameters * - * Luckily, most of time we can do with this function */ - -static 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_BUTTON, menuDefault); -} - -/* End of command menu support code */ - -static void -new_part(int i) { - char response[LINE_LENGTH], def[LINE_LENGTH]; - char c; - long long first = p_info[i].first_sector; - long long last = p_info[i].last_sector; - long long offset = 0; - int flags = 0; - int id = LINUX; - int num = -1; - long long num_sects = last - first + 1; - int len, ext, j; - char *errmsg; - double sectors_per_MB = K*K / 512.0; - - if (p_info[i].num == PRI_OR_LOG) { - static struct MenuItem menuPartType[]= - { - { 'p', N_("Primary"), N_("Create a new primary partition") }, - { 'l', N_("Logical"), N_("Create a new logical partition") }, - { ESC, N_("Cancel"), N_("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 !!!")); - - snprintf(def, sizeof(def), "%.2f", num_sects/sectors_per_MB); - 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/cylinder_size)) - for (j = 0; - j < len-1 && (isdigit(response[j]) || response[j] == '.'); - j++); - if (toupper(response[j]) == 'K') { - num_sects = num_cyls(atof(response)*K)*cylinder_size; - } else if (toupper(response[j]) == 'M') { - num_sects = num_cyls(atof(response)*K*K)*cylinder_size; - } else if (toupper(response[j]) == 'G') { - num_sects = num_cyls(atof(response)*K*K*K)*cylinder_size; - } else if (toupper(response[j]) == 'C') { - num_sects = round_int(atof(response))*cylinder_size; - } else if (toupper(response[j]) == 'S') { - num_sects = round_int(atof(response)); - } else { - num_sects = num_cyls(atof(response)*K*K)*cylinder_size; - } - } - - 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', N_("Beginning"), N_("Add partition at beginning of free space") }, - { 'e', N_("End"), N_("Add partition at end of free space") }, - { ESC, N_("Cancel"), N_("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(_("No room to create the extended partition")); - return; - } - errmsg = 0; - if (add_part(ext, DOS_EXTENDED, 0, first, last, - (first == 0 ? sectors : 0), 0, &errmsg) && errmsg) - print_warning(errmsg); - first = ext_info.first_sector + ext_info.offset; - } - - /* increment number of all partitions past this one */ - if (IS_LOGICAL(num)) { -#if 0 - /* original text - ok, but fails when partitions not in disk order */ - for (j = i; j < num_parts; j++) - if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num)) - p_info[j].num++; -#else - /* always ok */ - for (j = 0; j < num_parts; j++) - if (p_info[j].id > 0 && p_info[j].num >= num) - p_info[j].num++; -#endif - } - - /* Now we have a complete partition to ourselves */ - if (first == 0 || IS_LOGICAL(num)) - offset = sectors; - - errmsg = 0; - if (add_part(num, id, flags, first, last, offset, 0, &errmsg) && errmsg) - print_warning(errmsg); -} - -static void -get_kernel_geometry(void) { -#ifdef HDIO_GETGEO - struct hd_geometry geometry; - - if (!ioctl(fd, HDIO_GETGEO, &geometry)) { - kern_heads = geometry.heads; - kern_sectors = geometry.sectors; - } -#endif -} - -static int -said_yes(char answer) { - char reply[2]; - - reply[0] = answer; - reply[1] = 0; - - return (rpmatch(reply) == 1) ? 1 : 0; -} - -static void -get_partition_table_geometry(partition_table *bufp) { - struct partition *p; - int i,h,s,hh,ss; - int first = TRUE; - int bad = FALSE; - - for (i=0; i<66; i++) - if (bufp->c.b[446+i]) - goto nonz; - - /* zero table */ - if (!curses_started) { - fatal(_("No partition table.\n"), 3); - return; - } else { - mvaddstr(WARNING_START, 0, - _("No partition table. Starting with zero table.")); - putchar(BELL); - refresh(); - zero_table = TRUE; - return; - } - nonz: - if (bufp->p.magicflag[0] != PART_TABLE_FLAG0 || - bufp->p.magicflag[1] != PART_TABLE_FLAG1) { - if (!curses_started) - fatal(_("Bad signature on partition table"), 3); - - /* Matthew Wilcox */ - mvaddstr(WARNING_START, 0, - _("Unknown partition table type")); - mvaddstr(WARNING_START+1, 0, - _("Do you wish to start with a zero table [y/N] ?")); - putchar(BELL); - refresh(); - { - int cont = getch(); - if (cont == EOF || !said_yes(cont)) - die_x(3); - } - zero_table = TRUE; - return; - } - - hh = ss = 0; - for (i=0; i<4; i++) { - p = &(bufp->p.part[i]); - if (p->sys_ind != 0) { - h = p->end_head + 1; - s = (p->end_sector & 077); - if (first) { - hh = h; - ss = s; - first = FALSE; - } else if (hh != h || ss != s) - bad = TRUE; - } - } - - if (!first && !bad) { - pt_heads = hh; - pt_sectors = ss; - } -} - -static void -decide_on_geometry(void) { - heads = (user_heads ? user_heads : - pt_heads ? pt_heads : - kern_heads ? kern_heads : 255); - sectors = (user_sectors ? user_sectors : - pt_sectors ? pt_sectors : - kern_sectors ? kern_sectors : 63); - cylinder_size = heads*sectors; - cylinders = actual_size/cylinder_size; - if (user_cylinders > 0) - cylinders = user_cylinders; - - if (cylinder_size * cylinders > actual_size) - print_warning(_("You specified more cylinders than fit on disk")); -} - -static void -clear_p_info(void) { - num_parts = 1; - p_info[0].first_sector = 0; - p_info[0].last_sector = actual_size - 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; -} - -static void -fill_p_info(void) { - int pn, i; - long long bs, bsz; - unsigned long long llsectors; - struct partition *p; - partition_table buffer; - partition_info tmp_ext; - - memset(&tmp_ext, 0, sizeof tmp_ext); - tmp_ext.id = FREE_SPACE; - tmp_ext.num = PRIMARY; - - if ((fd = open(disk_device, O_RDWR)) < 0) { - if ((fd = open(disk_device, O_RDONLY)) < 0) - fatal(_("Cannot open disk drive"), 2); - opentype = O_RDONLY; - print_warning(_("Opened disk read-only - you have no permission to write")); - if (curses_started) { - refresh(); - getch(); - clear_warning(); - } - } else - opentype = O_RDWR; - opened = TRUE; - - if (gpt_probe_signature_fd(fd)) { - print_warning(_("Warning!! Unsupported GPT (GUID Partition Table) detected. Use GNU Parted.")); - refresh(); - getch(); - clear_warning(); - } - -#ifdef BLKFLSBUF - /* 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 */ -#endif - - if (blkdev_get_sectors(fd, &llsectors) == -1) - fatal(_("Cannot get disk size"), 3); - actual_size = llsectors; - - read_sector(buffer.c.b, 0); - - get_kernel_geometry(); - - if (!zero_table || use_partition_table_geometry) - get_partition_table_geometry(& buffer); - - decide_on_geometry(); - - clear_p_info(); - - if (!zero_table) { - char *errmsg = ""; - - for (i = 0; i < 4; i++) { - p = & buffer.p.part[i]; - bs = get_start_sect(p); - bsz = get_nr_sects(p); - - if (p->sys_ind > 0 && - add_part(i, p->sys_ind, p->boot_ind, - ((bs <= sectors) ? 0 : bs), bs + bsz - 1, - ((bs <= sectors) ? bs : 0), 1, &errmsg)) { - char *bad = _("Bad primary partition"); - char *msg = (char *) xmalloc(strlen(bad) + strlen(errmsg) + 30); - sprintf(msg, "%s %d: %s", bad, i + 1, errmsg); - fatal(msg, 4); - } - 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 (pn = 0; - pn < 4 && (!buffer.p.part[pn].sys_ind || - is_extended(buffer.p.part[pn].sys_ind)); - pn++); - - if (pn < 4) { - p = & buffer.p.part[pn]; - bs = get_start_sect(p); - bsz = get_nr_sects(p); - - if (add_part(i++, p->sys_ind, p->boot_ind, - logical_sectors[logical-1], - logical_sectors[logical-1] + bs + bsz - 1, - bs, 1, &errmsg)) { - char *bad = _("Bad logical partition"); - char *msg = (char *) xmalloc(strlen(bad) + strlen(errmsg) + 30); - sprintf(msg, "%s %d: %s", bad, i, errmsg); - fatal(msg, 4); - } - } - - for (pn = 0; - pn < 4 && !is_extended(buffer.p.part[pn].sys_ind); - pn++); - if (pn < 4) { - p = & buffer.p.part[pn]; - bs = get_start_sect(p); - logical_sectors[logical] = ext_info.first_sector - + ext_info.offset + bs; - read_sector(buffer.c.b, logical_sectors[logical++]); - } - } while (pn < 4 && logical < MAXIMUM_PARTS-4); - } - } -} - -static void -fill_part_table(struct partition *p, partition_info *pi) { - long long begin; - - p->boot_ind = pi->flags; - p->sys_ind = pi->id; - begin = pi->first_sector + pi->offset; - if (IS_LOGICAL(pi->num)) - set_start_sect(p,pi->offset); - else - set_start_sect(p,begin); - set_nr_sects(p, pi->last_sector - begin + 1); - set_hsc_begin(p, begin); - set_hsc_end(p, pi->last_sector); -} - -static 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.magicflag[0] = PART_TABLE_FLAG0; - buffer->p.magicflag[1] = PART_TABLE_FLAG1; -} - -static void -fill_logical_table(partition_table *buffer, partition_info *pi) { - struct partition *p; - int i; - - for (i = 0; i < logical && pi->first_sector != logical_sectors[i]; i++); - if (i == logical || buffer->p.magicflag[0] != PART_TABLE_FLAG0 - || buffer->p.magicflag[1] != PART_TABLE_FLAG1) - 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; - set_start_sect(p, pi->first_sector - ext_info.first_sector - ext_info.offset); - set_nr_sects(p, pi->last_sector - pi->first_sector + 1); - set_hsc_begin(p, pi->first_sector); - set_hsc_end(p, pi->last_sector); - } - - buffer->p.magicflag[0] = PART_TABLE_FLAG0; - buffer->p.magicflag[1] = PART_TABLE_FLAG1; -} - -static void -write_part_table(void) { - int i, ct, done = FALSE, len; - partition_table buffer; - struct stat s; - int is_bdev; - char response[LINE_LENGTH]; - - if (opentype == O_RDONLY) { - print_warning(_("Opened disk read-only - you have no permission to write")); - 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(_("Warning!! This may destroy data on your disk!")); - - while (!done) { - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - _("Are you sure you want to 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 (strcasecmp(response, _("no")) == 0 || - strcasecmp(response, "no") == 0) { - print_warning(_("Did not write partition table to disk")); - return; - } else if (strcasecmp(response, _("yes")) == 0 || - strcasecmp(response, "yes") == 0) - done = TRUE; - else - print_warning(_("Please enter `yes' or `no'")); - } - - clear_warning(); - print_warning(_("Writing partition table to disk...")); - 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) { -#ifdef BLKRRPART - sync(); - if (!ioctl(fd,BLKRRPART)) - changed = TRUE; -#endif - sync(); - - clear_warning(); - if (changed) - print_warning(_("Wrote partition table to disk")); - else - print_warning(_("Wrote partition table, but re-read table failed. Run partprobe(8), kpartx(8) or reboot to update table.")); - } else - print_warning(_("Wrote partition table to disk")); - - /* Check: unique bootable primary partition? */ - ct = 0; - for (i = 0; i < num_parts; i++) - if (IS_PRIMARY(i) && p_info[i].flags == ACTIVE_FLAG) - ct++; - if (ct == 0) - print_warning(_("No primary partitions are marked bootable. DOS MBR cannot boot this.")); - if (ct > 1) - print_warning(_("More than one primary partition is marked bootable. DOS MBR cannot boot this.")); -} - -static void -fp_printf(FILE *fp, char *format, ...) { - va_list args; - char buf[1024]; - int y, x __attribute__((unused)); - - va_start(args, format); - vsnprintf(buf, sizeof(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 -static void -print_file_buffer(FILE *fp, unsigned 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", 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"); -} - -static 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]; - snprintf(errstr, sizeof(errstr), - _("Cannot open file '%s'"), 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(); - } -} - -static void -print_p_info_entry(FILE *fp, partition_info *p) { - long long 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, "%11lld%c", p->first_sector, - ((p->first_sector/cylinder_size) != - ((float)p->first_sector/cylinder_size) ? - '*' : ' ')); - - fp_printf(fp, "%11lld%c", p->last_sector, - (((p->last_sector+1)/cylinder_size) != - ((float)(p->last_sector+1)/cylinder_size) ? - '*' : ' ')); - - fp_printf(fp, "%6ld%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, "%11lld%c", size, - ((size/cylinder_size) != ((float)size/cylinder_size) ? - '*' : ' ')); - - /* fp_printf(fp, " "); */ - - if (p->id == UNUSABLE) - sprintf(part_str, "%.15s", _("Unusable")); - else if (p->id == FREE_SPACE) - sprintf(part_str, "%.15s", _("Free Space")); - else if (partition_type_name(p->id)) - sprintf(part_str, "%.15s (%02X)", _(partition_type_name(p->id)), p->id); - else - sprintf(part_str, "%.15s (%02X)", _("Unknown"), p->id); - fp_printf(fp, "%-20.20s", part_str); - - fp_printf(fp, " "); - - if (p->flags == ACTIVE_FLAG) - fp_printf(fp, _("Boot"), p->flags); - else if (p->flags != 0) - fp_printf(fp, _("(%02X)"), p->flags); - else - fp_printf(fp, _("None"), p->flags); - - fp_printf(fp, "\n"); -} - -static 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]; - snprintf(errstr, LINE_LENGTH, _("Cannot open file '%s'"), 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) Flag\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(); - } -} - -static void -print_part_entry(FILE *fp, int num, partition_info *pi) { - long long first = 0, start = 0, end = 0, size = 0; - unsigned char ss, es, sh, eh; - int sc, ec; - int flags = 0, id = 0; - - ss = sh = es = eh = 0; - sc = ec = 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; - - set_hsc0(&sh, &ss, &sc, start); - set_hsc0(&eh, &es, &ec, end); - } - - fp_printf(fp, "%2d 0x%02X %4d %4d %5d 0x%02X %4d %4d %5d %11lld %11lld\n", - num+1, flags, sh, ss, sc, id, eh, es, ec, first, size); -} - - -static 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]; - snprintf(errstr, LINE_LENGTH, _("Cannot open file '%s'"), 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"); - /* Three-line heading. Read "Start Sector" etc vertically. */ - 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(); - } -} - -static void -print_tables(void) { - int done = FALSE; - - static struct MenuItem menuFormat[]= - { - { 'r', N_("Raw"), N_("Print the table using raw data format") }, - { 's', N_("Sectors"), N_("Print the table ordered by sectors") }, - { 't', N_("Table"), N_("Just print the partition table") }, - { ESC, N_("Cancel"), N_("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!" -static void -display_help(void) { - char *help_text[] = { - N_("Help Screen for cfdisk"), - "", - N_("This is cfdisk, a curses based disk partitioning program, which"), - N_("allows you to create, delete and modify partitions on your hard"), - N_("disk drive."), - "", - N_("Copyright (C) 1994-1999 Kevin E. Martin & aeb"), - "", - N_("Command Meaning"), - N_("------- -------"), - N_(" b Toggle bootable flag of the current partition"), - N_(" d Delete the current partition"), - N_(" g Change cylinders, heads, sectors-per-track parameters"), - N_(" WARNING: This option should only be used by people who"), - N_(" know what they are doing."), - N_(" h Print this screen"), - N_(" m Maximize disk usage of the current partition"), - N_(" Note: This may make the partition incompatible with"), - N_(" DOS, OS/2, ..."), - N_(" n Create new partition from free space"), - N_(" p Print partition table to the screen or to a file"), - N_(" There are several different formats for the partition"), - N_(" that you can choose from:"), - N_(" r - Raw data (exactly what would be written to disk)"), - N_(" s - Table ordered by sectors"), - N_(" t - Table in raw format"), - N_(" q Quit program without writing partition table"), - N_(" t Change the filesystem type"), - N_(" u Change units of the partition size display"), - N_(" Rotates through MB, sectors and cylinders"), - N_(" W Write partition table to disk (must enter upper case W)"), - N_(" Since this might destroy data on the disk, you must"), - N_(" either confirm or deny the write by entering `yes' or"), - N_(" `no'"), - N_("Up Arrow Move cursor to the previous partition"), - N_("Down Arrow Move cursor to the next partition"), - N_("CTRL-L Redraws the screen"), - N_(" ? Print this screen"), - "", - N_("Note: All of the commands can be entered with either upper or lower"), - N_("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 (help_text[cur_line][0]) - fp_printf(fp, "%s\n", _(help_text[cur_line])); - else - fp_printf(fp, "\n"); - cur_line++; - } - menuContinue(); -} - -static int -change_geometry(void) { - int ret_val = FALSE; - int done = FALSE; - char def[LINE_LENGTH]; - char response[LINE_LENGTH]; - long long tmp_val; - int i; - - while (!done) { - static struct MenuItem menuGeometry[]= - { - { 'c', N_("Cylinders"), N_("Change cylinder geometry") }, - { 'h', N_("Heads"), N_("Change head geometry") }, - { 's', N_("Sectors"), N_("Change sector geometry") }, - { 'd', N_("Done"), N_("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, "%llu", actual_size/cylinder_size); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, - _("Enter the number of cylinders: ")); - i = get_string(response, LINE_LENGTH, def); - if (i == GS_DEFAULT) { - user_cylinders = actual_size/cylinder_size; - ret_val = TRUE; - } else if (i > 0) { - tmp_val = atoll(response); - if (tmp_val > 0) { - user_cylinders = tmp_val; - ret_val = TRUE; - } else - print_warning(_("Illegal cylinders value")); - } - 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 = atoll(response); - if (tmp_val > 0 && tmp_val <= MAX_HEADS) { - user_heads = tmp_val; - ret_val = TRUE; - } else - print_warning(_("Illegal heads value")); - } - 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 = atoll(response); - if (tmp_val > 0 && tmp_val <= MAX_SECTORS) { - user_sectors = tmp_val; - ret_val = TRUE; - } else - print_warning(_("Illegal sectors value")); - } - break; - case ESC: - case 'D': - done = TRUE; - break; - default: - putchar(BELL); - break; - } - - if (ret_val) { - decide_on_geometry(); - draw_screen(); - } - } - - if (ret_val) { - long long disk_end; - - disk_end = actual_size-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; -} - -static 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 = ((p_info[i].id == LINUX) ? LINUX_SWAP : LINUX); - int y_start, y_end, row, row_min, row_max, row_offset, j, needmore; - - for (j = 1; i386_sys_types[j].name; j++) ; - num_types = j-1; /* do not count the Empty type */ - - 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 < 1) { - y_start = 1; - y_end = COMMAND_LINE_Y - 2; - } else { - if (y_start > DISK_TABLE_START+cur_part+4) - y_start = DISK_TABLE_START+cur_part+4; - y_end = y_start + num_down - 1; - } - - row_min = 1; - row_max = COMMAND_LINE_Y - 2; - row_offset = 0; - do { - for (j = y_start - 1; j <= y_end + 1; j++) { - move(j, 0); - clrtoeol(); - } - needmore = 0; - for (j = 1; i386_sys_types[j].name; j++) { - row = y_start + (j-1) % num_down - row_offset; - if (row >= row_min && row <= row_max) { - move(row, ((j-1)/num_down)*COL_ID_WIDTH + 1); - printw("%02X %-20.20s", - i386_sys_types[j].type, - _(i386_sys_types[j].name)); - } - if (row > row_max) - needmore = 1; - } - if (needmore) - menuContinue(); - row_offset += (row_max - row_min + 1); - } while(needmore); - - sprintf(def, "%02X", new_id); - mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, _("Enter filesystem type: ")); - if ((len = get_string(id, 3, 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(_("Cannot change FS Type to empty")); - else if (is_extended(new_id)) - print_warning(_("Cannot change FS Type to extended")); - else - p_info[i].id = new_id; -} - -static void -draw_partition(int i) { - int j; - int y = i + DISK_TABLE_START + 2 - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN; - char *t; - long long size; - double fsize; - - if (!arrow_cursor) { - move(y, 0); - for (j = 0; j < COLS; j++) - addch(' '); - } - - if (p_info[i].id > 0) { - char *dbn = my_basename(disk_device); - int l = strlen(dbn); - int digit_last = isdigit(dbn[l-1]); - - mvprintw(y, NAME_START, - "%s%s%d", dbn, (digit_last ? "p" : ""), - 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; - fsize = (double) size * SECTOR_SIZE; - if (display_units == SECTORS) - mvprintw(y, SIZE_START, "%11lld", size); - else if (display_units == CYLINDERS) - mvprintw(y, SIZE_START, "%11lld", size/cylinder_size); - else if (display_units == MEGABYTES) - mvprintw(y, SIZE_START, "%11.2f", ceiling((100*fsize)/(K*K))/100); - else if (display_units == GIGABYTES) - mvprintw(y, SIZE_START, "%11.2f", ceiling((100*fsize)/(K*K*K))/100); - if (size % cylinder_size != 0 || - p_info[i].first_sector % cylinder_size != 0) - mvprintw(y, COLUMNS-1, "*"); -} - -static 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; - } -} - -static void -draw_screen(void) { - int i; - char *line; - - line = (char *) xmalloc((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); - - - snprintf(line, COLS+1, "cfdisk (%s)", PACKAGE_STRING); - mvaddstr(HEADER_START, (COLS-strlen(line))/2, line); - snprintf(line, COLS+1, _("Disk Drive: %s"), disk_device); - mvaddstr(HEADER_START+2, (COLS-strlen(line))/2, line); - { - long long bytes = actual_size*(long long) SECTOR_SIZE; - long long megabytes = bytes/(K*K); - - if (megabytes < 10000) - sprintf(line, _("Size: %lld bytes, %lld MB"), - bytes, megabytes); - else - sprintf(line, _("Size: %lld bytes, %lld.%lld GB"), - bytes, megabytes/K, (10*megabytes/K)%10); - } - mvaddstr(HEADER_START+3, (COLS-strlen(line))/2, line); - snprintf(line, COLS+1, _("Heads: %d Sectors per Track: %d Cylinders: %lld"), - heads, sectors, cylinders); - mvaddstr(HEADER_START+4, (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 if (display_units == MEGABYTES) - mvaddstr(DISK_TABLE_START, SIZE_START, _(" Size (MB)")); - else if (display_units == GIGABYTES) - mvaddstr(DISK_TABLE_START, SIZE_START, _(" Size (GB)")); - - 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); -} - -static void -draw_cursor(int move) { - if (move != 0 && (cur_part + move < 0 || cur_part + move >= num_parts)) { - print_warning(_("No more partitions")); - return; - } - - 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(); - } -} - -static void -do_curses_fdisk(void) { - int done = FALSE; - int command; - int is_first_run = TRUE; - - static struct MenuItem menuMain[] = { - { 'b', N_("Bootable"), N_("Toggle bootable flag of the current partition") }, - { 'd', N_("Delete"), N_("Delete the current partition") }, - { 'g', N_("Geometry"), N_("Change disk geometry (experts only)") }, - { 'h', N_("Help"), N_("Print help screen") }, - { 'm', N_("Maximize"), N_("Maximize disk usage of the current partition (experts only)") }, - { 'n', N_("New"), N_("Create new partition from free space") }, - { 'p', N_("Print"), N_("Print partition table to the screen or to a file") }, - { 'q', N_("Quit"), N_("Quit program without writing partition table") }, - { 't', N_("Type"), N_("Change the filesystem type (DOS, Linux, OS/2 and so on)") }, - { 'u', N_("Units"), N_("Change units of the partition size display (MB, sect, cyl)") }, - { 'W', N_("Write"), N_("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; - - 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, 10, - s, MENU_BUTTON | MENU_ACCEPT_OTHERS, 5); - } else if (p_info[cur_part].id > 0) { - s = ((opentype == O_RDWR) ? "bdhmpqtuW" : "bdhmpqtu"); - command = menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuMain, 10, - s, MENU_BUTTON | MENU_ACCEPT_OTHERS, is_first_run ? 7 : 0); - } else { - s = ((opentype == O_RDWR) ? "hpquW" : "hpqu"); - command = menuSelect(COMMAND_LINE_Y, COMMAND_LINE_X, menuMain, 10, - s, MENU_BUTTON | MENU_ACCEPT_OTHERS, 0); - } - is_first_run = FALSE; - switch ( command ) { - case 'B': - case 'b': - if (p_info[cur_part].id > 0) - p_info[cur_part].flags ^= 0x80; - else - print_warning(_("Cannot make this partition bootable")); - 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(_("Cannot delete an empty partition")); - 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(_("Cannot maximize this partition")); - } else - print_warning(_("Cannot maximize this partition")); - 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(_("This partition is unusable")); - else - print_warning(_("This partition is already in use")); - 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(_("Cannot change the type of an empty partition")); - break; - case 'U': - case 'u': - if (display_units == GIGABYTES) - display_units = MEGABYTES; - else if (display_units == MEGABYTES) - display_units = SECTORS; - else if (display_units == SECTORS) - display_units = CYLINDERS; - else if (display_units == CYLINDERS) - display_units = MEGABYTES; /* not yet GIGA */ - draw_screen(); - break; - case 'W': - write_part_table(); - break; - case 'H': - case 'h': - case '?': - display_help(); - draw_screen(); - break; - case KEY_UP: /* Up arrow key */ - case '\020': /* ^P */ - case 'k': /* Vi-like alternative */ - draw_cursor(-1); - break; - case KEY_DOWN: /* Down arrow key */ - case '\016': /* ^N */ - case 'j': /* Vi-like alternative */ - draw_cursor(1); - break; - case REDRAWKEY: - clear(); - draw_screen(); - break; - case KEY_HOME: - draw_cursor(-cur_part); - break; - case KEY_END: - draw_cursor(num_parts - cur_part - 1); - break; - default: - print_warning(_("Illegal command")); - putchar(BELL); /* CTRL-G */ - } - } - - die_x(0); -} - -static void -copyright(void) { - fprintf(stderr, _("Copyright (C) 1994-2002 Kevin E. Martin & aeb\n")); -} - -static void -usage(char *prog_name) { - /* Unfortunately, xgettext does not handle multi-line strings */ - /* so, let's use explicit \n's instead */ - fprintf(stderr, _("\n" -"Usage:\n" -"Print version:\n" -" %s -v\n" -"Print partition table:\n" -" %s -P {r|s|t} [options] device\n" -"Interactive use:\n" -" %s [options] device\n" -"\n" -"Options:\n" -"-a: Use arrow instead of highlighting;\n" -"-z: Start with a zero partition table, instead of reading the pt from disk;\n" -"-c C -h H -s S: Override the kernel's idea of the number of cylinders,\n" -" the number of heads and the number of sectors/track.\n\n"), - prog_name, prog_name, prog_name); - - copyright(); -} - -int -main(int argc, char **argv) -{ - int c; - int i, len; - - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - atexit(close_stdout); - - while ((c = getopt(argc, argv, "ac:gh:s:vzP:")) != -1) - switch (c) { - case 'a': - arrow_cursor = TRUE; - break; - case 'c': - user_cylinders = cylinders = strtos64_or_err(optarg, _("cannot parse number of cylinders")); - if (cylinders <= 0) { - fprintf(stderr, "%s: %s\n", argv[0], _("Illegal cylinders value")); - exit(1); - } - break; - case 'g': - use_partition_table_geometry = TRUE; - break; - case 'h': - user_heads = heads = strtol_or_err(optarg, _("cannot parse number of heads")); - if (heads <= 0 || heads > MAX_HEADS) { - fprintf(stderr, "%s: %s\n", argv[0], _("Illegal heads value")); - exit(1); - } - break; - case 's': - user_sectors = sectors = strtol_or_err(optarg, _("cannot parse number of sectors")); - if (sectors <= 0 || sectors > MAX_SECTORS) { - fprintf(stderr, "%s: %s\n", argv[0], _("Illegal sectors value")); - exit(1); - } - break; - case 'v': - fprintf(stderr, "cfdisk (%s)\n", PACKAGE_STRING); - 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]); - exit(1); - } - } - 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/fdisk/common.h b/fdisk/common.h deleted file mode 100644 index 352b9a597..000000000 --- a/fdisk/common.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef FDISK_COMMON_H -#define FDISK_COMMON_H - -/* common stuff for fdisk, cfdisk, sfdisk */ - -struct systypes { - unsigned char type; - char *name; -}; - -extern struct systypes i386_sys_types[]; - -extern char *partname(char *dev, int pno, int lth); - -#endif /* FDISK_COMMON_H */ diff --git a/fdisk/fdisk.8 b/fdisk/fdisk.8 deleted file mode 100644 index 5233f0f51..000000000 --- a/fdisk/fdisk.8 +++ /dev/null @@ -1,283 +0,0 @@ -.\" Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu) -.\" Copyright 1998 Andries E. Brouwer (aeb@cwi.nl) -.\" Copyright 2012 Davidlohr Bueso <dave@gnu.org> -.\" May be distributed under the GNU General Public License -.TH FDISK 8 "June 2012" "util-linux" "System Administration" -.SH NAME -fdisk \- manipulate disk partition table -.SH SYNOPSIS -.B fdisk -.RB [ \-uc ] -.RB [ \-b -.IR sectorsize ] -.RB [ \-C -.IR cyls ] -.RB [ \-H -.IR heads ] -.RB [ \-S -.IR sects ] -.I device -.sp -.B fdisk \-l -.RB [ \-u ] -.RI [ device ...] -.sp -.B fdisk \-s -.IR partition ... -.sp -.B fdisk \-v -.sp -.B fdisk \-h -.SH DESCRIPTION -.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. - -.B fdisk -does not understand GUID partition tables (GPTs) and it is not designed -for large partitions. In these cases, use the more advanced GNU -.BR parted (8). - -.B fdisk -does not use DOS-compatible mode and cylinders as display units by default. -The old deprecated DOS behavior can be enabled with -the '-c=dos -u=cylinders' command-line options. - -Hard disks can be divided into one or more logical disks called -.IR partitions . -This division is recorded in the -.IR "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. - -.SH DEVICES -The -.I device -is usually /dev/sda, /dev/sdb or so. A device name refers to the entire disk. -Old systems without libata (a library used inside the Linux kernel to -support ATA host controllers and devices) make a difference between IDE and -SCSI disks. In such cases the device name will be /dev/hd* (IDE) or /dev/sd* -(SCSI). - -The -.I partition -is a device name followed by a partition number. For example, /dev/sda1 -is the first partition on the first hard disk in the system. -See also Linux kernel documentation (the Documentation/devices.txt file). - -.SH DISK LABELS -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. - -An IRIX/SGI-type disklabel can describe 16 partitions, -the eleventh of which should be an entire `volume' partition, -while the ninth should be labeled `volume header'. -The volume header will also cover the partition table, i.e., -it starts at block zero and extends by default over five cylinders. -The remaining space in the volume header may be used by header -directory entries. No partitions may overlap with the volume header. -Also do not change its type or make some filesystem on it, since -you will lose the partition table. Use this type of label only when -working with Linux on IRIX/SGI machines or IRIX/SGI disks under Linux. - -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 -problems. First, these C/H/S fields can be filled only -when the number of heads and the number of sectors per track -are known. And second, 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 it 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 each 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 an ioctl(BLKRRPART) (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/sda1, 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/sda1 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 -.BI "\-b " sectorsize -Specify the sector size of the disk. Valid values are 512, 1024, 2048 or 4096. -(Recent kernels know the sector size. Use this only on old kernels or -to override the kernel's ideas.) Since util-linux-2.17, fdisk differentiates -between logical and physical sector size. This option changes both sector sizes to -.IB sectorsize . -.TP -.BI "\-c"[=mode] -Specify the compatibility mode, 'dos' or 'nondos'. The default is non-DOS -mode. For backward compatibility, it is possible to use the option without -the <mode> argument -- then the default is used. Note that the optional -<mode> argument cannot be separated from the -c option by a space, the correct -form is for example '-c=dos'. This option is DEPRECATED. -.TP -.BI "\-C " cyls -Specify the number of cylinders of the disk. -I have no idea why anybody would want to do so. This option is DEPRECATED. -.TP -.BI "\-H " heads -Specify the number of heads of the disk. (Not the physical number, -of course, but the number used for partition tables.) -Reasonable values are 255 and 16. This option is DEPRECATED. -.TP -.BI "\-S " sects -Specify the number of sectors per track of the disk. -(Not the physical number, of course, but the number used for -partition tables.) -A reasonable value is 63. This option is DEPRECATED. -.TP -.BI \-h -Print help and then exit. -.TP -.B \-l -List the partition tables for the specified devices and then exit. -If no devices are given, those mentioned in -.I /proc/partitions -(if that exists) are used. -.TP -.BI "\-s " partition... -Print the size (in blocks) of each given partition. -.TP -.BI "\-u"[=unit] -When listing partition tables, show sizes in 'sectors' or in 'cylinders'. The -default is to show sizes in sectors. For backward compatibility, it is possible -to use the option without the <units> argument -- then the default is used. -Note that the optional <unit> argument cannot be separated from the -u option -by a space, the correct form is for example '-u=cylinders'. -.TP -.B \-v -Print version number of -.B fdisk -program and exit. -.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 . -(Indeed, -.B cfdisk -is a beautiful program that has strict requirements on -the partition tables it accepts, and produces high quality partition -tables. Use it if you can. -.B fdisk -is a buggy program that does fuzzy things - usually it happens to -produce reasonable results. Its single advantage is that it has -some support for BSD disk labels and other non-DOS partition tables. -Avoid it if you can. -.B sfdisk -is for hackers only -- the user interface is terrible, but it is -more correct than fdisk and more powerful than both fdisk and cfdisk. -Moreover, it can be used noninteractively.) -.PP -There also is -.BR parted -which supports many types of different partition table formats. -.PP -The IRIX/SGI-type disklabel is currently not supported by the kernel. -Moreover, IRIX/SGI header directories are not fully supported yet. -.PP -The option `dump partition table to file' is missing. -.\" .SH AUTHORS -.\" A. V. Le Blanc (LeBlanc@mcc.ac.uk) -.\" Bernhard Fastenrath (fasten@informatik.uni-bonn.de) -.\" Jakub Jelinek (jj@sunsite.mff.cuni.cz) -.\" Andreas Neuper (ANeuper@GUUG.de) -.\" and many others. -.SH "SEE ALSO" -.BR cfdisk (8), -.BR sfdisk (8), -.BR mkfs (8), -.BR parted (8), -.BR partprobe (8), -.BR kpartx (8) -.SH AVAILABILITY -The fdisk command is part of the util-linux package and is available from -ftp://ftp.kernel.org/pub/linux/utils/util-linux/. diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c deleted file mode 100644 index 748badf47..000000000 --- a/fdisk/fdisk.c +++ /dev/null @@ -1,2116 +0,0 @@ -/* fdisk.c -- Partition table manipulator for Linux. - * - * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk) - * Copyright (C) 2012 Davidlohr Bueso <dave@gnu.org> - * - * This program is free software. You can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation: either version 1 or - * (at your option) any later version. - */ - -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <ctype.h> -#include <errno.h> -#include <getopt.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <time.h> -#include <limits.h> - -#include "xalloc.h" -#include "nls.h" -#include "rpmatch.h" -#include "blkdev.h" -#include "common.h" -#include "mbsalign.h" -#include "fdisk.h" -#include "wholedisk.h" -#include "pathnames.h" -#include "canonicalize.h" -#include "strutils.h" -#include "closestream.h" - -#include "fdisksunlabel.h" -#include "fdisksgilabel.h" -#include "fdiskaixlabel.h" -#include "fdiskmaclabel.h" -#include "fdiskdoslabel.h" -#include "fdiskbsdlabel.h" - -#ifdef HAVE_LINUX_COMPILER_H -#include <linux/compiler.h> -#endif -#ifdef HAVE_LINUX_BLKPG_H -#include <linux/blkpg.h> -#endif - -#include "gpt.h" - -int MBRbuffer_changed; - -#define hex_val(c) ({ \ - char _c = (c); \ - isdigit(_c) ? _c - '0' : \ - tolower(_c) + 10 - 'a'; \ - }) - - -#define sector(s) ((s) & 0x3f) -#define cylinder(s, c) ((c) | (((s) & 0xc0) << 2)) - -/* menu list description */ - -struct menulist_descr { - char command; /* command key */ - char *description; /* command description */ - enum labeltype label[2]; /* disklabel types associated with main and expert menu */ -}; - -static const struct menulist_descr menulist[] = { - {'a', N_("toggle a bootable flag"), {DOS_LABEL, 0}}, - {'a', N_("toggle a read only flag"), {SUN_LABEL, 0}}, - {'a', N_("select bootable partition"), {SGI_LABEL, 0}}, - {'a', N_("change number of alternate cylinders"), {0, SUN_LABEL}}, - {'b', N_("edit bsd disklabel"), {DOS_LABEL, 0}}, - {'b', N_("edit bootfile entry"), {SGI_LABEL, 0}}, - {'b', N_("move beginning of data in a partition"), {0, DOS_LABEL}}, - {'c', N_("toggle the dos compatibility flag"), {DOS_LABEL, 0}}, - {'c', N_("toggle the mountable flag"), {SUN_LABEL, 0}}, - {'c', N_("select sgi swap partition"), {SGI_LABEL, 0}}, - {'c', N_("change number of cylinders"), {0, DOS_LABEL | SUN_LABEL}}, - {'d', N_("delete a partition"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL, 0}}, - {'d', N_("print the raw data in the partition table"), {0, ANY_LABEL}}, - {'e', N_("change number of extra sectors per cylinder"), {0, SUN_LABEL}}, - {'e', N_("list extended partitions"), {0, DOS_LABEL}}, - {'e', N_("edit drive data"), {OSF_LABEL, 0}}, - {'f', N_("fix partition order"), {0, DOS_LABEL}}, - {'g', N_("create an IRIX (SGI) partition table"), {0, ANY_LABEL}}, - {'h', N_("change number of heads"), {0, DOS_LABEL | SUN_LABEL}}, - {'i', N_("change interleave factor"), {0, SUN_LABEL}}, - {'i', N_("change the disk identifier"), {0, DOS_LABEL}}, - {'i', N_("install bootstrap"), {OSF_LABEL, 0}}, - {'l', N_("list known partition types"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL, 0}}, - {'m', N_("print this menu"), {ANY_LABEL, ANY_LABEL}}, - {'n', N_("add a new partition"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL, 0}}, - {'o', N_("create a new empty DOS partition table"), {~OSF_LABEL, 0}}, - {'o', N_("change rotation speed (rpm)"), {0, SUN_LABEL}}, - {'p', N_("print the partition table"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL, DOS_LABEL | SUN_LABEL}}, - {'q', N_("quit without saving changes"), {ANY_LABEL, ANY_LABEL}}, - {'r', N_("return to main menu"), {OSF_LABEL, DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL}}, - {'s', N_("create a new empty Sun disklabel"), {~OSF_LABEL, 0}}, - {'s', N_("change number of sectors/track"), {0, DOS_LABEL | SUN_LABEL}}, - {'s', N_("show complete disklabel"), {OSF_LABEL, 0}}, - {'t', N_("change a partition's system id"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL, 0}}, - {'u', N_("change display/entry units"), {DOS_LABEL | SUN_LABEL | SGI_LABEL | OSF_LABEL, 0}}, - {'v', N_("verify the partition table"), {DOS_LABEL | SUN_LABEL | SGI_LABEL, DOS_LABEL | SUN_LABEL | SGI_LABEL}}, - {'w', N_("write table to disk and exit"), {DOS_LABEL | SUN_LABEL | SGI_LABEL, DOS_LABEL | SUN_LABEL | SGI_LABEL}}, - {'w', N_("write disklabel to disk"), {OSF_LABEL, 0}}, - {'x', N_("extra functionality (experts only)"), {DOS_LABEL | SUN_LABEL | SGI_LABEL, 0}}, -#if !defined (__alpha__) - {'x', N_("link BSD partition to non-BSD partition"), {OSF_LABEL, 0}}, -#endif - {'y', N_("change number of physical cylinders"), {0, SUN_LABEL}}, -}; - -int -valid_part_table_flag(unsigned char *b) { - return (b[510] == 0x55 && b[511] == 0xaa); -} - -sector_t get_nr_sects(struct partition *p) { - return read4_little_endian(p->size4); -} - -char *line_ptr, /* interactive input */ - line_buffer[LINE_LENGTH]; - -int nowarn = 0, /* no warnings for fdisk -l/-s */ - dos_compatible_flag = 0, /* disabled by default */ - dos_changed = 0, - partitions = 4; /* maximum partition + 1 */ - -unsigned int user_cylinders, user_heads, user_sectors; -sector_t sector_offset = 1; -unsigned int units_per_sector = 1, display_in_cyl_units = 0; -unsigned long grain = DEFAULT_SECTOR_SIZE; -enum labeltype disklabel; /* Current disklabel */ - -static void __attribute__ ((__noreturn__)) usage(FILE *out) -{ - fprintf(out, _("Usage:\n" - " %1$s [options] <disk> change partition table\n" - " %1$s [options] -l <disk> list partition table(s)\n" - " %1$s -s <partition> give partition size(s) in blocks\n" - "\nOptions:\n" - " -b <size> sector size (512, 1024, 2048 or 4096)\n" - " -c[=<mode>] compatible mode: 'dos' or 'nondos' (default)\n" - " -h print this help text\n" - " -u[=<unit>] display units: 'cylinders' or 'sectors' (default)\n" - " -v print program version\n" - " -C <number> specify the number of cylinders\n" - " -H <number> specify the number of heads\n" - " -S <number> specify the number of sectors per track\n" - "\n"), program_invocation_short_name); - exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); -} - -void fatal(struct fdisk_context *cxt, enum failure why) -{ - close(cxt->dev_fd); - switch (why) { - case unable_to_read: - err(EXIT_FAILURE, _("unable to read %s"), cxt->dev_path); - - case unable_to_seek: - err(EXIT_FAILURE, _("unable to seek on %s"), cxt->dev_path); - - case unable_to_write: - err(EXIT_FAILURE, _("unable to write %s"), cxt->dev_path); - - case ioctl_error: - err(EXIT_FAILURE, _("BLKGETSIZE ioctl failed on %s"), cxt->dev_path); - - default: - err(EXIT_FAILURE, _("fatal error")); - } -} - -struct partition * -get_part_table(int i) { - return ptes[i].part_table; -} - -void -set_all_unchanged(void) { - int i; - - for (i = 0; i < MAXIMUM_PARTS; i++) - ptes[i].changed = 0; -} - -void -set_changed(int i) { - ptes[i].changed = 1; -} - -static int -is_garbage_table(void) { - int i; - - for (i = 0; i < 4; i++) { - struct pte *pe = &ptes[i]; - struct partition *p = pe->part_table; - - if (p->boot_ind != 0 && p->boot_ind != 0x80) - return 1; - } - return 0; -} - -void print_menu(enum menutype menu) -{ - size_t i; - - puts(_("Command action")); - - for (i = 0; i < ARRAY_SIZE(menulist); i++) - if (menulist[i].label[menu] & disklabel) - printf(" %c %s\n", menulist[i].command, menulist[i].description); -} - -static int -get_sysid(struct fdisk_context *cxt, int i) { - return ( - disklabel == SUN_LABEL ? sun_get_sysid(cxt, i) : - disklabel == SGI_LABEL ? sgi_get_sysid(cxt, i) : - ptes[i].part_table->sys_ind); -} - -static struct systypes * -get_sys_types(void) { - return ( - disklabel == SUN_LABEL ? sun_sys_types : - disklabel == SGI_LABEL ? sgi_sys_types : - i386_sys_types); -} - -char *partition_type(unsigned char type) -{ - int i; - struct systypes *types = get_sys_types(); - - for (i=0; types[i].name; i++) - if (types[i].type == type) - return _(types[i].name); - - return NULL; -} - -void list_types(struct systypes *sys) -{ - unsigned int last[4], done = 0, next = 0, size; - int i; - - for (i = 0; sys[i].name; i++); - size = i; - - for (i = 3; i >= 0; i--) - last[3 - i] = done += (size + i - done) / (i + 1); - i = done = 0; - - do { - #define NAME_WIDTH 15 - char name[NAME_WIDTH * MB_LEN_MAX]; - size_t width = NAME_WIDTH; - - printf("%c%2x ", i ? ' ' : '\n', sys[next].type); - size_t ret = mbsalign(_(sys[next].name), name, sizeof(name), - &width, MBS_ALIGN_LEFT, 0); - if (ret == (size_t)-1 || ret >= sizeof(name)) - printf("%-15.15s", _(sys[next].name)); - else - fputs(name, stdout); - - next = last[i++] + done; - if (i > 3 || next >= last[i]) { - i = 0; - next = ++done; - } - } while (done < last[0]); - putchar('\n'); -} - -static 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; -} - -static int -lba_is_aligned(struct fdisk_context *cxt, sector_t lba) -{ - unsigned int granularity = max(cxt->phy_sector_size, cxt->min_io_size); - sector_t offset = (lba * cxt->sector_size) & (granularity - 1); - - return !((granularity + cxt->alignment_offset - offset) & (granularity - 1)); -} - -sector_t align_lba(struct fdisk_context *cxt, sector_t lba, int direction) -{ - sector_t res; - - if (lba_is_aligned(cxt, lba)) - res = lba; - else { - sector_t sects_in_phy = grain / cxt->sector_size; - - if (lba < sector_offset) - res = sector_offset; - - else if (direction == ALIGN_UP) - res = ((lba + sects_in_phy) / sects_in_phy) * sects_in_phy; - - else if (direction == ALIGN_DOWN) - res = (lba / sects_in_phy) * sects_in_phy; - - else /* ALIGN_NEAREST */ - res = ((lba + sects_in_phy / 2) / sects_in_phy) * sects_in_phy; - - if (cxt->alignment_offset && !lba_is_aligned(cxt, res) && - res > cxt->alignment_offset / cxt->sector_size) { - /* - * apply alignment_offset - * - * On disk with alignment compensation physical blocks starts - * at LBA < 0 (usually LBA -1). It means we have to move LBA - * according the offset to be on the physical boundary. - */ - /* fprintf(stderr, "LBA: %llu apply alignment_offset\n", res); */ - res -= (max(cxt->phy_sector_size, cxt->min_io_size) - - cxt->alignment_offset) / cxt->sector_size; - - if (direction == ALIGN_UP && res < lba) - res += sects_in_phy; - } - } - - /*** - fprintf(stderr, "LBA %llu (%s) --align-(%s)--> %llu (%s)\n", - lba, - lba_is_aligned(lba) ? "OK" : "FALSE", - direction == ALIGN_UP ? "UP " : - direction == ALIGN_DOWN ? "DOWN " : "NEAREST", - res, - lba_is_aligned(res) ? "OK" : "FALSE"); - ***/ - return res; -} - -int warn_geometry(struct fdisk_context *cxt) -{ - char *m = NULL; - int prev = 0; - - if (disklabel == SGI_LABEL) /* cannot set cylinders etc anyway */ - return 0; - if (!cxt->geom.heads) - prev = test_c(&m, _("heads")); - if (!cxt->geom.sectors) - prev = test_c(&m, _("sectors")); - if (!cxt->geom.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; -} - -void update_units(struct fdisk_context *cxt) -{ - int cyl_units = cxt->geom.heads * cxt->geom.sectors; - - if (display_in_cyl_units && cyl_units) - units_per_sector = cyl_units; - else - units_per_sector = 1; /* in sectors */ -} - -void warn_limits(struct fdisk_context *cxt) -{ - if (cxt->total_sectors > UINT_MAX && !nowarn) { - unsigned long long bytes = cxt->total_sectors * cxt->sector_size; - int giga = bytes / 1000000000; - int hectogiga = (giga + 50) / 100; - - fprintf(stderr, _("\n" -"WARNING: The size of this disk is %d.%d TB (%llu bytes).\n" -"DOS partition table format can not be used on drives for volumes\n" -"larger than (%llu bytes) for %ld-byte sectors. Use parted(1) and GUID \n" -"partition table format (GPT).\n\n"), - hectogiga / 10, hectogiga % 10, - bytes, - (sector_t ) UINT_MAX * cxt->sector_size, - cxt->sector_size); - } -} - -void warn_alignment(struct fdisk_context *cxt) -{ - if (nowarn) - return; - - if (cxt->sector_size != cxt->phy_sector_size) - fprintf(stderr, _("\n" -"The device presents a logical sector size that is smaller than\n" -"the physical sector size. Aligning to a physical sector (or optimal\n" -"I/O) size boundary is recommended, or performance may be impacted.\n")); - - if (dos_compatible_flag) - fprintf(stderr, _("\n" -"WARNING: DOS-compatible mode is deprecated. It's strongly recommended to\n" -" switch off the mode (with command 'c').")); - - if (display_in_cyl_units) - fprintf(stderr, _("\n" -"WARNING: cylinders as display units are deprecated. Use command 'u' to\n" -" change units to sectors.\n")); - -} - -void -get_partition_table_geometry(struct fdisk_context *cxt, unsigned int *ph, unsigned int *ps) { - unsigned char *bufp = cxt->mbr; - struct partition *p; - int i, h, s, hh, ss; - int first = 1; - int bad = 0; - - if (!(valid_part_table_flag(bufp))) - return; - - hh = ss = 0; - for (i=0; i<4; i++) { - p = pt_offset(bufp, i); - if (p->sys_ind != 0) { - h = p->end_head + 1; - s = (p->end_sector & 077); - if (first) { - hh = h; - ss = s; - first = 0; - } else if (hh != h || ss != s) - bad = 1; - } - } - - if (!first && !bad) { - *ph = hh; - *ps = ss; - } -} - -/* - * Sets LBA of the first partition - */ -void -update_sector_offset(struct fdisk_context *cxt) -{ - grain = cxt->io_size; - - if (dos_compatible_flag) - sector_offset = cxt->geom.sectors; /* usually 63 sectors */ - else { - /* - * Align the begin of partitions to: - * - * a) topology - * a2) alignment offset - * a1) or physical sector (minimal_io_size, aka "grain") - * - * b) or default to 1MiB (2048 sectrors, Windows Vista default) - * - * c) or for very small devices use 1 phy.sector - */ - sector_t x = 0; - - if (fdisk_dev_has_topology(cxt)) { - if (cxt->alignment_offset) - x = cxt->alignment_offset; - else if (cxt->io_size > 2048 * 512) - x = cxt->io_size; - } - /* default to 1MiB */ - if (!x) - x = 2048 * 512; - - sector_offset = x / cxt->sector_size; - - /* don't use huge offset on small devices */ - if (cxt->total_sectors <= sector_offset * 4) - sector_offset = cxt->phy_sector_size / cxt->sector_size; - - /* use 1MiB grain always when possible */ - if (grain < 2048 * 512) - grain = 2048 * 512; - - /* don't use huge grain on small devices */ - if (cxt->total_sectors <= (grain * 4 / cxt->sector_size)) - grain = cxt->phy_sector_size; - } -} - -/* - * Read MBR. Returns: - * -1: no 0xaa55 flag present (possibly entire disk BSD) - * 0: found or created label - * 1: I/O error - */ -static int get_boot(struct fdisk_context *cxt, int try_only) { - - disklabel = ANY_LABEL; - update_units(cxt); - - if (!check_dos_label(cxt)) - if (check_sun_label(cxt) || check_sgi_label(cxt) || check_aix_label(cxt) - || check_mac_label(cxt)) - return 0; - - if (check_osf_label(cxt)) { - /* intialize partitions for BSD as well */ - dos_init(cxt); - if (!valid_part_table_flag(cxt->mbr)) { - disklabel = OSF_LABEL; - return 0; - } - printf(_("This disk has both DOS and BSD magic.\n" - "Give the 'b' command to go to BSD mode.\n")); - return 0; - } - - if (disklabel == ANY_LABEL) { - if (try_only) - return -1; - - fprintf(stderr, - _("Device does not contain a recognized partition table\n")); -#ifdef __sparc__ - create_sunlabel(cxt); -#else - create_doslabel(cxt); -#endif - } - return 0; -} - -static int is_partition_table_changed(void) -{ - int i; - - for (i = 0; i < partitions; i++) - if (ptes[i].changed) - return 1; - return 0; -} - -static void maybe_exit(int rc, int *asked) -{ - char line[LINE_LENGTH]; - - putchar('\n'); - if (asked) - *asked = 0; - - if (is_partition_table_changed() || MBRbuffer_changed) { - fprintf(stderr, _("Do you really want to quit? ")); - - if (!fgets(line, LINE_LENGTH, stdin) || rpmatch(line) == 1) - exit(rc); - if (asked) - *asked = 1; - } else - exit(rc); -} - -/* read line; return 0 or first char */ -int -read_line(int *asked) -{ - line_ptr = line_buffer; - if (!fgets(line_buffer, LINE_LENGTH, stdin)) { - maybe_exit(1, asked); - return 0; - } - if (asked) - *asked = 0; - while (*line_ptr && !isgraph(*line_ptr)) - line_ptr++; - return *line_ptr; -} - -char -read_char(char *mesg) -{ - do { - fputs(mesg, stdout); - fflush (stdout); /* requested by niles@scyld.com */ - } while (!read_line(NULL)); - return *line_ptr; -} - -char -read_chars(char *mesg) -{ - int rc, asked = 0; - - do { - fputs(mesg, stdout); - fflush (stdout); /* niles@scyld.com */ - rc = read_line(&asked); - } while (asked); - - if (!rc) { - *line_ptr = '\n'; - line_ptr[1] = 0; - } - 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; - } - } -} - -unsigned int -read_int_with_suffix(struct fdisk_context *cxt, - unsigned int low, unsigned int dflt, unsigned int high, - unsigned int base, char *mesg, int *is_suffix_used) -{ - unsigned int res; - int default_ok = 1; - int absolute = 0; - static char *ms = NULL; - static size_t mslen = 0; - - if (!ms || strlen(mesg)+100 > mslen) { - mslen = strlen(mesg)+200; - ms = xrealloc(ms,mslen); - } - - if (dflt < low || dflt > high) - default_ok = 0; - - if (default_ok) - snprintf(ms, mslen, _("%s (%u-%u, default %u): "), - mesg, low, high, dflt); - else - snprintf(ms, mslen, "%s (%u-%u): ", - mesg, low, high); - - while (1) { - int use_default = default_ok; - - /* ask question and read answer */ - while (read_chars(ms) != '\n' && !isdigit(*line_ptr) - && *line_ptr != '-' && *line_ptr != '+') - continue; - - if (*line_ptr == '+' || *line_ptr == '-') { - int minus = (*line_ptr == '-'); - int suflen; - - absolute = 0; - res = atoi(line_ptr + 1); - - while (isdigit(*++line_ptr)) - use_default = 0; - - while (isspace(*line_ptr)) - line_ptr++; - - suflen = strlen(line_ptr) - 1; - - while(isspace(*(line_ptr + suflen))) - *(line_ptr + suflen--) = '\0'; - - if ((*line_ptr == 'C' || *line_ptr == 'c') && - *(line_ptr + 1) == '\0') { - /* - * Cylinders - */ - if (!display_in_cyl_units) - res *= cxt->geom.heads * cxt->geom.sectors; - } else if (*line_ptr && - *(line_ptr + 1) == 'B' && - *(line_ptr + 2) == '\0') { - /* - * 10^N - */ - if (*line_ptr == 'K') - absolute = 1000; - else if (*line_ptr == 'M') - absolute = 1000000; - else if (*line_ptr == 'G') - absolute = 1000000000; - else - absolute = -1; - } else if (*line_ptr && - *(line_ptr + 1) == '\0') { - /* - * 2^N - */ - if (*line_ptr == 'K') - absolute = 1 << 10; - else if (*line_ptr == 'M') - absolute = 1 << 20; - else if (*line_ptr == 'G') - absolute = 1 << 30; - else - absolute = -1; - } else if (*line_ptr != '\0') - absolute = -1; - - if (absolute == -1) { - printf(_("Unsupported suffix: '%s'.\n"), line_ptr); - printf(_("Supported: 10^N: KB (KiloByte), MB (MegaByte), GB (GigaByte)\n" - " 2^N: K (KibiByte), M (MebiByte), G (GibiByte)\n")); - continue; - } - - if (absolute && res) { - unsigned long long bytes; - unsigned long unit; - - bytes = (unsigned long long) res * absolute; - unit = cxt->sector_size * units_per_sector; - bytes += unit/2; /* round */ - bytes /= unit; - res = bytes; - } - if (minus) - res = -res; - res += base; - } else { - res = atoi(line_ptr); - while (isdigit(*line_ptr)) { - line_ptr++; - use_default = 0; - } - } - if (use_default) { - printf(_("Using default value %u\n"), dflt); - return dflt; - } - if (res >= low && res <= high) - break; - else - printf(_("Value out of range.\n")); - } - if (is_suffix_used) - *is_suffix_used = absolute > 0; - return res; -} - -/* - * Print the message MESG, then read an integer in LOW..HIGH. - * If the user hits Enter, DFLT is returned, provided that is in LOW..HIGH. - * Answers like +10 are interpreted as offsets from BASE. - * - * There is no default if DFLT is not between LOW and HIGH. - */ -unsigned int -read_int(struct fdisk_context *cxt, - unsigned int low, unsigned int dflt, unsigned int high, - unsigned int base, char *mesg) -{ - return read_int_with_suffix(cxt, low, dflt, high, base, mesg, NULL); -} - -int -get_partition_dflt(struct fdisk_context *cxt, int warn, int max, int dflt) { - struct pte *pe; - int i; - - i = read_int(cxt, 1, dflt, max, 0, _("Partition number")) - 1; - pe = &ptes[i]; - - if (warn) { - if ((disklabel != SUN_LABEL && disklabel != SGI_LABEL && !pe->part_table->sys_ind) - || (disklabel == SUN_LABEL && - (!sunlabel->partitions[i].num_sectors || - !sunlabel->part_tags[i].tag)) - || (disklabel == SGI_LABEL && (!sgi_get_num_sectors(cxt, i))) - ) - fprintf(stderr, - _("Warning: partition %d has empty type\n"), - i+1); - } - return i; -} - -int -get_partition(struct fdisk_context *cxt, int warn, int max) { - return get_partition_dflt(cxt, warn, max, 0); -} - -/* User partition selection unless one partition only is available */ - -static int -get_existing_partition(struct fdisk_context *cxt, int warn, int max) { - int pno = -1; - int i; - - if (disklabel != DOS_LABEL) - goto not_implemented; - - for (i = 0; i < max; i++) { - struct pte *pe = &ptes[i]; - struct partition *p = pe->part_table; - - if (p && !is_cleared_partition(p)) { - if (pno >= 0) - goto not_unique; - pno = i; - } - } - - if (pno >= 0) { - printf(_("Selected partition %d\n"), pno+1); - return pno; - } - printf(_("No partition is defined yet!\n")); - return -1; - -not_implemented: -not_unique: - return get_partition(cxt, warn, max); -} - -const char * -str_units(int n) -{ - if (display_in_cyl_units) - return P_("cylinder", "cylinders", n); - return P_("sector", "sectors", n); -} - -void change_units(struct fdisk_context *cxt) -{ - display_in_cyl_units = !display_in_cyl_units; - update_units(cxt); - - if (display_in_cyl_units) - printf(_("Changing display/entry units to cylinders (DEPRECATED!)\n")); - else - printf(_("Changing display/entry units to sectors\n")); -} - -static void -toggle_active(int i) { - struct pte *pe = &ptes[i]; - struct partition *p = pe->part_table; - - if (IS_EXTENDED (p->sys_ind) && !p->boot_ind) - fprintf(stderr, - _("WARNING: Partition %d is an extended partition\n"), - i + 1); - p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG); - pe->changed = 1; -} - -static void -toggle_dos_compatibility_flag(struct fdisk_context *cxt) { - dos_compatible_flag = ~dos_compatible_flag; - if (dos_compatible_flag) - printf(_("DOS Compatibility flag is set (DEPRECATED!)\n")); - else - printf(_("DOS Compatibility flag is not set\n")); - - update_sector_offset(cxt); -} - -static void -delete_partition(struct fdisk_context *cxt, int i) -{ - if (i < 0) - return; - - if (warn_geometry(cxt)) - return; /* C/H/S not set */ - - ptes[i].changed = 1; - - if (disklabel == DOS_LABEL) - dos_delete_partition(i); - else if (disklabel == SUN_LABEL) - sun_delete_partition(cxt, i); - else if (disklabel == SGI_LABEL) - sgi_delete_partition(cxt, i); - - printf(_("Partition %d is deleted\n"), i + 1); -} - -static void change_sysid(struct fdisk_context *cxt) -{ - char *temp; - int i, sys, origsys; - struct partition *p; - - i = get_existing_partition(cxt, 0, partitions); - - if (i == -1) - return; - p = ptes[i].part_table; - origsys = sys = get_sysid(cxt, i); - - /* if changing types T to 0 is allowed, then - the reverse change must be allowed, too */ - if (!sys && disklabel != SGI_LABEL && disklabel != SUN_LABEL && !get_nr_sects(p)) - printf(_("Partition %d does not exist yet!\n"), i + 1); - else while (1) { - sys = read_hex (get_sys_types()); - - if (!sys && disklabel != SGI_LABEL && disklabel != SUN_LABEL) { - printf(_("Type 0 means free space to many systems\n" - "(but not to Linux). Having partitions of\n" - "type 0 is probably unwise. You can delete\n" - "a partition using the `d' command.\n")); - /* break; */ - } - - if (disklabel != SGI_LABEL && disklabel != 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 (disklabel == SUN_LABEL && i == 2 && sys != SUN_TAG_BACKUP) - printf(_("Consider leaving partition 3 " - "as Whole disk (5),\n" - "as SunOS/Solaris expects it and " - "even Linux likes it.\n\n")); - if (disklabel == SGI_LABEL && ((i == 10 && sys != ENTIRE_DISK) - || (i == 8 && sys != 0))) - printf(_("Consider leaving partition 9 " - "as volume header (0),\nand " - "partition 11 as entire volume (6), " - "as IRIX expects it.\n\n")); - if (sys == origsys) - break; - if (disklabel == SUN_LABEL) { - ptes[i].changed = sun_change_sysid(cxt, i, sys); - } else - if (disklabel == SGI_LABEL) { - ptes[i].changed = sgi_change_sysid(cxt, i, sys); - } else { - p->sys_ind = sys; - ptes[i].changed = 1; - } - temp = partition_type(sys) ? : _("Unknown"); - if (ptes[i].changed) - printf (_("Changed system type of partition %d " - "to %x (%s)\n"), i + 1, sys, temp); - else - printf (_("System type of partition %d is unchanged: " - "%x (%s)\n"), i + 1, sys, temp); - if (is_dos_partition(origsys) || - is_dos_partition(sys)) - dos_changed = 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(struct fdisk_context *cxt, unsigned long ls, - unsigned int *c, unsigned int *h, unsigned int *s) { - int spc = cxt->geom.heads * cxt->geom.sectors; - - *c = ls / spc; - ls = ls % spc; - *h = ls / cxt->geom.sectors; - *s = ls % cxt->geom.sectors + 1; /* sectors count from 1 */ -} - -static void check_consistency(struct fdisk_context *cxt, struct partition *p, int partition) { - unsigned int pbc, pbh, pbs; /* physical beginning c, h, s */ - unsigned int pec, peh, pes; /* physical ending c, h, s */ - unsigned int lbc, lbh, lbs; /* logical beginning c, h, s */ - unsigned int lec, leh, les; /* logical ending c, h, s */ - - if (!dos_compatible_flag) - return; - - if (!cxt->geom.heads || !cxt->geom.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(cxt, get_start_sect(p), &lbc, &lbh, &lbs); - -/* compute logical ending (c, h, s) */ - long2chs(cxt, get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les); - -/* Same physical / logical beginning? */ - if (cxt->geom.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 (cxt->geom.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); - } - -/* Ending on cylinder boundary? */ - if (peh != (cxt->geom.heads - 1) || pes != cxt->geom.sectors) { - printf(_("Partition %i does not end on cylinder boundary.\n"), - partition + 1); - } -} - -static void -check_alignment(struct fdisk_context *cxt, sector_t lba, int partition) -{ - if (!lba_is_aligned(cxt, lba)) - printf(_("Partition %i does not start on physical sector boundary.\n"), - partition + 1); -} - -static void -list_disk_geometry(struct fdisk_context *cxt) { - unsigned long long bytes = cxt->total_sectors * cxt->sector_size; - long megabytes = bytes/1000000; - - if (megabytes < 10000) - printf(_("\nDisk %s: %ld MB, %lld bytes\n"), - cxt->dev_path, megabytes, bytes); - else { - long hectomega = (megabytes + 50) / 100; - printf(_("\nDisk %s: %ld.%ld GB, %llu bytes\n"), - cxt->dev_path, hectomega / 10, hectomega % 10, bytes); - } - printf(_("%d heads, %llu sectors/track, %llu cylinders"), - cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders); - if (units_per_sector == 1) - printf(_(", total %llu sectors"), cxt->total_sectors); - printf("\n"); - printf(_("Units = %s of %d * %ld = %ld bytes\n"), - str_units(PLURAL), - units_per_sector, cxt->sector_size, units_per_sector * cxt->sector_size); - - printf(_("Sector size (logical/physical): %lu bytes / %lu bytes\n"), - cxt->sector_size, cxt->phy_sector_size); - printf(_("I/O size (minimum/optimal): %lu bytes / %lu bytes\n"), - cxt->min_io_size, cxt->io_size); - if (cxt->alignment_offset) - printf(_("Alignment offset: %lu bytes\n"), cxt->alignment_offset); - if (disklabel == DOS_LABEL) - dos_print_mbr_id(cxt); - printf("\n"); -} - -/* - * Check whether partition entries are ordered by their starting positions. - * Return 0 if OK. Return i if partition i should have been earlier. - * Two separate checks: primary and logical partitions. - */ -static int -wrong_p_order(int *prev) { - struct pte *pe; - struct partition *p; - unsigned int last_p_start_pos = 0, p_start_pos; - int i, last_i = 0; - - for (i = 0 ; i < partitions; i++) { - if (i == 4) { - last_i = 4; - last_p_start_pos = 0; - } - pe = &ptes[i]; - if ((p = pe->part_table)->sys_ind) { - p_start_pos = get_partition_start(pe); - - if (last_p_start_pos > p_start_pos) { - if (prev) - *prev = last_i; - return i; - } - - last_p_start_pos = p_start_pos; - last_i = i; - } - } - return 0; -} - -/* - * Fix the chain of logicals. - * extended_offset is unchanged, the set of sectors used is unchanged - * The chain is sorted so that sectors increase, and so that - * starting sectors increase. - * - * After this it may still be that cfdisk doesn't like the table. - * (This is because cfdisk considers expanded parts, from link to - * end of partition, and these may still overlap.) - * Now - * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda - * may help. - */ -static void -fix_chain_of_logicals(void) { - int j, oj, ojj, sj, sjj; - struct partition *pj,*pjj,tmp; - - /* Stage 1: sort sectors but leave sector of part 4 */ - /* (Its sector is the global extended_offset.) */ - stage1: - for (j = 5; j < partitions-1; j++) { - oj = ptes[j].offset; - ojj = ptes[j+1].offset; - if (oj > ojj) { - ptes[j].offset = ojj; - ptes[j+1].offset = oj; - pj = ptes[j].part_table; - set_start_sect(pj, get_start_sect(pj)+oj-ojj); - pjj = ptes[j+1].part_table; - set_start_sect(pjj, get_start_sect(pjj)+ojj-oj); - set_start_sect(ptes[j-1].ext_pointer, - ojj-extended_offset); - set_start_sect(ptes[j].ext_pointer, - oj-extended_offset); - goto stage1; - } - } - - /* Stage 2: sort starting sectors */ - stage2: - for (j = 4; j < partitions-1; j++) { - pj = ptes[j].part_table; - pjj = ptes[j+1].part_table; - sj = get_start_sect(pj); - sjj = get_start_sect(pjj); - oj = ptes[j].offset; - ojj = ptes[j+1].offset; - if (oj+sj > ojj+sjj) { - tmp = *pj; - *pj = *pjj; - *pjj = tmp; - set_start_sect(pj, ojj+sjj-oj); - set_start_sect(pjj, oj+sj-ojj); - goto stage2; - } - } - - /* Probably something was changed */ - for (j = 4; j < partitions; j++) - ptes[j].changed = 1; -} - -static void -fix_partition_table_order(void) { - struct pte *pei, *pek; - int i,k; - - if (!wrong_p_order(NULL)) { - printf(_("Nothing to do. Ordering is correct already.\n\n")); - return; - } - - while ((i = wrong_p_order(&k)) != 0 && i < 4) { - /* partition i should have come earlier, move it */ - /* We have to move data in the MBR */ - struct partition *pi, *pk, *pe, pbuf; - pei = &ptes[i]; - pek = &ptes[k]; - - pe = pei->ext_pointer; - pei->ext_pointer = pek->ext_pointer; - pek->ext_pointer = pe; - - pi = pei->part_table; - pk = pek->part_table; - - memmove(&pbuf, pi, sizeof(struct partition)); - memmove(pi, pk, sizeof(struct partition)); - memmove(pk, &pbuf, sizeof(struct partition)); - - pei->changed = pek->changed = 1; - } - - if (i) - fix_chain_of_logicals(); - - printf(_("Done.\n")); - -} - -static void -list_table(struct fdisk_context *cxt, int xtra) { - struct partition *p; - char *type; - int i, w; - - if (disklabel == SUN_LABEL) { - sun_list_table(cxt, xtra); - return; - } - - if (disklabel == SGI_LABEL) { - sgi_list_table(cxt, xtra); - return; - } - - list_disk_geometry(cxt); - - if (disklabel == OSF_LABEL) { - xbsd_print_disklabel(cxt, xtra); - return; - } - - if (is_garbage_table()) { - printf(_("This doesn't look like a partition table\n" - "Probably you selected the wrong device.\n\n")); - } - - /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3, - but if the device name ends in a digit, say /dev/foo1, - then the partition is called /dev/foo1p3. */ - w = strlen(cxt->dev_path); - if (w && isdigit(cxt->dev_path[w-1])) - w++; - if (w < 5) - w = 5; - - printf(_("%*s Boot Start End Blocks Id System\n"), - w+1, _("Device")); - - for (i = 0; i < partitions; i++) { - struct pte *pe = &ptes[i]; - - p = pe->part_table; - if (p && !is_cleared_partition(p)) { - unsigned int psects = get_nr_sects(p); - unsigned int pblocks = psects; - unsigned int podd = 0; - - if (cxt->sector_size < 1024) { - pblocks /= (1024 / cxt->sector_size); - podd = psects % (1024 / cxt->sector_size); - } - if (cxt->sector_size > 1024) - pblocks *= (cxt->sector_size / 1024); - printf( - "%s %c %11lu %11lu %11lu%c %2x %s\n", - partname(cxt->dev_path, i+1, w+2), -/* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG - ? '*' : '?', -/* start */ (unsigned long) cround(get_partition_start(pe)), -/* end */ (unsigned long) cround(get_partition_start(pe) + psects - - (psects ? 1 : 0)), -/* odd flag on end */ (unsigned long) pblocks, podd ? '+' : ' ', -/* type id */ p->sys_ind, -/* type name */ (type = partition_type(p->sys_ind)) ? - type : _("Unknown")); - check_consistency(cxt, p, i); - check_alignment(cxt, get_partition_start(pe), i); - } - } - - /* Is partition table in disk order? It need not be, but... */ - /* partition table entries are not checked for correct order if this - is a sgi, sun or aix labeled disk... */ - if (disklabel == DOS_LABEL && wrong_p_order(NULL)) { - printf(_("\nPartition table entries are not in disk order\n")); - } -} - -static void -x_list_table(struct fdisk_context *cxt, int extend) { - struct pte *pe; - struct partition *p; - int i; - - printf(_("\nDisk %s: %d heads, %llu sectors, %llu cylinders\n\n"), - cxt->dev_path, cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders); - printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n")); - for (i = 0 ; i < partitions; i++) { - pe = &ptes[i]; - p = (extend ? pe->ext_pointer : pe->part_table); - if (p != NULL) { - printf("%2d %02x%4d%4d%5d%4d%4d%5d%11lu%11lu %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), - (unsigned long) get_start_sect(p), - (unsigned long) get_nr_sects(p), p->sys_ind); - if (p->sys_ind) { - check_consistency(cxt, p, i); - check_alignment(cxt, get_partition_start(pe), i); - } - } - } -} - -void fill_bounds(sector_t *first, sector_t *last) -{ - int i; - struct pte *pe = &ptes[0]; - struct partition *p; - - for (i = 0; i < partitions; pe++,i++) { - p = pe->part_table; - if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) { - first[i] = 0xffffffff; - last[i] = 0; - } else { - first[i] = get_partition_start(pe); - last[i] = first[i] + get_nr_sects(p) - 1; - } - } -} - -static void -check(struct fdisk_context *cxt, int n, unsigned int h, unsigned int s, unsigned int c, - unsigned int start) { - unsigned int total, real_s, real_c; - - real_s = sector(s) - 1; - real_c = cylinder(s, c); - total = (real_c * cxt->geom.sectors + real_s) * cxt->geom.heads + h; - if (!total) - fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n); - if (h >= cxt->geom.heads) - fprintf(stderr, - _("Partition %d: head %d greater than maximum %d\n"), - n, h + 1, cxt->geom.heads); - if (real_s >= cxt->geom.sectors) - fprintf(stderr, _("Partition %d: sector %d greater than " - "maximum %llu\n"), n, s, cxt->geom.sectors); - if (real_c >= cxt->geom.cylinders) - fprintf(stderr, _("Partitions %d: cylinder %d greater than " - "maximum %llu\n"), n, real_c + 1, cxt->geom.cylinders); - if (cxt->geom.cylinders <= 1024 && start != total) - fprintf(stderr, - _("Partition %d: previous sectors %d disagrees with " - "total %d\n"), n, start, total); -} - -static void -verify(struct fdisk_context *cxt) { - int i, j; - sector_t total = 1, n_sectors = cxt->total_sectors; - unsigned long long first[partitions], last[partitions]; - struct partition *p; - - if (warn_geometry(cxt)) - return; - - if (disklabel == SUN_LABEL) { - verify_sun(cxt); - return; - } - - if (disklabel == SGI_LABEL) { - verify_sgi(cxt, 1); - return; - } - - fill_bounds(first, last); - for (i = 0; i < partitions; i++) { - struct pte *pe = &ptes[i]; - - p = pe->part_table; - if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) { - check_consistency(cxt, p, i); - check_alignment(cxt, get_partition_start(pe), i); - if (get_partition_start(pe) < first[i]) - printf(_("Warning: bad start-of-data in " - "partition %d\n"), i + 1); - check(cxt, 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) { - struct pte *pex = &ptes[ext_index]; - sector_t e_last = get_start_sect(pex->part_table) + - get_nr_sects(pex->part_table) - 1; - - for (i = 4; i < partitions; i++) { - total++; - p = ptes[i].part_table; - 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 > n_sectors) - printf(_("Total allocated sectors %llu greater than the maximum" - " %llu\n"), total, n_sectors); - else if (total < n_sectors) - printf(_("Remaining %lld unallocated %ld-byte sectors\n"), - n_sectors - total, cxt->sector_size); -} - -void print_partition_size(struct fdisk_context *cxt, - int num, sector_t start, sector_t stop, int sysid) -{ - char *str = size_to_human_string(SIZE_SUFFIX_3LETTER | SIZE_SUFFIX_SPACE, - (stop - start + 1) * cxt->sector_size); - printf(_("Partition %d of type %s and of size %s is set\n"), num, partition_type(sysid), str); - free(str); -} - -static void new_partition(struct fdisk_context *cxt) -{ - if (warn_geometry(cxt)) - return; - - if (disklabel == SUN_LABEL) { - add_sun_partition(cxt, get_partition(cxt, 0, partitions), LINUX_NATIVE); - return; - } - - if (disklabel == SGI_LABEL) { - sgi_add_partition(cxt, get_partition(cxt, 0, partitions), LINUX_NATIVE); - return; - } - - if (disklabel == AIX_LABEL) { - printf(_("\tSorry - this fdisk cannot handle AIX disk labels." - "\n\tIf you want to add DOS-type partitions, create" - "\n\ta new empty DOS partition table first. (Use o.)" - "\n\tWARNING: " - "This will destroy the present disk contents.\n")); - return; - } - - if (disklabel == MAC_LABEL) { - printf(_("\tSorry - this fdisk cannot handle Mac disk labels." - "\n\tIf you want to add DOS-type partitions, create" - "\n\ta new empty DOS partition table first. (Use o.)" - "\n\tWARNING: " - "This will destroy the present disk contents.\n")); - return; - } - - /* default to DOS/BSD */ - dos_new_partition(cxt); -} - -static void -write_table(struct fdisk_context *cxt) { - int i; - - if (disklabel == DOS_LABEL) - dos_write_table(cxt); - else if (disklabel == SGI_LABEL) - /* no test on change? the printf below might be mistaken */ - sgi_write_table(cxt); - else if (disklabel == SUN_LABEL) { - int needw = 0; - - for (i=0; i<8; i++) - if (ptes[i].changed) - needw = 1; - if (needw) - sun_write_table(cxt); - } - - printf(_("The partition table has been altered!\n\n")); - reread_partition_table(cxt, 1); -} - -void -reread_partition_table(struct fdisk_context *cxt, int leave) { - int i; - struct stat statbuf; - - i = fstat(cxt->dev_fd, &statbuf); - if (i == 0 && S_ISBLK(statbuf.st_mode)) { - sync(); -#ifdef BLKRRPART - printf(_("Calling ioctl() to re-read partition table.\n")); - i = ioctl(cxt->dev_fd, BLKRRPART); -#else - errno = ENOSYS; - i = 1; -#endif - } - - if (i) { - printf(_("\nWARNING: Re-reading the partition table failed with error %d: %m.\n" - "The kernel still uses the old table. The new table will be used at\n" - "the next reboot or after you run partprobe(8) or kpartx(8)\n"), - errno); - } - - if (dos_changed) - 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")); - - if (leave) { - if (fsync(cxt->dev_fd) || close(cxt->dev_fd)) { - fprintf(stderr, _("\nError closing file\n")); - exit(1); - } - - printf(_("Syncing disks.\n")); - sync(); - exit(!!i); - } -} - -#define MAX_PER_LINE 16 -static void -print_buffer(struct fdisk_context *cxt, unsigned char pbuffer[]) { - unsigned int i, l; - - for (i = 0, l = 0; i < cxt->sector_size; i++, l++) { - if (l == 0) - printf("0x%03X:", i); - printf(" %02X", pbuffer[i]); - if (l == MAX_PER_LINE - 1) { - printf("\n"); - l = -1; - } - } - if (l > 0) - printf("\n"); - printf("\n"); -} - -static void print_raw(struct fdisk_context *cxt) -{ - int i; - - printf(_("Device: %s\n"), cxt->dev_path); - if (disklabel == SUN_LABEL || disklabel == SGI_LABEL) - print_buffer(cxt, cxt->mbr); - else for (i = 3; i < partitions; i++) - print_buffer(cxt, ptes[i].sectorbuffer); -} - -static void -move_begin(struct fdisk_context *cxt, int i) { - struct pte *pe = &ptes[i]; - struct partition *p = pe->part_table; - unsigned int new, free_start, curr_start, last; - int x; - - if (warn_geometry(cxt)) - 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; - } - - /* the default start is at the second sector of the disk or at the - * second sector of the extended partition - */ - free_start = pe->offset ? pe->offset + 1 : 1; - - curr_start = get_partition_start(pe); - - /* look for a free space before the current start of the partition */ - for (x = 0; x < partitions; x++) { - unsigned int end; - struct pte *prev_pe = &ptes[x]; - struct partition *prev_p = prev_pe->part_table; - - if (!prev_p) - continue; - end = get_partition_start(prev_pe) + get_nr_sects(prev_p); - - if (!is_cleared_partition(prev_p) && - end > free_start && end <= curr_start) - free_start = end; - } - - last = get_partition_start(pe) + get_nr_sects(p) - 1; - - new = read_int(cxt, free_start, curr_start, last, free_start, - _("New beginning of data")) - pe->offset; - - if (new != get_nr_sects(p)) { - unsigned int sects = get_nr_sects(p) + get_start_sect(p) - new; - set_nr_sects(p, sects); - set_start_sect(p, new); - pe->changed = 1; - } -} - -static void __attribute__ ((__noreturn__)) handle_quit(struct fdisk_context *cxt) -{ - fdisk_free_context(cxt); - printf("\n"); - exit(EXIT_SUCCESS); -} - -static void -expert_command_prompt(struct fdisk_context *cxt) -{ - char c; - - while(1) { - putchar('\n'); - c = tolower(read_char(_("Expert command (m for help): "))); - switch (c) { - case 'a': - if (disklabel == SUN_LABEL) - sun_set_alt_cyl(cxt); - break; - case 'b': - if (disklabel == DOS_LABEL) - move_begin(cxt, get_partition(cxt, 0, partitions)); - break; - case 'c': - user_cylinders = cxt->geom.cylinders = - read_int(cxt, 1, cxt->geom.cylinders, 1048576, 0, - _("Number of cylinders")); - if (disklabel == SUN_LABEL) - sun_set_ncyl(cxt, cxt->geom.cylinders); - break; - case 'd': - print_raw(cxt); - break; - case 'e': - if (disklabel == SGI_LABEL) - sgi_set_xcyl(); - else if (disklabel == SUN_LABEL) - sun_set_xcyl(cxt); - else - if (disklabel == DOS_LABEL) - x_list_table(cxt, 1); - break; - case 'f': - if (disklabel == DOS_LABEL) - fix_partition_table_order(); - break; - case 'g': - create_sgilabel(cxt); - break; - case 'h': - user_heads = cxt->geom.heads = read_int(cxt, 1, cxt->geom.heads, 256, 0, - _("Number of heads")); - update_units(cxt); - break; - case 'i': - if (disklabel == SUN_LABEL) - sun_set_ilfact(cxt); - else if (disklabel == DOS_LABEL) - dos_set_mbr_id(cxt); - break; - case 'o': - if (disklabel == SUN_LABEL) - sun_set_rspeed(cxt); - break; - case 'p': - if (disklabel == SUN_LABEL) - list_table(cxt, 1); - else - x_list_table(cxt, 0); - break; - case 'q': - handle_quit(cxt); - case 'r': - return; - case 's': - user_sectors = cxt->geom.sectors = read_int(cxt, 1, cxt->geom.sectors, 63, 0, - _("Number of sectors")); - if (dos_compatible_flag) - fprintf(stderr, _("Warning: setting " - "sector offset for DOS " - "compatiblity\n")); - update_sector_offset(cxt); - update_units(cxt); - break; - case 'v': - verify(cxt); - break; - case 'w': - write_table(cxt); - break; - case 'y': - if (disklabel == SUN_LABEL) - sun_set_pcylcount(cxt); - break; - default: - print_menu(EXPERT_MENU); - } - } -} - -static int is_ide_cdrom_or_tape(char *device) -{ - int fd, ret; - - if ((fd = open(device, O_RDONLY)) < 0) - return 0; - ret = blkdev_is_cdrom(fd); - - close(fd); - return ret; -} - -static void -gpt_warning(char *dev) -{ - if (dev && gpt_probe_signature_devname(dev)) - fprintf(stderr, _("\nWARNING: GPT (GUID Partition Table) detected on '%s'! " - "The util fdisk doesn't support GPT. Use GNU Parted.\n\n"), dev); -} - -/* Print disk geometry and partition table of a specified device (-l option) */ -static void print_partition_table_from_option(char *device, unsigned long sector_size) -{ - int gb; - - struct fdisk_context *cxt = fdisk_new_context_from_filename(device, 1); /* read-only */ - if (!cxt) - err(EXIT_FAILURE, _("unable to open %s"), device); - if (sector_size) /* passed -b option, override autodiscovery */ - cxt->phy_sector_size = cxt->sector_size = sector_size; - /* passed CHS option(s), override autodiscovery */ - if (user_cylinders) - cxt->geom.cylinders = user_cylinders; - if (user_heads) { - cxt->geom.heads = user_heads; - fdisk_geom_set_cyls(cxt); - } - if (user_sectors) { - cxt->geom.sectors = user_sectors; - fdisk_geom_set_cyls(cxt); - } - - gpt_warning(device); - gb = get_boot(cxt, 1); - if (gb < 0) { /* no DOS signature */ - list_disk_geometry(cxt); - if (disklabel != AIX_LABEL && disklabel != MAC_LABEL) - btrydev(cxt); - } - else if (!gb) - list_table(cxt, 0); - fdisk_free_context(cxt); - cxt = NULL; -} - -/* - * for fdisk -l: - * try all things in /proc/partitions that look like a full disk - */ -static void -print_all_partition_table_from_option(unsigned long sector_size) -{ - FILE *procpt; - char line[128], ptname[128], devname[256]; - int ma, mi; - unsigned long long sz; - - procpt = fopen(_PATH_PROC_PARTITIONS, "r"); - if (procpt == NULL) { - fprintf(stderr, _("cannot open %s\n"), _PATH_PROC_PARTITIONS); - return; - } - - while (fgets(line, sizeof(line), procpt)) { - if (sscanf (line, " %d %d %llu %128[^\n ]", - &ma, &mi, &sz, ptname) != 4) - continue; - snprintf(devname, sizeof(devname), "/dev/%s", ptname); - if (is_whole_disk(devname)) { - char *cn = canonicalize_path(devname); - if (cn) { - if (!is_ide_cdrom_or_tape(cn)) - print_partition_table_from_option(cn, sector_size); - free(cn); - } - } - } - fclose(procpt); -} - -static void -unknown_command(int c) { - printf(_("%c: unknown command\n"), c); -} - -static void print_welcome(void) -{ - printf(_("Welcome to fdisk (%s).\n\n" - "Changes will remain in memory only, until you decide to write them.\n" - "Be careful before using the write command.\n\n"), PACKAGE_STRING); - - fflush(stdout); -} - -static void command_prompt(struct fdisk_context *cxt) -{ - int c; - - if (disklabel == OSF_LABEL) { - putchar('\n'); - /* OSF label, and no DOS label */ - printf(_("Detected an OSF/1 disklabel on %s, entering " - "disklabel mode.\n"), - cxt->dev_path); - bsd_command_prompt(cxt); - /* If we return we may want to make an empty DOS label? */ - disklabel = DOS_LABEL; - } - - while (1) { - putchar('\n'); - c = tolower(read_char(_("Command (m for help): "))); - switch (c) { - case 'a': - if (disklabel == DOS_LABEL) - toggle_active(get_partition(cxt, 1, partitions)); - else if (disklabel == SUN_LABEL) - toggle_sunflags(cxt, get_partition(cxt, 1, partitions), - SUN_FLAG_UNMNT); - else if (disklabel == SGI_LABEL) - sgi_set_bootpartition(cxt, - get_partition(cxt, 1, partitions)); - else - unknown_command(c); - break; - case 'b': - if (disklabel == SGI_LABEL) - sgi_set_bootfile(cxt); - else if (disklabel == DOS_LABEL) { - disklabel = OSF_LABEL; - bsd_command_prompt(cxt); - disklabel = DOS_LABEL; - } else - unknown_command(c); - break; - case 'c': - if (disklabel == DOS_LABEL) - toggle_dos_compatibility_flag(cxt); - else if (disklabel == SUN_LABEL) - toggle_sunflags(cxt, get_partition(cxt, 1, partitions), - SUN_FLAG_RONLY); - else if (disklabel == SGI_LABEL) - sgi_set_swappartition(cxt, - get_partition(cxt, 1, partitions)); - else - unknown_command(c); - break; - case 'd': - delete_partition(cxt, get_existing_partition(cxt, 1, partitions)); - break; - case 'i': - if (disklabel == SGI_LABEL) - create_sgiinfo(cxt); - else - unknown_command(c); - break; - case 'l': - list_types(get_sys_types()); - break; - case 'm': - print_menu(MAIN_MENU); - break; - case 'n': - new_partition(cxt); - break; - case 'o': - create_doslabel(cxt); - break; - case 'p': - list_table(cxt, 0); - break; - case 'q': - handle_quit(cxt); - case 's': - create_sunlabel(cxt); - break; - case 't': - change_sysid(cxt); - break; - case 'u': - change_units(cxt); - break; - case 'v': - verify(cxt); - break; - case 'w': - write_table(cxt); - break; - case 'x': - expert_command_prompt(cxt); - break; - default: - unknown_command(c); - print_menu(MAIN_MENU); - } - } -} - -static sector_t get_dev_blocks(char *dev) -{ - int fd; - sector_t size; - - if ((fd = open(dev, O_RDONLY)) < 0) - err(EXIT_FAILURE, _("unable to open %s"), dev); - if (blkdev_get_sectors(fd, &size) == -1) { - close(fd); - err(EXIT_FAILURE, _("BLKGETSIZE ioctl failed on %s"), dev); - } - close(fd); - return size/2; -} - -int main(int argc, char **argv) -{ - int c, optl = 0, opts = 0; - unsigned long sector_size = 0; - struct fdisk_context *cxt = NULL; - - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - atexit(close_stdout); - - while ((c = getopt(argc, argv, "b:c::C:hH:lsS:u::vV")) != -1) { - switch (c) { - case 'b': - /* Ugly: this sector size is really per device, - so cannot be combined with multiple disks, - and te same goes for the C/H/S options. - */ - sector_size = strtou32_or_err(optarg, _("invalid sector size argument")); - if (sector_size != 512 && sector_size != 1024 && - sector_size != 2048 && sector_size != 4096) - usage(stderr); - sector_offset = 2; - break; - case 'C': - user_cylinders = strtou32_or_err(optarg, _("invalid cylinders argument")); - break; - case 'c': - dos_compatible_flag = 0; /* default */ - - if (optarg && !strcmp(optarg, "=dos")) - dos_compatible_flag = ~0; - else if (optarg && strcmp(optarg, "=nondos")) - usage(stderr); - break; - case 'H': - user_heads = strtou32_or_err(optarg, _("invalid heads argument")); - if (user_heads > 256) - user_heads = 0; - break; - case 'S': - user_sectors = strtou32_or_err(optarg, _("invalid sectors argument")); - if (user_sectors >= 64) - user_sectors = 0; - break; - case 'l': - optl = 1; - break; - case 's': - opts = 1; - break; - case 'u': - display_in_cyl_units = 0; /* default */ - if (optarg && strcmp(optarg, "=cylinders") == 0) - display_in_cyl_units = !display_in_cyl_units; - else if (optarg && strcmp(optarg, "=sectors")) - usage(stderr); - break; - case 'V': - case 'v': - printf(UTIL_LINUX_VERSION); - return EXIT_SUCCESS; - case 'h': - usage(stdout); - default: - usage(stderr); - } - } - - fdisk_init_debug(0); - - if (sector_size && argc-optind != 1) - printf(_("Warning: the -b (set sector size) option should" - " be used with one specified device\n")); - - if (optl) { - nowarn = 1; - if (argc > optind) { - int k; - for (k = optind; k < argc; k++) - print_partition_table_from_option(argv[k], sector_size); - } else - print_all_partition_table_from_option(sector_size); - exit(EXIT_SUCCESS); - } - - if (opts) { - /* print partition size for one or more devices */ - int i, ndevs = argc - optind; - if (ndevs <= 0) - usage(stderr); - - for (i = optind; i < argc; i++) { - if (ndevs == 1) - printf("%llu\n", get_dev_blocks(argv[i])); - else - printf("%s: %llu\n", argv[i], get_dev_blocks(argv[i])); - } - exit(EXIT_SUCCESS); - } - - if (argc-optind == 1) { - cxt = fdisk_new_context_from_filename(argv[optind], 0); - if (!cxt) - err(EXIT_FAILURE, _("unable to open %s"), argv[optind]); - if (sector_size) /* passed -b option, override autodiscovery */ - cxt->phy_sector_size = cxt->sector_size = sector_size; - /* passed CHS option(s), override autodiscovery */ - if (user_cylinders) - cxt->geom.cylinders = user_cylinders; - if (user_heads) { - cxt->geom.heads = user_heads; - fdisk_geom_set_cyls(cxt); - } - if (user_sectors) { - cxt->geom.sectors = user_sectors; - fdisk_geom_set_cyls(cxt); - } - } - else - usage(stderr); - - print_welcome(); - - if (!fdisk_dev_sectsz_is_default(cxt)) - printf(_("Note: sector size is %ld (not %d)\n"), - cxt->sector_size, DEFAULT_SECTOR_SIZE); - - gpt_warning(cxt->dev_path); - get_boot(cxt, 0); - - command_prompt(cxt); - - return 0; -} diff --git a/fdisk/fdisk.h b/fdisk/fdisk.h deleted file mode 100644 index 51a63b228..000000000 --- a/fdisk/fdisk.h +++ /dev/null @@ -1,253 +0,0 @@ -/* - fdisk.h -*/ - -#include "c.h" - -#define DEFAULT_SECTOR_SIZE 512 -#define MAX_SECTOR_SIZE 2048 -#define SECTOR_SIZE 512 /* still used in BSD code */ -#define MAXIMUM_PARTS 60 - -#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 LINUX_LVM 0x8e -#define LINUX_RAID 0xfd - -#define ALIGN_UP 1 -#define ALIGN_DOWN 2 -#define ALIGN_NEAREST 3 - -#define LINE_LENGTH 800 - -#define IS_EXTENDED(i) \ - ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED) - -#define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n)) -#define scround(x) (((x)+units_per_sector-1)/units_per_sector) - -/* fdisk debugging flags/options */ -#define FDISK_DEBUG_INIT (1 << 1) -#define FDISK_DEBUG_CONTEXT (1 << 2) -#define FDISK_DEBUG_TOPOLOGY (1 << 3) -#define FDISK_DEBUG_GEOMETRY (1 << 4) -#define FDISK_DEBUG_ALL 0xFFFF - -# define ON_DBG(m, x) do { \ - if ((FDISK_DEBUG_ ## m) & fdisk_debug_mask) { \ - x; \ - } \ - } while (0) - -# define DBG(m, x) do { \ - if ((FDISK_DEBUG_ ## m) & fdisk_debug_mask) { \ - fprintf(stderr, "%d: fdisk: %8s: ", getpid(), # m); \ - x; \ - } \ - } while (0) - -# define DBG_FLUSH do { \ - if (fdisk_debug_mask && \ - fdisk_debug_mask != FDISK_DEBUG_INIT) \ - fflush(stderr); \ - } while(0) - -static inline void __attribute__ ((__format__ (__printf__, 1, 2))) -dbgprint(const char *mesg, ...) -{ - va_list ap; - va_start(ap, mesg); - vfprintf(stderr, mesg, ap); - va_end(ap); - fputc('\n', stderr); -} - -extern int fdisk_debug_mask; -extern void fdisk_init_debug(int mask); - -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 */ -} __attribute__ ((packed)); - -enum menutype { - MAIN_MENU, - EXPERT_MENU, -}; - -enum failure { - ioctl_error, - unable_to_read, - unable_to_seek, - unable_to_write -}; - -typedef unsigned long long sector_t; - -/* - * Legacy CHS based geometry - */ -struct fdisk_geometry { - unsigned int heads; - sector_t sectors; - sector_t cylinders; -}; - -struct fdisk_context { - int dev_fd; /* device descriptor */ - char *dev_path; /* device path */ - unsigned char *mbr; /* buffer with master boot record */ - - /* topology */ - unsigned long io_size; /* I/O size used by fdisk */ - unsigned long optimal_io_size; /* optional I/O returned by device */ - unsigned long min_io_size; /* minimal I/O size */ - unsigned long phy_sector_size; /* physical size */ - unsigned long sector_size; /* logical size */ - unsigned long alignment_offset; - - /* geometry */ - sector_t total_sectors; /* in logical sectors */ - struct fdisk_geometry geom; -}; - -extern struct fdisk_context *fdisk_new_context_from_filename(const char *fname, int readonly); -extern int fdisk_dev_has_topology(struct fdisk_context *cxt); -extern int fdisk_dev_sectsz_is_default(struct fdisk_context *cxt); -extern void fdisk_free_context(struct fdisk_context *cxt); -extern void fdisk_mbr_zeroize(struct fdisk_context *cxt); -extern void fdisk_geom_set_cyls(struct fdisk_context *cxt); - -/* prototypes for fdisk.c */ -extern char *disk_device, *line_ptr; -extern int fd, partitions; -extern unsigned int display_in_cyl_units, units_per_sector; -extern void change_units(struct fdisk_context *cxt); -extern void fatal(struct fdisk_context *cxt, enum failure why); -extern int get_partition(struct fdisk_context *cxt, int warn, int max); -extern void list_types(struct systypes *sys); -extern int read_line (int *asked); -extern char read_char(char *mesg); -extern int read_hex(struct systypes *sys); -extern void reread_partition_table(struct fdisk_context *cxt, int leave); -extern struct partition *get_part_table(int); -extern int valid_part_table_flag(unsigned char *b); -extern unsigned int read_int(struct fdisk_context *cxt, - unsigned int low, unsigned int dflt, - unsigned int high, unsigned int base, char *mesg); -extern void print_menu(enum menutype); -extern void print_partition_size(struct fdisk_context *cxt, int num, sector_t start, sector_t stop, int sysid); - -extern void fill_bounds(sector_t *first, sector_t *last); -extern unsigned int heads, cylinders; -extern sector_t sectors; -extern char *partition_type(unsigned char type); -extern void update_units(struct fdisk_context *cxt); -extern char read_chars(char *mesg); -extern void set_changed(int); -extern void set_all_unchanged(void); -extern int warn_geometry(struct fdisk_context *cxt); -extern void warn_limits(struct fdisk_context *cxt); -extern void warn_alignment(struct fdisk_context *cxt); -extern unsigned int read_int_with_suffix(struct fdisk_context *cxt, - unsigned int low, unsigned int dflt, unsigned int high, - unsigned int base, char *mesg, int *is_suffix_used); -extern sector_t align_lba(struct fdisk_context *cxt, sector_t lba, int direction); -extern int get_partition_dflt(struct fdisk_context *cxt, int warn, int max, int dflt); -extern void update_sector_offset(struct fdisk_context *cxt); -extern void get_partition_table_geometry(struct fdisk_context *cxt, - unsigned int *ph, unsigned int *ps); - -#define PLURAL 0 -#define SINGULAR 1 -extern const char * str_units(int); - -extern sector_t get_nr_sects(struct partition *p); - -enum labeltype { - DOS_LABEL = 1, - SUN_LABEL = 2, - SGI_LABEL = 4, - AIX_LABEL = 8, - OSF_LABEL = 16, - MAC_LABEL = 32, - ANY_LABEL = -1 -}; - -extern enum labeltype disklabel; -extern int MBRbuffer_changed; -extern unsigned long grain; - -/* start_sect and nr_sects are stored little endian on all machines */ -/* moreover, they are not aligned correctly */ -static inline 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); -} - -static inline unsigned int read4_little_endian(const unsigned char *cp) -{ - return (unsigned int)(cp[0]) + ((unsigned int)(cp[1]) << 8) - + ((unsigned int)(cp[2]) << 16) - + ((unsigned int)(cp[3]) << 24); -} - -static inline void set_nr_sects(struct partition *p, sector_t nr_sects) -{ - store4_little_endian(p->size4, nr_sects); -} - -static inline void set_start_sect(struct partition *p, unsigned int start_sect) -{ - store4_little_endian(p->start4, start_sect); -} - -static inline void seek_sector(struct fdisk_context *cxt, sector_t secno) -{ - off_t offset = (off_t) secno * cxt->sector_size; - if (lseek(cxt->dev_fd, offset, SEEK_SET) == (off_t) -1) - fatal(cxt, unable_to_seek); -} - -static inline void read_sector(struct fdisk_context *cxt, sector_t secno, unsigned char *buf) -{ - seek_sector(cxt, secno); - if (read(cxt->dev_fd, buf, cxt->sector_size) != (ssize_t) cxt->sector_size) - fatal(cxt, unable_to_read); -} - -static inline void write_sector(struct fdisk_context *cxt, sector_t secno, unsigned char *buf) -{ - seek_sector(cxt, secno); - if (write(cxt->dev_fd, buf, cxt->sector_size) != (ssize_t) cxt->sector_size) - fatal(cxt, unable_to_write); -} - -static inline sector_t get_start_sect(struct partition *p) -{ - return read4_little_endian(p->start4); -} - -static inline int is_cleared_partition(struct partition *p) -{ - return !(!p || p->boot_ind || p->head || p->sector || p->cyl || - p->sys_ind || p->end_head || p->end_sector || p->end_cyl || - get_start_sect(p) || get_nr_sects(p)); -} diff --git a/fdisk/fdiskaixlabel.c b/fdisk/fdiskaixlabel.c deleted file mode 100644 index fb36489e1..000000000 --- a/fdisk/fdiskaixlabel.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - Changes: - Sat Mar 20 09:51:38 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br> - Internationalization -*/ -#include <stdio.h> /* stderr */ -#include <string.h> /* strstr */ -#include <unistd.h> /* write */ - -#include <endian.h> - -#include "common.h" -#include "fdisk.h" -#include "fdiskaixlabel.h" -#include "nls.h" - -#define aixlabel ((aix_partition *)cxt->mbr) - -static int other_endian = 0; -static short volumes=1; - -/* - * only dealing with free blocks here - */ - -static void -aix_info( void ) { - puts( - _("\n\tThere is a valid AIX label on this disk.\n" - "\tUnfortunately Linux cannot handle these\n" - "\tdisks at the moment. Nevertheless some\n" - "\tadvice:\n" - "\t1. fdisk will destroy its contents on write.\n" - "\t2. Be sure that this disk is NOT a still vital\n" - "\t part of a volume group. (Otherwise you may\n" - "\t erase the other disks as well, if unmirrored.)\n" - "\t3. Before deleting this physical volume be sure\n" - "\t to remove the disk logically from your AIX\n" - "\t machine. (Otherwise you become an AIXpert).") - ); -} - -void -aix_nolabel(struct fdisk_context *cxt) -{ - aixlabel->magic = 0; - partitions = 4; - fdisk_mbr_zeroize(cxt); - return; -} - -int check_aix_label(struct fdisk_context *cxt) -{ - if (aixlabel->magic != AIX_LABEL_MAGIC && - aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) { - other_endian = 0; - return 0; - } - other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED); - update_units(cxt); - disklabel = AIX_LABEL; - partitions= 1016; - volumes = 15; - aix_info(); - aix_nolabel(cxt); /* %% */ - return 1; -} diff --git a/fdisk/fdiskaixlabel.h b/fdisk/fdiskaixlabel.h deleted file mode 100644 index bd4cb2781..000000000 --- a/fdisk/fdiskaixlabel.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef FDISK_AIX_LABEL_H -#define FDISK_AIX_LABEL_H - -#include <stdint.h> -/* - * Copyright (C) Andreas Neuper, Sep 1998. - * This file may be redistributed under - * the terms of the GNU Public License. - */ - -typedef struct { - unsigned int magic; /* expect AIX_LABEL_MAGIC */ - unsigned int fillbytes1[124]; - unsigned int physical_volume_id; - unsigned int fillbytes2[124]; -} aix_partition; - -#define AIX_LABEL_MAGIC 0xc9c2d4c1 -#define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9 -#define AIX_INFO_MAGIC 0x00072959 -#define AIX_INFO_MAGIC_SWAPPED 0x59290700 - -/* fdiskaixlabel.c */ -extern struct systypes aix_sys_types[]; -extern int check_aix_label(struct fdisk_context *cxt); - -#endif /* FDISK_AIX_LABEL_H */ diff --git a/fdisk/fdiskbsdlabel.c b/fdisk/fdiskbsdlabel.c deleted file mode 100644 index 71efd33f6..000000000 --- a/fdisk/fdiskbsdlabel.c +++ /dev/null @@ -1,847 +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. - - Changes: - 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls - - 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better - support for OSF/1 disklabels on Alpha. - Also fixed unaligned accesses in alpha_bootblock_checksum() -*/ - -#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 "nls.h" - -#include <sys/param.h> - -#include "common.h" -#include "fdisk.h" -#define FREEBSD_PARTITION 0xa5 -#define NETBSD_PARTITION 0xa9 -#define DKTYPENAMES -#include "fdiskbsdlabel.h" - -static void xbsd_delete_part (void); -static void xbsd_new_part (struct fdisk_context *cxt); -static void xbsd_write_disklabel (struct fdisk_context *cxt); -static int xbsd_create_disklabel (struct fdisk_context *cxt); -static void xbsd_edit_disklabel (void); -static void xbsd_write_bootstrap (struct fdisk_context *cxt); -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 unsigned short xbsd_dkcksum (struct xbsd_disklabel *lp); -static int xbsd_initlabel (struct fdisk_context *cxt, - struct partition *p, struct xbsd_disklabel *d, - int pindex); -static int xbsd_readlabel (struct fdisk_context *cxt, - struct partition *p, struct xbsd_disklabel *d); -static int xbsd_writelabel (struct fdisk_context *cxt, struct partition *p, struct xbsd_disklabel *d); -static void sync_disks (void); - -#if defined (__alpha__) -void alpha_bootblock_checksum (char *boot); -#endif - -#if !defined (__alpha__) -static int xbsd_translate_fstype (int linux_type); -static void xbsd_link_part (struct fdisk_context *cxt); -static struct partition *xbsd_part; -static int xbsd_part_index; -#endif - -#if defined (__alpha__) -/* We access this through a u_int64_t * when checksumming */ -static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8))); -#else -static char disklabelbuffer[BSD_BBSIZE]; -#endif - -static struct xbsd_disklabel xbsd_dlabel; - -#define bsd_cround(n) \ - (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n)) - -/* - * Test whether the whole disk has BSD disk label magic. - * - * Note: often reformatting with DOS-type label leaves the BSD magic, - * so this does not mean that there is a BSD disk label. - */ -int -check_osf_label(struct fdisk_context *cxt) { - if (xbsd_readlabel (cxt, NULL, &xbsd_dlabel) == 0) - return 0; - return 1; -} - -int -btrydev (struct fdisk_context *cxt) { - if (xbsd_readlabel (cxt, NULL, &xbsd_dlabel) == 0) - return -1; - printf(_("\nBSD label for device: %s\n"), cxt->dev_path); - xbsd_print_disklabel (cxt, 0); - return 0; -} - -#if !defined (__alpha__) -static int -hidden(int type) { - return type ^ 0x10; -} - -static int -is_bsd_partition_type(int type) { - return (type == FREEBSD_PARTITION || - type == hidden(FREEBSD_PARTITION) || - type == NETBSD_PARTITION || - type == hidden(NETBSD_PARTITION)); -} -#endif - -void -bsd_command_prompt (struct fdisk_context *cxt) -{ -#if !defined (__alpha__) - int t, ss; - struct partition *p; - - for (t=0; t<4; t++) { - p = get_part_table(t); - if (p && is_bsd_partition_type(p->sys_ind)) { - xbsd_part = p; - xbsd_part_index = t; - ss = get_start_sect(xbsd_part); - if (ss == 0) { - fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"), - partname(cxt->dev_path, t+1, 0)); - return; - } - printf (_("Reading disklabel of %s at sector %d.\n"), - partname(cxt->dev_path, t+1, 0), ss + BSD_LABELSECTOR); - if (xbsd_readlabel (cxt, xbsd_part, &xbsd_dlabel) == 0) - if (xbsd_create_disklabel (cxt) == 0) - return; - break; - } - } - - if (t == 4) { - printf (_("There is no *BSD partition on %s.\n"), cxt->dev_path); - return; - } - -#elif defined (__alpha__) - - if (xbsd_readlabel (cxt, NULL, &xbsd_dlabel) == 0) - if (xbsd_create_disklabel (cxt) == 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 (cxt); - break; - case 'l': - xbsd_list_types (); - break; - case 'n': - xbsd_new_part (cxt); - break; - case 'p': - xbsd_print_disklabel (cxt, 0); - break; - case 'q': - close (cxt->dev_fd); - exit ( EXIT_SUCCESS ); - case 'r': - return; - case 's': - xbsd_print_disklabel (cxt, 1); - break; - case 't': - xbsd_change_fstype (); - break; - case 'u': - change_units(cxt); - break; - case 'w': - xbsd_write_disklabel (cxt); - break; -#if !defined (__alpha__) - case 'x': - xbsd_link_part (cxt); - break; -#endif - default: - print_menu(MAIN_MENU); - 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 (struct fdisk_context *cxt) -{ - unsigned int begin, end; - char mesg[256]; - int i; - - if (!xbsd_check_new_partition (&i)) - return; - -#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__) - begin = get_start_sect(xbsd_part); - end = begin + get_nr_sects(xbsd_part) - 1; -#else - begin = 0; - end = xbsd_dlabel.d_secperunit - 1; -#endif - - snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR)); - begin = read_int (cxt, bsd_cround (begin), bsd_cround (begin), bsd_cround (end), - 0, mesg); - - if (display_in_cyl_units) - begin = (begin - 1) * xbsd_dlabel.d_secpercyl; - - snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"), - str_units(SINGULAR)); - end = read_int (cxt, bsd_cround (begin), bsd_cround (end), bsd_cround (end), - bsd_cround (begin), mesg); - - if (display_in_cyl_units) - end = end * xbsd_dlabel.d_secpercyl - 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; -} - -void -xbsd_print_disklabel (struct fdisk_context *cxt, int show_all) { - struct xbsd_disklabel *lp = &xbsd_dlabel; - struct xbsd_partition *pp; - FILE *f = stdout; - int i, j; - - if (show_all) { -#if defined (__alpha__) - fprintf(f, "# %s:\n", cxt->dev_path); -#else - fprintf(f, "# %s:\n", partname(cxt->dev_path, xbsd_part_index+1, 0)); -#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, _("# start end size fstype [fsize bsize cpg]\n")); - pp = lp->d_partitions; - for (i = 0; i < lp->d_npartitions; i++, pp++) { - if (pp->p_size) { - if (display_in_cyl_units && lp->d_secpercyl) { - fprintf(f, " %c: %8ld%c %8ld%c %8ld%c ", - 'a' + i, - (long) pp->p_offset / lp->d_secpercyl + 1, - (pp->p_offset % lp->d_secpercyl) ? '*' : ' ', - (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) - / lp->d_secpercyl, - ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ', - (long) pp->p_size / lp->d_secpercyl, - (pp->p_size % lp->d_secpercyl) ? '*' : ' '); - } else { - fprintf(f, " %c: %8ld %8ld %8ld ", - 'a' + i, - (long) pp->p_offset, - (long) pp->p_offset + pp->p_size - 1, - (long) pp->p_size); - } - 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, "%22.22s", ""); - break; - } - fprintf(f, "\n"); - } - } -} - -static void -xbsd_write_disklabel (struct fdisk_context *cxt) { -#if defined (__alpha__) - printf (_("Writing disklabel to %s.\n"), cxt->dev_path); - xbsd_writelabel (cxt, NULL, &xbsd_dlabel); -#else - printf (_("Writing disklabel to %s.\n"), - partname(cxt->dev_path, xbsd_part_index+1, 0)); - xbsd_writelabel (cxt, xbsd_part, &xbsd_dlabel); -#endif - reread_partition_table(cxt, 0); /* no exit yet */ -} - -static int -xbsd_create_disklabel (struct fdisk_context *cxt) { - char c; - -#if defined (__alpha__) - fprintf (stderr, _("%s contains no disklabel.\n"), cxt->dev_path); -#else - fprintf (stderr, _("%s contains no disklabel.\n"), - partname(cxt->dev_path, xbsd_part_index+1, 0)); -#endif - - while (1) { - c = read_char (_("Do you want to create a disklabel? (y/n) ")); - if (tolower(c) == 'y') { - if (xbsd_initlabel (cxt, -#if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \ - defined (__s390__) || defined (__s390x__) - NULL, &xbsd_dlabel, 0 -#else - xbsd_part, &xbsd_dlabel, xbsd_part_index -#endif - ) == 1) { - xbsd_print_disklabel (cxt, 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 (NULL)) - return def; - } - while (!isdigit (*line_ptr)); - return atoi (line_ptr); -} - -static void -xbsd_edit_disklabel (void) -{ - struct xbsd_disklabel *d; - - d = &xbsd_dlabel; - -#if defined (__alpha__) || defined (__ia64__) - d -> d_secsize = (unsigned long) edit_int ((unsigned long) d -> d_secsize ,_("bytes/sector")); - d -> d_nsectors = (unsigned long) edit_int ((unsigned long) d -> d_nsectors ,_("sectors/track")); - d -> d_ntracks = (unsigned long) edit_int ((unsigned long) d -> d_ntracks ,_("tracks/cylinder")); - d -> d_ncylinders = (unsigned long) edit_int ((unsigned long) d -> d_ncylinders ,_("cylinders")); -#endif - - /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */ - while (1) - { - d -> d_secpercyl = (unsigned long) edit_int ((unsigned 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 = (unsigned short) edit_int ((unsigned short) d -> d_rpm ,_("rpm")); - d -> d_interleave = (unsigned short) edit_int ((unsigned short) d -> d_interleave,_("interleave")); - d -> d_trackskew = (unsigned short) edit_int ((unsigned short) d -> d_trackskew ,_("trackskew")); - d -> d_cylskew = (unsigned short) edit_int ((unsigned short) d -> d_cylskew ,_("cylinderskew")); - d -> d_headswitch = (unsigned long) edit_int ((unsigned long) d -> d_headswitch ,_("headswitch")); - d -> d_trkseek = (unsigned long) edit_int ((unsigned 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 (struct fdisk_context *cxt) -{ - char *bootdir = BSD_LINUX_BOOTDIR; - char path[sizeof(BSD_LINUX_BOOTDIR) + 1 + 2 + 4]; /* BSD_LINUX_BOOTDIR + / + {sd,wd} + boot */ - 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 (NULL)) { - line_ptr[strlen (line_ptr)-1] = '\0'; - dkbasename = line_ptr; - } - snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename); - if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize)) - return; - - /* We need a backup of the disklabel (xbsd_dlabel might have changed). */ - d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE]; - memmove (&dl, d, sizeof (struct xbsd_disklabel)); - - /* The disklabel will be overwritten by 0's from bootxx anyway */ - memset (d, 0, sizeof (struct xbsd_disklabel)); - - snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename); - if (!xbsd_get_bootstrap (path, &disklabelbuffer[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 ); - } - - memmove (d, &dl, sizeof (struct xbsd_disklabel)); - -#if defined (__powerpc__) || defined (__hppa__) - sector = 0; -#elif defined (__alpha__) - sector = 0; - alpha_bootblock_checksum (disklabelbuffer); -#else - sector = get_start_sect(xbsd_part); -#endif - - if (lseek (cxt->dev_fd, (off_t) sector * SECTOR_SIZE, SEEK_SET) == -1) - fatal (cxt, unable_to_seek); - if (BSD_BBSIZE != write (cxt->dev_fd, disklabelbuffer, BSD_BBSIZE)) - fatal (cxt, unable_to_write); - -#if defined (__alpha__) - printf (_("Bootstrap installed on %s.\n"), cxt->dev_path); -#else - printf (_("Bootstrap installed on %s.\n"), - partname (cxt->dev_path, xbsd_part_index+1, 0)); -#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[256]; - char l; - - snprintf (prompt, sizeof(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) { - - /* room for more? various BSD flavours have different maxima */ - if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) { - int t; - - 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 unsigned short -xbsd_dkcksum (struct xbsd_disklabel *lp) { - unsigned short *start, *end; - unsigned short sum = 0; - - start = (unsigned short *) lp; - end = (unsigned short *) &lp->d_partitions[lp->d_npartitions]; - while (start < end) - sum ^= *start++; - return sum; -} - -static int -xbsd_initlabel (struct fdisk_context *cxt, struct partition *p, struct xbsd_disklabel *d, - int pindex __attribute__((__unused__))) { - struct xbsd_partition *pp; - - memset (d, 0, sizeof (struct xbsd_disklabel)); - - d -> d_magic = BSD_DISKMAGIC; - - if (strncmp (cxt->dev_path, "/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 (__alpha__) - d -> d_flags = BSD_D_DOSPART; -#else - d -> d_flags = 0; -#endif - d -> d_secsize = SECTOR_SIZE; /* bytes/sector */ - d -> d_nsectors = cxt->geom.sectors; /* sectors/track */ - d -> d_ntracks = cxt->geom.heads; /* tracks/cylinder (heads) */ - d -> d_ncylinders = cxt->geom.cylinders; - d -> d_secpercyl = cxt->geom.sectors * cxt->geom.heads;/* sectors/cylinder */ - if (d -> d_secpercyl == 0) - d -> d_secpercyl = 1; /* avoid segfaults */ - 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 (__alpha__) - 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; -} - -/* - * Read a xbsd_disklabel from sector 0 or from the starting sector of p. - * If it has the right magic, return 1. - */ -static int -xbsd_readlabel (struct fdisk_context *cxt, struct partition *p, struct xbsd_disklabel *d) -{ - int t, sector; - - /* p is used only to get the starting sector */ -#if !defined (__alpha__) - sector = (p ? get_start_sect(p) : 0); -#elif defined (__alpha__) - sector = 0; -#endif - - if (lseek (cxt->dev_fd, (off_t) sector * SECTOR_SIZE, SEEK_SET) == -1) - fatal (cxt, unable_to_seek); - if (BSD_BBSIZE != read (cxt->dev_fd, disklabelbuffer, BSD_BBSIZE)) - fatal (cxt, unable_to_read); - - memmove (d, - &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET], - sizeof (struct xbsd_disklabel)); - - if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC) - return 0; - - 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_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 fdisk_context *cxt, struct partition *p, struct xbsd_disklabel *d) -{ - unsigned int sector; - -#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__) - sector = get_start_sect(p) + BSD_LABELSECTOR; -#else - 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. - */ - memmove (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET], d, - sizeof (struct xbsd_disklabel)); - -#if defined (__alpha__) && BSD_LABELSECTOR == 0 - alpha_bootblock_checksum (disklabelbuffer); - if (lseek (cxt->dev_fd, (off_t) 0, SEEK_SET) == -1) - fatal (cxt, unable_to_seek); - if (BSD_BBSIZE != write (cxt->dev_fd, disklabelbuffer, BSD_BBSIZE)) - fatal (cxt, unable_to_write); -#else - if (lseek (cxt->dev_fd, (off_t) sector * SECTOR_SIZE + BSD_LABELOFFSET, - SEEK_SET) == -1) - fatal (cxt, unable_to_seek); - if (sizeof (struct xbsd_disklabel) != write (cxt->dev_fd, d, sizeof (struct xbsd_disklabel))) - fatal (cxt, unable_to_write); -#endif - - sync_disks (); - - return 1; -} - -static void -sync_disks (void) -{ - printf (_("\nSyncing disks.\n")); - sync (); - sleep (4); -} - -#if !defined (__alpha__) -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 (struct fdisk_context *cxt) -{ - int k, i; - struct partition *p; - - k = get_partition (cxt, 1, partitions); - - if (!xbsd_check_new_partition (&i)) - return; - - p = get_part_table(k); - - xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p); - xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p); - xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind); -} -#endif - -#if defined (__alpha__) - -#if !defined(__GLIBC__) -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/fdisk/fdiskbsdlabel.h b/fdisk/fdiskbsdlabel.h deleted file mode 100644 index 79f291348..000000000 --- a/fdisk/fdiskbsdlabel.h +++ /dev/null @@ -1,246 +0,0 @@ -#ifndef FDISK_BSD_LABEL_H -#define FDISK_BSD_LABEL_H - -/* - * 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 <stdint.h> - -#ifndef BSD_DISKMAGIC -#define BSD_DISKMAGIC ((uint32_t) 0x82564557) -#endif - -#ifndef BSD_MAXPARTITIONS -#define BSD_MAXPARTITIONS 16 -#endif - -#define BSD_LINUX_BOOTDIR "/usr/ucb/mdec" - -#if defined (__i386__) || defined (__sparc__) || defined (__arm__) || \ - defined (__mips__) || defined (__s390__) || defined (__sh__) || \ - defined(__x86_64__) || defined (__avr32__) || defined(__cris__) -#define BSD_LABELSECTOR 1 -#define BSD_LABELOFFSET 0 -#elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__) -#define BSD_LABELSECTOR 0 -#define BSD_LABELOFFSET 64 -#elif defined (__s390__) || defined (__s390x__) -#define BSD_LABELSECTOR 1 -#define BSD_LABELOFFSET 0 -#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 { - uint32_t d_magic; /* the magic number */ - int16_t d_type; /* drive type */ - int16_t d_subtype; /* controller/d_type specific */ - char d_typename[16]; /* type name, e.g. "eagle" */ - char d_packname[16]; /* pack identifier */ - /* disk geometry: */ - uint32_t d_secsize; /* # of bytes per sector */ - uint32_t d_nsectors; /* # of data sectors per track */ - uint32_t d_ntracks; /* # of tracks per cylinder */ - uint32_t d_ncylinders; /* # of data cylinders per unit */ - uint32_t d_secpercyl; /* # of data sectors per cylinder */ - uint32_t 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. - */ - uint16_t d_sparespertrack; /* # of spare sectors per track */ - uint16_t d_sparespercyl; /* # of spare sectors per cylinder */ - /* - * Alternate cylinders include maintenance, replacement, - * configuration description areas, etc. - */ - uint32_t 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. - */ - uint16_t d_rpm; /* rotational speed */ - uint16_t d_interleave; /* hardware sector interleave */ - uint16_t d_trackskew; /* sector 0 skew, per track */ - uint16_t d_cylskew; /* sector 0 skew, per cylinder */ - uint32_t d_headswitch; /* head switch time, usec */ - uint32_t d_trkseek; /* track-to-track seek, usec */ - uint32_t d_flags; /* generic flags */ -#define NDDATA 5 - uint32_t d_drivedata[NDDATA]; /* drive-type specific information */ -#define NSPARE 5 - uint32_t d_spare[NSPARE]; /* reserved for future use */ - uint32_t d_magic2; /* the magic number (again) */ - uint16_t d_checksum; /* xor of data incl. partitions */ - /* filesystem and partition information: */ - uint16_t d_npartitions; /* number of partitions in following */ - uint32_t d_bbsize; /* size of boot area at sn0, bytes */ - uint32_t d_sbsize; /* max size of fs superblock, bytes */ - struct xbsd_partition { /* the partition table */ - uint32_t p_size; /* number of sectors in partition */ - uint32_t p_offset; /* starting sector */ - uint32_t p_fsize; /* filesystem basic fragment size */ - uint8_t p_fstype; /* filesystem type, see below */ - uint8_t p_frag; /* filesystem fragments per block */ - uint16_t 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 */ -#define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */ - -/* this is annoying, but it's also the way it is :-( */ -#ifdef __alpha__ -#define BSD_FS_EXT2 8 /* ext2 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"}, - {BSD_FS_ADVFS, "AdvFS"}, - { 0, NULL } -}; -#define BSD_FSMAXTYPES (ARRAY_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 */ - -extern void bsd_command_prompt(struct fdisk_context *cxt); -extern int check_osf_label(struct fdisk_context *cxt); -extern int btrydev(struct fdisk_context *cxt); -extern void xbsd_print_disklabel(struct fdisk_context *cxt, int); - -#endif /* FDISK_BSD_LABEL_H */ diff --git a/fdisk/fdiskdoslabel.c b/fdisk/fdiskdoslabel.c deleted file mode 100644 index a72a432c1..000000000 --- a/fdisk/fdiskdoslabel.c +++ /dev/null @@ -1,682 +0,0 @@ -/* - * Many, many hands. - * Specific DOS label file - Davidlohr Bueso <dave@gnu.org> - */ - -#include <unistd.h> -#include <ctype.h> - -#include "nls.h" -#include "xalloc.h" -#include "randutils.h" -#include "common.h" -#include "fdisk.h" -#include "fdiskdoslabel.h" - -#define set_hsc(h,s,c,sector) { \ - s = sector % cxt->geom.sectors + 1; \ - sector /= cxt->geom.sectors; \ - h = sector % cxt->geom.heads; \ - sector /= cxt->geom.heads; \ - c = sector & 0xff; \ - s |= (sector >> 2) & 0xc0; \ - } - -#define alignment_required (grain != cxt->sector_size) - -struct pte ptes[MAXIMUM_PARTS]; -sector_t extended_offset; -int ext_index; - -static int get_nonexisting_partition(struct fdisk_context *cxt, int warn, int max) -{ - int pno = -1; - int i; - int dflt = 0; - - for (i = 0; i < max; i++) { - struct pte *pe = &ptes[i]; - struct partition *p = pe->part_table; - - if (p && is_cleared_partition(p)) { - if (pno >= 0) { - dflt = pno + 1; - goto not_unique; - } - pno = i; - } - } - if (pno >= 0) { - printf(_("Selected partition %d\n"), pno+1); - return pno; - } - printf(_("All primary partitions have been defined already!\n")); - return -1; - - not_unique: - return get_partition_dflt(cxt, warn, max, dflt); -} - - -/* Allocate a buffer and read a partition table sector */ -static void read_pte(struct fdisk_context *cxt, int pno, sector_t offset) -{ - struct pte *pe = &ptes[pno]; - - pe->offset = offset; - pe->sectorbuffer = xmalloc(cxt->sector_size); - read_sector(cxt, offset, pe->sectorbuffer); - pe->changed = 0; - pe->part_table = pe->ext_pointer = NULL; -} - -static void dos_write_mbr_id(unsigned char *b, unsigned int id) -{ - store4_little_endian(&b[440], id); -} - -static unsigned int dos_read_mbr_id(const unsigned char *b) -{ - return read4_little_endian(&b[440]); -} - -static void clear_partition(struct partition *p) -{ - if (!p) - return; - p->boot_ind = 0; - p->head = 0; - p->sector = 0; - p->cyl = 0; - p->sys_ind = 0; - p->end_head = 0; - p->end_sector = 0; - p->end_cyl = 0; - set_start_sect(p,0); - set_nr_sects(p,0); -} - -void dos_init(struct fdisk_context *cxt) -{ - int i; - - disklabel = DOS_LABEL; - partitions = 4; - ext_index = 0; - extended_offset = 0; - - for (i = 0; i < 4; i++) { - struct pte *pe = &ptes[i]; - - pe->part_table = pt_offset(cxt->mbr, i); - pe->ext_pointer = NULL; - pe->offset = 0; - pe->sectorbuffer = cxt->mbr; - pe->changed = 0; - } - - warn_geometry(cxt); - warn_limits(cxt); - warn_alignment(cxt); -} - -static void read_extended(struct fdisk_context *cxt, int ext) -{ - int i; - struct pte *pex; - struct partition *p, *q; - - ext_index = ext; - pex = &ptes[ext]; - pex->ext_pointer = pex->part_table; - - p = pex->part_table; - if (!get_start_sect(p)) { - fprintf(stderr, - _("Bad offset in primary extended partition\n")); - return; - } - - while (IS_EXTENDED (p->sys_ind)) { - struct pte *pe = &ptes[partitions]; - - if (partitions >= MAXIMUM_PARTS) { - /* This is not a Linux restriction, but - this program uses arrays of size MAXIMUM_PARTS. - Do not try to `improve' this test. */ - struct pte *pre = &ptes[partitions-1]; - - fprintf(stderr, - _("Warning: omitting partitions after #%d.\n" - "They will be deleted " - "if you save this partition table.\n"), - partitions); - clear_partition(pre->ext_pointer); - pre->changed = 1; - return; - } - - read_pte(cxt, partitions, extended_offset + get_start_sect(p)); - - if (!extended_offset) - extended_offset = get_start_sect(p); - - q = p = pt_offset(pe->sectorbuffer, 0); - for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) { - if (IS_EXTENDED (p->sys_ind)) { - if (pe->ext_pointer) - fprintf(stderr, - _("Warning: extra link " - "pointer in partition table" - " %d\n"), partitions + 1); - else - pe->ext_pointer = p; - } else if (p->sys_ind) { - if (pe->part_table) - fprintf(stderr, - _("Warning: ignoring extra " - "data in partition table" - " %d\n"), partitions + 1); - else - pe->part_table = p; - } - } - - /* very strange code here... */ - if (!pe->part_table) { - if (q != pe->ext_pointer) - pe->part_table = q; - else - pe->part_table = q + 1; - } - if (!pe->ext_pointer) { - if (q != pe->part_table) - pe->ext_pointer = q; - else - pe->ext_pointer = q + 1; - } - - p = pe->ext_pointer; - partitions++; - } - - /* remove empty links */ - remove: - for (i = 4; i < partitions; i++) { - struct pte *pe = &ptes[i]; - - if (!get_nr_sects(pe->part_table) && - (partitions > 5 || ptes[4].part_table->sys_ind)) { - printf(_("omitting empty partition (%d)\n"), i+1); - dos_delete_partition(i); - goto remove; /* numbering changed */ - } - } -} - -void dos_print_mbr_id(struct fdisk_context *cxt) -{ - printf(_("Disk identifier: 0x%08x\n"), dos_read_mbr_id(cxt->mbr)); -} - -void create_doslabel(struct fdisk_context *cxt) -{ - unsigned int id; - - /* random disk signature */ - random_get_bytes(&id, sizeof(id)); - - fprintf(stderr, _("Building a new DOS disklabel with disk identifier 0x%08x.\n"), id); - - dos_init(cxt); - fdisk_mbr_zeroize(cxt); - set_all_unchanged(); - set_changed(0); - - /* Generate an MBR ID for this disk */ - dos_write_mbr_id(cxt->mbr, id); - - /* Put MBR signature */ - write_part_table_flag(cxt->mbr); -} - -void dos_set_mbr_id(struct fdisk_context *cxt) -{ - unsigned long new_id; - char *ep; - char ps[64]; - - snprintf(ps, sizeof ps, _("New disk identifier (current 0x%08x): "), - dos_read_mbr_id(cxt->mbr)); - - if (read_chars(ps) == '\n') - return; - - new_id = strtoul(line_ptr, &ep, 0); - if (*ep != '\n') - return; - - dos_write_mbr_id(cxt->mbr, new_id); - MBRbuffer_changed = 1; - dos_print_mbr_id(cxt); -} - -void dos_delete_partition(int i) -{ - struct pte *pe = &ptes[i]; - struct partition *p = pe->part_table; - struct partition *q = pe->ext_pointer; - - /* Note that for the fifth partition (i == 4) we don't actually - decrement partitions. */ - - if (i < 4) { - if (IS_EXTENDED (p->sys_ind) && i == ext_index) { - partitions = 4; - ptes[ext_index].ext_pointer = NULL; - extended_offset = 0; - } - clear_partition(p); - } else if (!q->sys_ind && i > 4) { - /* the last one in the chain - just delete */ - --partitions; - --i; - clear_partition(ptes[i].ext_pointer); - ptes[i].changed = 1; - } else { - /* not the last one - further ones will be moved down */ - if (i > 4) { - /* delete this link in the chain */ - p = ptes[i-1].ext_pointer; - *p = *q; - set_start_sect(p, get_start_sect(q)); - set_nr_sects(p, get_nr_sects(q)); - ptes[i-1].changed = 1; - } else if (partitions > 5) { /* 5 will be moved to 4 */ - /* the first logical in a longer chain */ - struct pte *pe = &ptes[5]; - - if (pe->part_table) /* prevent SEGFAULT */ - set_start_sect(pe->part_table, - get_partition_start(pe) - - extended_offset); - pe->offset = extended_offset; - pe->changed = 1; - } - - if (partitions > 5) { - partitions--; - while (i < partitions) { - ptes[i] = ptes[i+1]; - i++; - } - } else - /* the only logical: clear only */ - clear_partition(ptes[i].part_table); - } -} - -int check_dos_label(struct fdisk_context *cxt) -{ - int i; - - if (!valid_part_table_flag(cxt->mbr)) - return 0; - - dos_init(cxt); - - for (i = 0; i < 4; i++) { - struct pte *pe = &ptes[i]; - - if (IS_EXTENDED (pe->part_table->sys_ind)) { - if (partitions != 4) - fprintf(stderr, _("Ignoring extra extended " - "partition %d\n"), i + 1); - else - read_extended(cxt, i); - } - } - - for (i = 3; i < partitions; i++) { - struct pte *pe = &ptes[i]; - - if (!valid_part_table_flag(pe->sectorbuffer)) { - fprintf(stderr, - _("Warning: invalid flag 0x%04x of partition " - "table %d will be corrected by w(rite)\n"), - part_table_flag(pe->sectorbuffer), i + 1); - pe->changed = 1; - } - } - - return 1; -} - -/* - * Avoid warning about DOS partitions when no DOS partition was changed. - * Here a heuristic "is probably dos partition". - * We might also do the opposite and warn in all cases except - * for "is probably nondos partition". - */ -int is_dos_partition(int t) -{ - return (t == 1 || t == 4 || t == 6 || - t == 0x0b || t == 0x0c || t == 0x0e || - t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 || - t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 || - t == 0xc1 || t == 0xc4 || t == 0xc6); -} - -static void set_partition(struct fdisk_context *cxt, - int i, int doext, sector_t start, - sector_t stop, int sysid) -{ - struct partition *p; - sector_t offset; - - if (doext) { - p = ptes[i].ext_pointer; - offset = extended_offset; - } else { - p = ptes[i].part_table; - offset = ptes[i].offset; - } - p->boot_ind = 0; - p->sys_ind = sysid; - set_start_sect(p, start - offset); - set_nr_sects(p, stop - start + 1); - - if (!doext) - print_partition_size(cxt, i + 1, start, stop, sysid); - - if (dos_compatible_flag && (start/(cxt->geom.sectors*cxt->geom.heads) > 1023)) - start = cxt->geom.heads*cxt->geom.sectors*1024 - 1; - set_hsc(p->head, p->sector, p->cyl, start); - if (dos_compatible_flag && (stop/(cxt->geom.sectors*cxt->geom.heads) > 1023)) - stop = cxt->geom.heads*cxt->geom.sectors*1024 - 1; - set_hsc(p->end_head, p->end_sector, p->end_cyl, stop); - ptes[i].changed = 1; -} - -static sector_t get_unused_start(int part_n, sector_t start, - sector_t first[], sector_t last[]) -{ - int i; - - for (i = 0; i < partitions; i++) { - sector_t lastplusoff; - - if (start == ptes[i].offset) - start += sector_offset; - lastplusoff = last[i] + ((part_n < 4) ? 0 : sector_offset); - if (start >= first[i] && start <= lastplusoff) - start = lastplusoff + 1; - } - - return start; -} - -static sector_t align_lba_in_range(struct fdisk_context *cxt, - sector_t lba, sector_t start, sector_t stop) -{ - start = align_lba(cxt, start, ALIGN_UP); - stop = align_lba(cxt, stop, ALIGN_DOWN); - - lba = align_lba(cxt, lba, ALIGN_NEAREST); - - if (lba < start) - return start; - else if (lba > stop) - return stop; - return lba; -} - -void dos_add_partition(struct fdisk_context *cxt, int n, int sys) -{ - char mesg[256]; /* 48 does not suffice in Japanese */ - int i, read = 0; - struct partition *p = ptes[n].part_table; - struct partition *q = ptes[ext_index].part_table; - sector_t start, stop = 0, limit, temp, - first[partitions], last[partitions]; - - if (p && p->sys_ind) { - printf(_("Partition %d is already defined. Delete " - "it before re-adding it.\n"), n + 1); - return; - } - fill_bounds(first, last); - if (n < 4) { - start = sector_offset; - if (display_in_cyl_units || !cxt->total_sectors) - limit = cxt->geom.heads * cxt->geom.sectors * cxt->geom.cylinders - 1; - else - limit = cxt->total_sectors - 1; - - if (limit > UINT_MAX) - limit = UINT_MAX; - - 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 (display_in_cyl_units) - for (i = 0; i < partitions; i++) - first[i] = (cround(first[i]) - 1) * units_per_sector; - - snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR)); - do { - sector_t dflt, aligned; - - temp = start; - dflt = start = get_unused_start(n, start, first, last); - - /* the default sector should be aligned and unused */ - do { - aligned = align_lba_in_range(cxt, dflt, dflt, limit); - dflt = get_unused_start(n, aligned, first, last); - } while (dflt != aligned && dflt > aligned && dflt < limit); - - if (dflt >= limit) - dflt = start; - if (start > limit) - break; - if (start >= temp+units_per_sector && read) { - printf(_("Sector %llu is already allocated\n"), temp); - temp = start; - read = 0; - } - if (!read && start == temp) { - sector_t i = start; - - start = read_int(cxt, cround(i), cround(dflt), cround(limit), - 0, mesg); - if (display_in_cyl_units) { - start = (start - 1) * units_per_sector; - if (start < i) start = i; - } - read = 1; - } - } while (start != temp || !read); - if (n > 4) { /* NOT for fifth partition */ - struct pte *pe = &ptes[n]; - - pe->offset = start - sector_offset; - if (pe->offset == extended_offset) { /* must be corrected */ - pe->offset++; - if (sector_offset == 1) - start++; - } - } - - for (i = 0; i < partitions; i++) { - struct pte *pe = &ptes[i]; - - if (start < pe->offset && limit >= pe->offset) - limit = pe->offset - 1; - if (start < first[i] && limit >= first[i]) - limit = first[i] - 1; - } - if (start > limit) { - printf(_("No free sectors available\n")); - if (n > 4) - partitions--; - return; - } - if (cround(start) == cround(limit)) { - stop = limit; - } else { - int is_suffix_used = 0; - - snprintf(mesg, sizeof(mesg), - _("Last %1$s, +%2$s or +size{K,M,G}"), - str_units(SINGULAR), str_units(PLURAL)); - - stop = read_int_with_suffix(cxt, - cround(start), cround(limit), cround(limit), - cround(start), mesg, &is_suffix_used); - if (display_in_cyl_units) { - stop = stop * units_per_sector - 1; - if (stop >limit) - stop = limit; - } - - if (is_suffix_used && alignment_required) { - /* the last sector has not been exactly requested (but - * defined by +size{K,M,G} convention), so be smart - * and align the end of the partition. The next - * partition will start at phy.block boundary. - */ - stop = align_lba_in_range(cxt, stop, start, limit) - 1; - if (stop > limit) - stop = limit; - } - } - - set_partition(cxt, n, 0, start, stop, sys); - if (n > 4) - set_partition(cxt, n - 1, 1, ptes[n].offset, stop, EXTENDED); - - if (IS_EXTENDED (sys)) { - struct pte *pe4 = &ptes[4]; - struct pte *pen = &ptes[n]; - - ext_index = n; - pen->ext_pointer = p; - pe4->offset = extended_offset = start; - pe4->sectorbuffer = xcalloc(1, cxt->sector_size); - pe4->part_table = pt_offset(pe4->sectorbuffer, 0); - pe4->ext_pointer = pe4->part_table + 1; - pe4->changed = 1; - partitions = 5; - } -} - -static void add_logical(struct fdisk_context *cxt) -{ - if (partitions > 5 || ptes[4].part_table->sys_ind) { - struct pte *pe = &ptes[partitions]; - - pe->sectorbuffer = xcalloc(1, cxt->sector_size); - pe->part_table = pt_offset(pe->sectorbuffer, 0); - pe->ext_pointer = pe->part_table + 1; - pe->offset = 0; - pe->changed = 1; - partitions++; - } - printf(_("Adding logical partition %d\n"), partitions); - dos_add_partition(cxt, partitions - 1, LINUX_NATIVE); -} - -/* - * Ask the user for new partition type information (logical, extended). - * This function calls the actual partition adding logic - dos_add_partition. - */ -void dos_new_partition(struct fdisk_context *cxt) -{ - int i, free_primary = 0; - - for (i = 0; i < 4; i++) - free_primary += !ptes[i].part_table->sys_ind; - - if (!free_primary && partitions >= MAXIMUM_PARTS) { - printf(_("The maximum number of partitions has been created\n")); - return; - } - - if (!free_primary) { - if (extended_offset) { - printf(_("All primary partitions are in use\n")); - add_logical(cxt); - } else - printf(_("If you want to create more than four partitions, you must replace a\n" - "primary partition with an extended partition first.\n")); - } else if (partitions >= MAXIMUM_PARTS) { - printf(_("All logical partitions are in use\n")); - printf(_("Adding a primary partition\n")); - dos_add_partition(cxt, get_partition(cxt, 0, 4), LINUX_NATIVE); - } else { - char c, dflt, line[LINE_LENGTH]; - - dflt = (free_primary == 1 && !extended_offset) ? 'e' : 'p'; - snprintf(line, sizeof(line), - _("Partition type:\n" - " p primary (%d primary, %d extended, %d free)\n" - "%s\n" - "Select (default %c): "), - 4 - (extended_offset ? 1 : 0) - free_primary, extended_offset ? 1 : 0, free_primary, - extended_offset ? _(" l logical (numbered from 5)") : _(" e extended"), - dflt); - - c = tolower(read_chars(line)); - if (c == '\n') { - c = dflt; - printf(_("Using default response %c\n"), c); - } - if (c == 'p') { - int i = get_nonexisting_partition(cxt, 0, 4); - if (i >= 0) - dos_add_partition(cxt, i, LINUX_NATIVE); - return; - } else if (c == 'l' && extended_offset) { - add_logical(cxt); - return; - } else if (c == 'e' && !extended_offset) { - int i = get_nonexisting_partition(cxt, 0, 4); - if (i >= 0) - dos_add_partition(cxt, i, EXTENDED); - return; - } else - printf(_("Invalid partition type `%c'\n"), c); - } -} - -void dos_write_table(struct fdisk_context *cxt) -{ - int i; - - /* MBR (primary partitions) */ - if (!MBRbuffer_changed) { - for (i = 0; i < 4; i++) - if (ptes[i].changed) - MBRbuffer_changed = 1; - } - if (MBRbuffer_changed) { - write_part_table_flag(cxt->mbr); - write_sector(cxt, 0, cxt->mbr); - } - /* EBR (logical partitions) */ - for (i = 4; i < partitions; i++) { - struct pte *pe = &ptes[i]; - - if (pe->changed) { - write_part_table_flag(pe->sectorbuffer); - write_sector(cxt, pe->offset, pe->sectorbuffer); - } - } -} diff --git a/fdisk/fdiskdoslabel.h b/fdisk/fdiskdoslabel.h deleted file mode 100644 index f64a4cedd..000000000 --- a/fdisk/fdiskdoslabel.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef FDISK_DOS_LABEL_H -#define FDISK_DOS_LABEL_H - -/* - * per partition table entry data - * - * The four primary partitions have the same sectorbuffer (MBRbuffer) - * and have NULL ext_pointer. - * Each logical partition table entry has two pointers, one for the - * partition and one link to the next one. - */ -struct pte { - struct partition *part_table; /* points into sectorbuffer */ - struct partition *ext_pointer; /* points into sectorbuffer */ - char changed; /* boolean */ - sector_t offset; /* disk sector number */ - unsigned char *sectorbuffer; /* disk sector contents */ -}; - -extern struct pte ptes[MAXIMUM_PARTS]; -extern int dos_compatible_flag; - -#define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \ - (n) * sizeof(struct partition))) - -extern int ext_index; /* the prime extended partition */ -extern sector_t extended_offset, sector_offset; - -static inline void write_part_table_flag(unsigned char *b) -{ - b[510] = 0x55; - b[511] = 0xaa; -} - -/* A valid partition table sector ends in 0x55 0xaa */ -static inline unsigned int part_table_flag(unsigned char *b) -{ - return ((unsigned int) b[510]) + (((unsigned int) b[511]) << 8); -} - -static inline sector_t get_partition_start(struct pte *pe) -{ - return pe->offset + get_start_sect(pe->part_table); -} - -extern void create_doslabel(struct fdisk_context *cxt); -extern void dos_print_mbr_id(struct fdisk_context *cxt); -extern void dos_set_mbr_id(struct fdisk_context *cxt); -extern void dos_delete_partition(int i); -extern int check_dos_label(struct fdisk_context *cxt); -extern int is_dos_partition(int t); -extern void dos_init(struct fdisk_context *cxt); -extern void dos_add_partition(struct fdisk_context *cxt, int n, int sys); -extern void dos_new_partition(struct fdisk_context *cxt); -extern void dos_write_table(struct fdisk_context *cxt); - -#endif diff --git a/fdisk/fdiskmaclabel.c b/fdisk/fdiskmaclabel.c deleted file mode 100644 index 96fc7121e..000000000 --- a/fdisk/fdiskmaclabel.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - Changes: - Sat Mar 20 09:51:38 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br> - Internationalization -*/ -#include <stdio.h> /* stderr */ -#include <string.h> /* strstr */ -#include <unistd.h> /* write */ - -#include <endian.h> - -#include "common.h" -#include "fdisk.h" -#include "fdiskmaclabel.h" -#include "nls.h" - -#define MAC_BITMASK 0xffff0000 - - -static int other_endian = 0; -static short volumes=1; - -/* - * only dealing with free blocks here - */ - -static void -mac_info( void ) { - puts( - _("\n\tThere is a valid Mac label on this disk.\n" - "\tUnfortunately fdisk(1) cannot handle these disks.\n" - "\tUse either pdisk or parted to modify the partition table.\n" - "\tNevertheless some advice:\n" - "\t1. fdisk will destroy its contents on write.\n" - "\t2. Be sure that this disk is NOT a still vital\n" - "\t part of a volume group. (Otherwise you may\n" - "\t erase the other disks as well, if unmirrored.)\n") - ); -} - -void -mac_nolabel(struct fdisk_context *cxt) -{ - maclabel->magic = 0; - partitions = 4; - fdisk_mbr_zeroize(cxt); - return; -} - -int -check_mac_label(struct fdisk_context *cxt) -{ - /* - Conversion: only 16 bit should compared - e.g.: HFS Label is only 16bit long - */ - int magic_masked = 0 ; - magic_masked = maclabel->magic & MAC_BITMASK ; - - switch (magic_masked) { - case MAC_LABEL_MAGIC : - case MAC_LABEL_MAGIC_2: - case MAC_LABEL_MAGIC_3: - goto IS_MAC; - break; - default: - other_endian = 0; - return 0; - - - } - -IS_MAC: - other_endian = (maclabel->magic == MAC_LABEL_MAGIC_SWAPPED); // =? - update_units(cxt); - disklabel = MAC_LABEL; - partitions= 1016; // =? - volumes = 15; // =? - mac_info(); - mac_nolabel(cxt); /* %% */ - return 1; -} - diff --git a/fdisk/fdiskmaclabel.h b/fdisk/fdiskmaclabel.h deleted file mode 100644 index 4873dcdf0..000000000 --- a/fdisk/fdiskmaclabel.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef FDISK_MAC_LABEL_H -#define FDISK_MAC_LABEL_H - -#include <sys/types.h> -/* - * Copyright (C) Andreas Neuper, Sep 1998. - * This file may be redistributed under - * the terms of the GNU Public License. - */ - -typedef struct { - unsigned int magic; /* expect MAC_LABEL_MAGIC */ - unsigned int fillbytes1[124]; - unsigned int physical_volume_id; - unsigned int fillbytes2[124]; -} mac_partition; - -/* MAC magic number only 16bits, do I always know that there are 0200 - * following? Problem, after magic the uint16_t res1; follows, I donnno know - * about the 200k */ -#define MAC_LABEL_MAGIC 0x45520000 -#define MAC_LABEL_MAGIC_2 0x50530000 -#define MAC_LABEL_MAGIC_3 0x504d0000 - -#define MAC_LABEL_MAGIC_SWAPPED 0x00002554 - -#define MAC_LABEL_MAGIC_2_SWAPPED 0x00003505 -#define MAC_LABEL_MAGIC_3_SWAPPED 0x0000d405 - -/* fdisk.c */ -#define maclabel ((mac_partition *)cxt->mbr) - -/* fdiskmaclabel.c */ -extern struct systypes mac_sys_types[]; -extern void mac_nolabel(struct fdisk_context *cxt); -extern int check_mac_label(struct fdisk_context *cxt); - -#endif /* FDISK_MAC_LABEL_H */ - diff --git a/fdisk/fdisksgilabel.c b/fdisk/fdisksgilabel.c deleted file mode 100644 index c9033cb41..000000000 --- a/fdisk/fdisksgilabel.c +++ /dev/null @@ -1,879 +0,0 @@ -/* - * - * fdisksgilabel.c - * - * Copyright (C) Andreas Neuper, Sep 1998. - * This file may be modified and redistributed under - * the terms of the GNU Public License. - * - * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br> - * Internationalization - * - * 2003-03-20 Phillip Kesling <pkesling@sgi.com> - * Some fixes - * - * 2012-06-16 Davidlohr Bueso <dave@gnu.org> - * Adapt to fdisk context and add heap sort for partitions - */ - -#include <stdio.h> /* stderr */ -#include <stdlib.h> /* exit */ -#include <string.h> /* strstr */ -#include <unistd.h> /* write */ -#include <sys/ioctl.h> /* ioctl */ -#include <sys/stat.h> /* stat */ -#include <assert.h> /* assert */ - -#include <endian.h> -#include "nls.h" -#include "xalloc.h" - -#include "blkdev.h" - -#include "common.h" -#include "fdisk.h" -#include "fdisksgilabel.h" - -static int other_endian = 0; -static int debug = 0; -static short volumes=1; - -/* - * only dealing with free blocks here - */ - -typedef struct { unsigned int first; unsigned int last; } freeblocks; -static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */ - -static void -setfreelist(int i, unsigned int f, unsigned int l) { - if (i < 17) { - freelist[i].first = f; - freelist[i].last = l; - } -} - -static void -add2freelist(unsigned int f, unsigned int l) { - int i = 0; - for ( ; i < 17 ; i++) - if (freelist[i].last == 0) - break; - setfreelist(i, f, l); -} - -static void -clearfreelist(void) { - int i; - - for (i = 0; i < 17 ; i++) - setfreelist(i, 0, 0); -} - -static unsigned int -isinfreelist(unsigned int b) { - int i; - - for (i = 0; i < 17 ; i++) - if (freelist[i].first <= b && freelist[i].last >= b) - return freelist[i].last; - return 0; -} - /* return last vacant block of this stride (never 0). */ - /* the '>=' is not quite correct, but simplifies the code */ -/* - * end of free blocks section - */ -struct systypes sgi_sys_types[] = { - {SGI_VOLHDR, N_("SGI volhdr")}, - {0x01, N_("SGI trkrepl")}, - {0x02, N_("SGI secrepl")}, - {SGI_SWAP, N_("SGI raw")}, - {0x04, N_("SGI bsd")}, - {0x05, N_("SGI sysv")}, - {ENTIRE_DISK, N_("SGI volume")}, - {SGI_EFS, N_("SGI efs")}, - {0x08, N_("SGI lvol")}, - {0x09, N_("SGI rlvol")}, - {SGI_XFS, N_("SGI xfs")}, - {SGI_XFSLOG, N_("SGI xfslog")}, - {SGI_XLV, N_("SGI xlv")}, - {SGI_XVM, N_("SGI xvm")}, - {LINUX_SWAP, N_("Linux swap")}, - {LINUX_NATIVE, N_("Linux native")}, - {LINUX_LVM, N_("Linux LVM")}, - {LINUX_RAID, N_("Linux RAID")}, - {0, NULL } -}; - -static int -sgi_get_nsect(struct fdisk_context *cxt) { - return SSWAP16(sgilabel->devparam.nsect); -} - -static int -sgi_get_ntrks(struct fdisk_context *cxt) { - return SSWAP16(sgilabel->devparam.ntrks); -} - -static unsigned int -two_s_complement_32bit_sum(unsigned int *base, int size /* in bytes */) { - int i = 0; - unsigned int sum = 0; - - size /= sizeof(unsigned int); - for (i = 0; i < size; i++) - sum -= SSWAP32(base[i]); - return sum; -} - -int -check_sgi_label(struct fdisk_context *cxt) { - if (sizeof(sgilabel) > 512) { - fprintf(stderr, - _("According to MIPS Computer Systems, Inc the " - "Label must not contain more than 512 bytes\n")); - exit(1); - } - - if (sgilabel->magic != SGI_LABEL_MAGIC && - sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) { - other_endian = 0; - return 0; - } - - other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED); - /* - * test for correct checksum - */ - if (two_s_complement_32bit_sum((unsigned int*)sgilabel, - sizeof(*sgilabel))) { - fprintf(stderr, - _("Detected sgi disklabel with wrong checksum.\n")); - } - update_units(cxt); - disklabel = SGI_LABEL; - partitions= 16; - volumes = 15; - return 1; -} - -void -sgi_list_table(struct fdisk_context *cxt, int xtra) { - int i, w; - int kpi = 0; /* kernel partition ID */ - char *type; - - w = strlen(cxt->dev_path); - - if (xtra) { - printf(_("\nDisk %s (SGI disk label): %d heads, %llu sectors\n" - "%llu cylinders, %d physical cylinders\n" - "%d extra sects/cyl, interleave %d:1\n" - "%s\n" - "Units = %s of %d * %ld bytes\n\n"), - cxt->dev_path, cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders, - SSWAP16(sgiparam.pcylcount), - (int) sgiparam.sparecyl, SSWAP16(sgiparam.ilfact), - (char *)sgilabel, - str_units(PLURAL), units_per_sector, - cxt->sector_size); - } else { - printf(_("\nDisk %s (SGI disk label): " - "%d heads, %llu sectors, %llu cylinders\n" - "Units = %s of %d * %ld bytes\n\n"), - cxt->dev_path, cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders, - str_units(PLURAL), units_per_sector, - cxt->sector_size); - } - printf(_("----- partitions -----\n" - "Pt# %*s Info Start End Sectors Id System\n"), - w + 1, _("Device")); - for (i = 0 ; i < partitions; i++) { - if (sgi_get_num_sectors(cxt, i) || debug) { - uint32_t start = sgi_get_start_sector(cxt, i); - uint32_t len = sgi_get_num_sectors(cxt, i); - kpi++; /* only count nonempty partitions */ - printf( - "%2d: %s %4s %9ld %9ld %9ld %2x %s\n", -/* fdisk part number */ i+1, -/* device */ partname(cxt->dev_path, kpi, w+2), -/* flags */ (sgi_get_swappartition(cxt) == i) ? "swap" : -/* flags */ (sgi_get_bootpartition(cxt) == i) ? "boot" : " ", -/* start */ (long) scround(start), -/* end */ (long) scround(start+len)-1, -/* no odd flag on end */ (long) len, -/* type id */ sgi_get_sysid(cxt, i), -/* type name */ (type = partition_type(sgi_get_sysid(cxt, i))) - ? type : _("Unknown")); - } - } - printf(_("----- Bootinfo -----\nBootfile: %s\n" - "----- Directory Entries -----\n"), - sgilabel->boot_file); - for (i = 0 ; i < volumes; i++) { - if (sgilabel->directory[i].vol_file_size) { - uint32_t start = SSWAP32(sgilabel->directory[i].vol_file_start); - uint32_t len = SSWAP32(sgilabel->directory[i].vol_file_size); - unsigned char *name = sgilabel->directory[i].vol_file_name; - printf(_("%2d: %-10s sector%5u size%8u\n"), - i, name, (unsigned int) start, - (unsigned int) len); - } - } -} - -unsigned int -sgi_get_start_sector(struct fdisk_context *cxt, int i) { - return SSWAP32(sgilabel->partitions[i].start_sector); -} - -unsigned int -sgi_get_num_sectors(struct fdisk_context *cxt, int i) { - return SSWAP32(sgilabel->partitions[i].num_sectors); -} - -int -sgi_get_sysid(struct fdisk_context *cxt, int i) -{ - return SSWAP32(sgilabel->partitions[i].id); -} - -int -sgi_get_bootpartition(struct fdisk_context *cxt) -{ - return (short) SSWAP16(sgilabel->boot_part); -} - -int -sgi_get_swappartition(struct fdisk_context *cxt) -{ - return (short) SSWAP16(sgilabel->swap_part); -} - -void -sgi_set_bootpartition(struct fdisk_context *cxt, int i) -{ - sgilabel->boot_part = SSWAP16(((short)i)); -} - -static unsigned int -sgi_get_lastblock(struct fdisk_context *cxt) { - return cxt->geom.heads * cxt->geom.sectors * cxt->geom.cylinders; -} - -void -sgi_set_swappartition(struct fdisk_context *cxt, int i) { - sgilabel->swap_part = SSWAP16(((short)i)); -} - -static int -sgi_check_bootfile(struct fdisk_context *cxt, const char* aFile) { - if (strlen(aFile) < 3) /* "/a\n" is minimum */ { - printf(_("\nInvalid Bootfile!\n" - "\tThe bootfile must be an absolute non-zero pathname,\n" - "\te.g. \"/unix\" or \"/unix.save\".\n")); - return 0; - } else { - if (strlen(aFile) > 16) { - printf(_("\n\tName of Bootfile too long: " - "16 bytes maximum.\n")); - return 0; - } else { - if (aFile[0] != '/') { - printf(_("\n\tBootfile must have a " - "fully qualified pathname.\n")); - return 0; - } - } - } - if (strncmp(aFile, (char *) sgilabel->boot_file, 16)) { - printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t" - "SGI's default is \"/unix\" and for backup \"/unix.save\".\n")); - /* filename is correct and did change */ - return 1; - } - return 0; /* filename did not change */ -} - -void -sgi_set_bootfile(struct fdisk_context *cxt) -{ - printf(_("\nThe current boot file is: %s\n"), sgilabel->boot_file); - if (read_chars(_("Please enter the name of the new boot file: ")) == '\n') { - printf(_("Boot file unchanged\n")); - return; - } - - if (sgi_check_bootfile(cxt, line_ptr)) { - size_t i = 0; - while (i < 16) { - if ((line_ptr[i] != '\n') /* in principle caught again by next line */ - && (strlen(line_ptr) > i)) - sgilabel->boot_file[i] = line_ptr[i]; - else - sgilabel->boot_file[i] = 0; - i++; - } - printf(_("\n\tBootfile is changed to \"%s\".\n"), - sgilabel->boot_file); - } -} - -void -create_sgiinfo(struct fdisk_context *cxt) { - /* I keep SGI's habit to write the sgilabel to the second block */ - sgilabel->directory[0].vol_file_start = SSWAP32(2); - sgilabel->directory[0].vol_file_size = SSWAP32(sizeof(sgiinfo)); - strncpy((char *) sgilabel->directory[0].vol_file_name, "sgilabel", 8); -} - -sgiinfo *fill_sgiinfo(void); - -void -sgi_write_table(struct fdisk_context *cxt) { - sgilabel->csum = 0; - sgilabel->csum = SSWAP32(two_s_complement_32bit_sum( - (unsigned int*)sgilabel, - sizeof(*sgilabel))); - assert(two_s_complement_32bit_sum( - (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0); - if (lseek(cxt->dev_fd, 0, SEEK_SET) < 0) - fatal(cxt, unable_to_seek); - if (write(cxt->dev_fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE) - fatal(cxt, unable_to_write); - if (! strncmp((char *) sgilabel->directory[0].vol_file_name, "sgilabel", 8)) { - /* - * keep this habit of first writing the "sgilabel". - * I never tested whether it works without (AN 981002). - */ - sgiinfo *info = fill_sgiinfo(); - int infostartblock = SSWAP32(sgilabel->directory[0].vol_file_start); - if (lseek(cxt->dev_fd, (off_t) infostartblock* - SECTOR_SIZE, SEEK_SET) < 0) - fatal(cxt, unable_to_seek); - if (write(cxt->dev_fd, info, SECTOR_SIZE) != SECTOR_SIZE) - fatal(cxt, unable_to_write); - free(info); - } -} - -static int -compare_start(struct fdisk_context *cxt, const void *x, const void *y) { - /* - * sort according to start sectors - * and prefers largest partition: - * entry zero is entire disk entry - */ - unsigned int i = *(int *) x; - unsigned int j = *(int *) y; - unsigned int a = sgi_get_start_sector(cxt, i); - unsigned int b = sgi_get_start_sector(cxt, j); - unsigned int c = sgi_get_num_sectors(cxt, i); - unsigned int d = sgi_get_num_sectors(cxt, j); - - if (a == b) - return (d > c) ? 1 : (d == c) ? 0 : -1; - return (a > b) ? 1 : -1; -} - -static int -sgi_gaps(struct fdisk_context *cxt) { - /* - * returned value is: - * = 0 : disk is properly filled to the rim - * < 0 : there is an overlap - * > 0 : there is still some vacant space - */ - return verify_sgi(cxt, 0); -} - -static void generic_swap(void *a, void *b, int size) -{ - char t; - - do { - t = *(char *)a; - *(char *)a++ = *(char *)b; - *(char *)b++ = t; - } while (--size > 0); -} - - -/* heap sort, based on Matt Mackall's linux kernel version */ -static void sort(void *base, size_t num, size_t size, struct fdisk_context *cxt, - int (*cmp_func)(struct fdisk_context *, const void *, const void *)) -{ - /* pre-scale counters for performance */ - int i = (num/2 - 1) * size; - size_t n = num * size, c, r; - - /* heapify */ - for ( ; i >= 0; i -= size) { - for (r = i; r * 2 + size < n; r = c) { - c = r * 2 + size; - if (c < n - size && - cmp_func(cxt, base + c, base + c + size) < 0) - c += size; - if (cmp_func(cxt, base + r, base + c) >= 0) - break; - generic_swap(base + r, base + c, size); - } - } - - /* sort */ - for (i = n - size; i > 0; i -= size) { - generic_swap(base, base + i, size); - for (r = 0; r * 2 + size < (size_t) i; r = c) { - c = r * 2 + size; - if (c < i - size && - cmp_func(cxt, base + c, base + c + size) < 0) - c += size; - if (cmp_func(cxt, base + r, base + c) >= 0) - break; - generic_swap(base + r, base + c, size); - } - } -} - - -int -verify_sgi(struct fdisk_context *cxt, int verbose) -{ - int Index[16]; /* list of valid partitions */ - int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */ - int entire = 0, i = 0; - unsigned int start = 0; - long long gap = 0; /* count unused blocks */ - unsigned int lastblock = sgi_get_lastblock(cxt); - - clearfreelist(); - for (i=0; i<16; i++) { - if (sgi_get_num_sectors(cxt, i) != 0) { - Index[sortcount++]=i; - if (sgi_get_sysid(cxt, i) == ENTIRE_DISK) { - if (entire++ == 1) { - if (verbose) - printf(_("More than one entire disk entry present.\n")); - } - } - } - } - if (sortcount == 0) { - if (verbose) - printf(_("No partitions defined\n")); - return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1; - } - - sort(Index, sortcount, sizeof(Index[0]), cxt, compare_start); - - if (sgi_get_sysid(cxt, Index[0]) == ENTIRE_DISK) { - if ((Index[0] != 10) && verbose) - printf(_("IRIX likes when Partition 11 covers the entire disk.\n")); - if ((sgi_get_start_sector(cxt, Index[0]) != 0) && verbose) - printf(_("The entire disk partition should start " - "at block 0,\n" - "not at diskblock %d.\n"), - sgi_get_start_sector(cxt, Index[0])); - if (debug) /* I do not understand how some disks fulfil it */ - if ((sgi_get_num_sectors(cxt, Index[0]) != lastblock) && verbose) - printf(_("The entire disk partition is only %d diskblock large,\n" - "but the disk is %d diskblocks long.\n"), - sgi_get_num_sectors(cxt, Index[0]), lastblock); - lastblock = sgi_get_num_sectors(cxt, Index[0]); - } else { - if (verbose) - printf(_("Partition 11 should cover the entire disk.\n")); - if (debug>2) - printf("sysid=%d\tpartition=%d\n", - sgi_get_sysid(cxt, Index[0]), Index[0]+1); - } - for (i=1, start=0; i<sortcount; i++) { - int cylsize = sgi_get_nsect(cxt) * sgi_get_ntrks(cxt); - if ((sgi_get_start_sector(cxt, Index[i]) % cylsize) != 0) { - if (debug) /* I do not understand how some disks fulfil it */ - if (verbose) - printf(_("Partition %d does not start on cylinder boundary.\n"), - Index[i]+1); - } - if (sgi_get_num_sectors(cxt, Index[i]) % cylsize != 0) { - if (debug) /* I do not understand how some disks fulfil it */ - if (verbose) - printf(_("Partition %d does not end on cylinder boundary.\n"), - Index[i]+1); - } - /* We cannot handle several "entire disk" entries. */ - if (sgi_get_sysid(cxt, Index[i]) == ENTIRE_DISK) continue; - if (start > sgi_get_start_sector(cxt, Index[i])) { - if (verbose) - printf(_("The Partition %d and %d overlap by %d sectors.\n"), - Index[i-1]+1, Index[i]+1, - start - sgi_get_start_sector(cxt, Index[i])); - if (gap > 0) gap = -gap; - if (gap == 0) gap = -1; - } - if (start < sgi_get_start_sector(cxt, Index[i])) { - if (verbose) - printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"), - sgi_get_start_sector(cxt, Index[i]) - start, - start, sgi_get_start_sector(cxt, Index[i])-1); - gap += sgi_get_start_sector(cxt, Index[i]) - start; - add2freelist(start, sgi_get_start_sector(cxt, Index[i])); - } - start = sgi_get_start_sector(cxt, Index[i]) - + sgi_get_num_sectors(cxt, Index[i]); - /* Align free space on cylinder boundary */ - if (start % cylsize) - start += cylsize - (start % cylsize); - if (debug > 1) { - if (verbose) - printf("%2d:%12d\t%12d\t%12d\n", Index[i], - sgi_get_start_sector(cxt, Index[i]), - sgi_get_num_sectors(cxt, Index[i]), - sgi_get_sysid(cxt, Index[i])); - } - } - if (start < lastblock) { - if (verbose) - printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"), - lastblock - start, start, lastblock-1); - gap += lastblock - start; - add2freelist(start, lastblock); - } - /* - * Done with arithmetics - * Go for details now - */ - if (verbose) { - if (sgi_get_bootpartition(cxt) < 0 || !sgi_get_num_sectors(cxt, sgi_get_bootpartition(cxt))) { - printf(_("\nThe boot partition does not exist.\n")); - } - if (sgi_get_swappartition(cxt) < 0 || !sgi_get_num_sectors(cxt, sgi_get_swappartition(cxt))) { - printf(_("\nThe swap partition does not exist.\n")); - } else { - if ((sgi_get_sysid(cxt, sgi_get_swappartition(cxt)) != SGI_SWAP) - && (sgi_get_sysid(cxt, sgi_get_swappartition(cxt)) != LINUX_SWAP)) - printf(_("\nThe swap partition has no swap type.\n")); - } - if (sgi_check_bootfile(cxt, "/unix")) - printf(_("\tYou have chosen an unusual boot file name.\n")); - } - return (gap > 0) ? 1 : (gap == 0) ? 0 : -1; -} - -int -sgi_change_sysid(struct fdisk_context *cxt, int i, int sys) -{ - if (sgi_get_num_sectors(cxt, i) == 0) /* caught already before, ... */ { - printf(_("Sorry, only for non-empty partitions you can change the tag.\n")); - return 0; - } - if (((sys != ENTIRE_DISK) && (sys != SGI_VOLHDR)) - && (sgi_get_start_sector(cxt, i)<1)) { - read_chars( - _("It is highly recommended that the partition at offset 0\n" - "is of type \"SGI volhdr\", the IRIX system will rely on it to\n" - "retrieve from its directory standalone tools like sash and fx.\n" - "Only the \"SGI volume\" entire disk section may violate this.\n" - "Type YES if you are sure about tagging this partition differently.\n")); - if (strcmp (line_ptr, _("YES\n"))) - return 0; - } - sgilabel->partitions[i].id = SSWAP32(sys); - return 1; -} - -/* returns partition index of first entry marked as entire disk */ -static int -sgi_entire(struct fdisk_context *cxt) { - int i; - - for (i=0; i<16; i++) - if (sgi_get_sysid(cxt, i) == SGI_VOLUME) - return i; - return -1; -} - -static void -sgi_set_partition(struct fdisk_context *cxt, - int i, unsigned int start, unsigned int length, int sys) { - sgilabel->partitions[i].id = SSWAP32(sys); - sgilabel->partitions[i].num_sectors = SSWAP32(length); - sgilabel->partitions[i].start_sector = SSWAP32(start); - set_changed(i); - if (sgi_gaps(cxt) < 0) /* rebuild freelist */ - printf(_("Partition overlap on the disk.\n")); - if (length) - print_partition_size(cxt, i + 1, start, start + length, sys); -} - -static void -sgi_set_entire(struct fdisk_context *cxt) { - int n; - - for (n=10; n<partitions; n++) { - if (!sgi_get_num_sectors(cxt, n)) { - sgi_set_partition(cxt, n, 0, sgi_get_lastblock(cxt), SGI_VOLUME); - break; - } - } -} - -static -void -sgi_set_volhdr(struct fdisk_context *cxt) -{ - int n; - - for (n=8; n<partitions; n++) { - if (!sgi_get_num_sectors(cxt, n)) { - /* - * Choose same default volume header size - * as IRIX fx uses. - */ - if (4096 < sgi_get_lastblock(cxt)) - sgi_set_partition(cxt, n, 0, 4096, SGI_VOLHDR); - break; - } - } -} - -void -sgi_delete_partition(struct fdisk_context *cxt, int i) -{ - sgi_set_partition(cxt, i, 0, 0, 0); -} - -void -sgi_add_partition(struct fdisk_context *cxt, int n, int sys) -{ - char mesg[256]; - unsigned int first=0, last=0; - - if (n == 10) { - sys = SGI_VOLUME; - } else if (n == 8) { - sys = 0; - } - if (sgi_get_num_sectors(cxt, n)) { - printf(_("Partition %d is already defined. Delete " - "it before re-adding it.\n"), n + 1); - return; - } - if ((sgi_entire(cxt) == -1) - && (sys != SGI_VOLUME)) { - printf(_("Attempting to generate entire disk entry automatically.\n")); - sgi_set_entire(cxt); - sgi_set_volhdr(cxt); - } - if ((sgi_gaps(cxt) == 0) && (sys != SGI_VOLUME)) { - printf(_("The entire disk is already covered with partitions.\n")); - return; - } - if (sgi_gaps(cxt) < 0) { - printf(_("You got a partition overlap on the disk. Fix it first!\n")); - return; - } - snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR)); - for (;;) { - if (sys == SGI_VOLUME) { - last = sgi_get_lastblock(cxt); - first = read_int(cxt, 0, 0, last-1, 0, mesg); - if (first != 0) { - printf(_("It is highly recommended that eleventh partition\n" - "covers the entire disk and is of type `SGI volume'\n")); - } - } else { - first = freelist[0].first; - last = freelist[0].last; - first = read_int(cxt, scround(first), scround(first), scround(last)-1, - 0, mesg); - } - if (display_in_cyl_units) - first *= units_per_sector; - /*else - first = first; * align to cylinder if you know how ... */ - if (!last) - last = isinfreelist(first); - if (last == 0) { - printf(_("You will get a partition overlap on the disk. " - "Fix it first!\n")); - } else - break; - } - snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR)); - last = read_int(cxt, scround(first), scround(last)-1, scround(last)-1, - scround(first), mesg)+1; - if (display_in_cyl_units) - last *= units_per_sector; - /*else - last = last; * align to cylinder if You know how ... */ - if ((sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock(cxt))) - printf(_("It is highly recommended that eleventh partition\n" - "covers the entire disk and is of type `SGI volume'\n")); - sgi_set_partition(cxt, n, first, last-first, sys); -} - -void -create_sgilabel(struct fdisk_context *cxt) -{ - struct hd_geometry geometry; - struct { - unsigned int start; - unsigned int nsect; - int sysid; - } old[4]; - int i=0; - sector_t llsectors; - int res; /* the result from the ioctl */ - int sec_fac; /* the sector factor */ - - sec_fac = cxt->sector_size / 512; /* determine the sector factor */ - - fprintf(stderr, - _("Building a new SGI disklabel.\n")); - - other_endian = (BYTE_ORDER == LITTLE_ENDIAN); - - res = blkdev_get_sectors(cxt->dev_fd, &llsectors); - -#ifdef HDIO_GETGEO - if (ioctl(cxt->dev_fd, HDIO_GETGEO, &geometry) < 0) - err(EXIT_FAILURE, _("HDIO_GETGEO ioctl failed on %s"), cxt->dev_path); - - cxt->geom.heads = geometry.heads; - cxt->geom.sectors = geometry.sectors; - if (res == 0) { - /* the get device size ioctl was successful */ - sector_t llcyls; - llcyls = llsectors / (cxt->geom.heads * cxt->geom.sectors * sec_fac); - cxt->geom.cylinders = llcyls; - if (cxt->geom.cylinders != llcyls) /* truncated? */ - cxt->geom.cylinders = ~0; - } else { - /* otherwise print error and use truncated version */ - cxt->geom.cylinders = geometry.cylinders; - fprintf(stderr, - _("Warning: BLKGETSIZE ioctl failed on %s. " - "Using geometry cylinder value of %llu.\n" - "This value may be truncated for devices" - " > 33.8 GB.\n"), cxt->dev_path, cxt->geom.cylinders); - } -#endif - for (i = 0; i < 4; i++) { - old[i].sysid = 0; - if (valid_part_table_flag(cxt->mbr)) { - if (get_part_table(i)->sys_ind) { - old[i].sysid = get_part_table(i)->sys_ind; - old[i].start = get_start_sect(get_part_table(i)); - old[i].nsect = get_nr_sects(get_part_table(i)); - if (debug) - printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"), - old[i].sysid, old[i].start, old[i].nsect); - } - } - } - - for (i = 0; i < 4; i++) - if (old[i].sysid) { - printf(_("Trying to keep parameters of partitions already set.\n")); - break; - } - - fdisk_mbr_zeroize(cxt); - sgilabel->magic = SSWAP32(SGI_LABEL_MAGIC); - sgilabel->boot_part = SSWAP16(0); - sgilabel->swap_part = SSWAP16(1); - - /* sizeof(sgilabel->boot_file) = 16 > 6 */ - memset(sgilabel->boot_file, 0, 16); - strcpy((char *) sgilabel->boot_file, "/unix"); - - sgilabel->devparam.skew = (0); - sgilabel->devparam.gap1 = (0); - sgilabel->devparam.gap2 = (0); - sgilabel->devparam.sparecyl = (0); - sgilabel->devparam.pcylcount = SSWAP16(geometry.cylinders); - sgilabel->devparam.head_vol0 = SSWAP16(0); - sgilabel->devparam.ntrks = SSWAP16(geometry.heads); - /* tracks/cylinder (heads) */ - sgilabel->devparam.cmd_tag_queue_depth = (0); - sgilabel->devparam.unused0 = (0); - sgilabel->devparam.unused1 = SSWAP16(0); - sgilabel->devparam.nsect = SSWAP16(geometry.sectors); - /* sectors/track */ - sgilabel->devparam.bytes = SSWAP16(cxt->sector_size); - sgilabel->devparam.ilfact = SSWAP16(1); - sgilabel->devparam.flags = SSWAP32(TRACK_FWD|\ - IGNORE_ERRORS|RESEEK); - sgilabel->devparam.datarate = SSWAP32(0); - sgilabel->devparam.retries_on_error = SSWAP32(1); - sgilabel->devparam.ms_per_word = SSWAP32(0); - sgilabel->devparam.xylogics_gap1 = SSWAP16(0); - sgilabel->devparam.xylogics_syncdelay = SSWAP16(0); - sgilabel->devparam.xylogics_readdelay = SSWAP16(0); - sgilabel->devparam.xylogics_gap2 = SSWAP16(0); - sgilabel->devparam.xylogics_readgate = SSWAP16(0); - sgilabel->devparam.xylogics_writecont = SSWAP16(0); - memset(&(sgilabel->directory), 0, sizeof(struct volume_directory)*15); - memset(&(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16); - disklabel = SGI_LABEL; - partitions = 16; - volumes = 15; - sgi_set_entire(cxt); - sgi_set_volhdr(cxt); - for (i = 0; i < 4; i++) { - if (old[i].sysid) { - sgi_set_partition(cxt, i, old[i].start, old[i].nsect, old[i].sysid); - } - } -} - -void -sgi_set_ilfact(void) -{ - /* do nothing in the beginning */ -} - -void -sgi_set_rspeed(void) -{ - /* do nothing in the beginning */ -} - -void -sgi_set_pcylcount(void) -{ - /* do nothing in the beginning */ -} - -void -sgi_set_xcyl(void) -{ - /* do nothing in the beginning */ -} - -void -sgi_set_ncyl(void) -{ - /* do nothing in the beginning */ -} - -/* _____________________________________________________________ - */ - -sgiinfo * -fill_sgiinfo(void) -{ - sgiinfo *info=xcalloc(1, sizeof(sgiinfo)); - info->magic=SSWAP32(SGI_INFO_MAGIC); - info->b1=SSWAP32(-1); - info->b2=SSWAP16(-1); - info->b3=SSWAP16(1); - /* You may want to replace this string !!!!!!! */ - strcpy((char *) info->scsi_string, "IBM OEM 0662S12 3 30"); - strcpy((char *) info->serial, "0000"); - info->check1816 = SSWAP16(18*256 +16); - strcpy((char *) info->installer, "Sfx version 5.3, Oct 18, 1994"); - return info; -} diff --git a/fdisk/fdisksgilabel.h b/fdisk/fdisksgilabel.h deleted file mode 100644 index 0c76edb91..000000000 --- a/fdisk/fdisksgilabel.h +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef FDISK_SGI_LABEL_H -#define FDISK_SGI_LABEL_H - -#include <stdint.h> - -#include "bitops.h" - -/* - * Copyright (C) Andreas Neuper, Sep 1998. - * This file may be modified and redistributed under - * the terms of the GNU Public License. - */ - -struct device_parameter { /* 48 bytes */ - unsigned char skew; - unsigned char gap1; - unsigned char gap2; - unsigned char sparecyl; - unsigned short pcylcount; - unsigned short head_vol0; - unsigned short ntrks; /* tracks in cyl 0 or vol 0 */ - unsigned char cmd_tag_queue_depth; - unsigned char unused0; - unsigned short unused1; - unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */ - unsigned short bytes; - unsigned short ilfact; - unsigned int flags; /* controller flags */ - unsigned int datarate; - unsigned int retries_on_error; - unsigned int ms_per_word; - unsigned short xylogics_gap1; - unsigned short xylogics_syncdelay; - unsigned short xylogics_readdelay; - unsigned short xylogics_gap2; - unsigned short xylogics_readgate; - unsigned short xylogics_writecont; -}; - -#define SGI_VOLHDR 0x00 -/* 1 and 2 were used for drive types no longer supported by SGI */ -#define SGI_SWAP 0x03 -/* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */ -#define SGI_VOLUME 0x06 -#define SGI_EFS 0x07 -#define SGI_LVOL 0x08 -#define SGI_RLVOL 0x09 -#define SGI_XFS 0x0a -#define SGI_XFSLOG 0x0b -#define SGI_XLV 0x0c -#define SGI_XVM 0x0d -#define ENTIRE_DISK SGI_VOLUME -/* - * controller flags - */ -#define SECTOR_SLIP 0x01 -#define SECTOR_FWD 0x02 -#define TRACK_FWD 0x04 -#define TRACK_MULTIVOL 0x08 -#define IGNORE_ERRORS 0x10 -#define RESEEK 0x20 -#define CMDTAGQ_ENABLE 0x40 - -typedef struct { - unsigned int magic; /* expect SGI_LABEL_MAGIC */ - short boot_part; /* active boot partition */ - short swap_part; /* active swap partition */ - unsigned char boot_file[16]; /* name of the bootfile */ - struct device_parameter devparam; /* 1 * 48 bytes */ - struct volume_directory { /* 15 * 16 bytes */ - unsigned char vol_file_name[8]; /* a character array */ - unsigned int vol_file_start; /* number of logical block */ - unsigned int vol_file_size; /* number of bytes */ - } directory[15]; - struct sgi_partition { /* 16 * 12 bytes */ - unsigned int num_sectors; /* number of blocks */ - unsigned int start_sector; /* must be cylinder aligned */ - unsigned int id; - } partitions[16]; - unsigned int csum; - unsigned int fillbytes; -} sgi_partition; - -typedef struct { - unsigned int magic; /* looks like a magic number */ - unsigned int a2; - unsigned int a3; - unsigned int a4; - unsigned int b1; - unsigned short b2; - unsigned short b3; - unsigned int c[16]; - unsigned short d[3]; - unsigned char scsi_string[50]; - unsigned char serial[137]; - unsigned short check1816; - unsigned char installer[225]; -} sgiinfo; - -#define SGI_LABEL_MAGIC 0x0be5a941 -#define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b -#define SGI_INFO_MAGIC 0x00072959 -#define SGI_INFO_MAGIC_SWAPPED 0x59290700 - -#define SSWAP16(x) (other_endian ? swab16(x) : (uint16_t)(x)) -#define SSWAP32(x) (other_endian ? swab32(x) : (uint32_t)(x)) - -/* fdisk.c */ -#define sgilabel ((sgi_partition *)cxt->mbr) -#define sgiparam (sgilabel->devparam) - -/* fdisksgilabel.c */ -extern struct systypes sgi_sys_types[]; -extern int check_sgi_label(struct fdisk_context *cxt); -extern void sgi_list_table( struct fdisk_context *cxt, int xtra ); -extern int sgi_change_sysid(struct fdisk_context *cxt, int i, int sys); -extern unsigned int sgi_get_start_sector(struct fdisk_context *cxt, int i ); -extern unsigned int sgi_get_num_sectors(struct fdisk_context *cxt, int i ); -extern int sgi_get_sysid(struct fdisk_context *cxt, int i ); -extern void sgi_delete_partition( struct fdisk_context *cxt, int i ); -extern void sgi_add_partition( struct fdisk_context *cxt, int n, int sys ); -extern void create_sgilabel( struct fdisk_context *cxt ); -extern void create_sgiinfo(struct fdisk_context *cxt); -extern int verify_sgi(struct fdisk_context *cxt, int verbose ); -extern void sgi_write_table( struct fdisk_context *cxt ); -extern void sgi_set_ilfact( void ); -extern void sgi_set_rspeed( void ); -extern void sgi_set_pcylcount( void ); -extern void sgi_set_xcyl( void ); -extern void sgi_set_ncyl( void ); -extern void sgi_set_bootpartition(struct fdisk_context *cxt, int i ); -extern void sgi_set_swappartition(struct fdisk_context *cxt, int i ); -extern int sgi_get_bootpartition(struct fdisk_context *cxt); -extern int sgi_get_swappartition(struct fdisk_context *cxt); -extern void sgi_set_bootfile(struct fdisk_context *cxt); - -#endif /* FDISK_SGI_LABEL_H */ diff --git a/fdisk/fdisksunlabel.c b/fdisk/fdisksunlabel.c deleted file mode 100644 index 65cbf8f16..000000000 --- a/fdisk/fdisksunlabel.c +++ /dev/null @@ -1,643 +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. - * - * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br> - * Internationalization - */ - -#include <stdio.h> /* stderr */ -#include <stdlib.h> /* qsort */ -#include <string.h> /* strstr */ -#include <unistd.h> /* write */ -#include <sys/ioctl.h> /* ioctl */ - -#include "nls.h" -#include "blkdev.h" - -#include <endian.h> - -#include "common.h" -#include "fdisk.h" -#include "fdisksunlabel.h" - -static int other_endian = 0; - -struct systypes sun_sys_types[] = { - {SUN_TAG_UNASSIGNED, N_("Unassigned")}, - {SUN_TAG_BOOT, N_("Boot")}, - {SUN_TAG_ROOT, N_("SunOS root")}, - {SUN_TAG_SWAP, N_("SunOS swap")}, - {SUN_TAG_USR, N_("SunOS usr")}, - {SUN_TAG_BACKUP, N_("Whole disk")}, - {SUN_TAG_STAND, N_("SunOS stand")}, - {SUN_TAG_VAR, N_("SunOS var")}, - {SUN_TAG_HOME, N_("SunOS home")}, - {SUN_TAG_ALTSCTR, N_("SunOS alt sectors")}, - {SUN_TAG_CACHE, N_("SunOS cachefs")}, - {SUN_TAG_RESERVED, N_("SunOS reserved")}, - {SUN_TAG_LINUX_SWAP, N_("Linux swap")}, - {SUN_TAG_LINUX_NATIVE, N_("Linux native")}, - {SUN_TAG_LINUX_LVM, N_("Linux LVM")}, - {SUN_TAG_LINUX_RAID, N_("Linux raid autodetect")}, - { 0, NULL } -}; - -static inline unsigned short __swap16(unsigned short x) { - return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8); -} -static inline uint32_t __swap32(uint32_t x) { - return (((uint32_t)(x) & 0xFF) << 24) | (((uint32_t)(x) & 0xFF00) << 8) | (((uint32_t)(x) & 0xFF0000) >> 8) | (((uint32_t)(x) & 0xFF000000) >> 24); -} - -#define SSWAP16(x) (other_endian ? __swap16(x) \ - : (uint16_t)(x)) -#define SSWAP32(x) (other_endian ? __swap32(x) \ - : (uint32_t)(x)) - -static void set_sun_partition(struct fdisk_context *cxt, - int i, uint32_t start, uint32_t stop, uint16_t sysid) -{ - sunlabel->part_tags[i].tag = SSWAP16(sysid); - sunlabel->part_tags[i].flag = SSWAP16(0); - sunlabel->partitions[i].start_cylinder = - SSWAP32(start / (cxt->geom.heads * cxt->geom.sectors)); - sunlabel->partitions[i].num_sectors = - SSWAP32(stop - start); - set_changed(i); - print_partition_size(cxt, i + 1, start, stop, sysid); -} - -static void init(void) -{ - disklabel = SUN_LABEL; - partitions = SUN_NUM_PARTITIONS; -} - -int check_sun_label(struct fdisk_context *cxt) -{ - unsigned short *ush; - int csum; - - if (sunlabel->magic != SUN_LABEL_MAGIC && - sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) { - other_endian = 0; - return 0; - } - - init(); - 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 { - int need_fixing = 0; - - cxt->geom.heads = SSWAP16(sunlabel->nhead); - cxt->geom.cylinders = SSWAP16(sunlabel->ncyl); - cxt->geom.sectors = SSWAP16(sunlabel->nsect); - - if (sunlabel->version != SSWAP32(SUN_LABEL_VERSION)) { - fprintf(stderr,_("Detected sun disklabel with wrong version [0x%08x].\n"), - SSWAP32(sunlabel->version)); - need_fixing = 1; - } - if (sunlabel->sanity != SSWAP32(SUN_LABEL_SANE)) { - fprintf(stderr,_("Detected sun disklabel with wrong sanity [0x%08x].\n"), - SSWAP32(sunlabel->sanity)); - need_fixing = 1; - } - if (sunlabel->num_partitions != SSWAP16(SUN_NUM_PARTITIONS)) { - fprintf(stderr,_("Detected sun disklabel with wrong num_partitions [%u].\n"), - SSWAP16(sunlabel->num_partitions)); - need_fixing = 1; - } - if (need_fixing) { - fprintf(stderr, _("Warning: Wrong values need to be " - "fixed up and will be corrected " - "by w(rite)\n")); - sunlabel->version = SSWAP32(SUN_LABEL_VERSION); - sunlabel->sanity = SSWAP32(SUN_LABEL_SANE); - sunlabel->num_partitions = SSWAP16(SUN_NUM_PARTITIONS); - - ush = (unsigned short *)sunlabel; - csum = 0; - while(ush < (unsigned short *)(&sunlabel->cksum)) - csum ^= *ush++; - sunlabel->cksum = csum; - - set_changed(0); - } - } - update_units(cxt); - return 1; -} - -void create_sunlabel(struct fdisk_context *cxt) -{ - struct hd_geometry geometry; - sector_t llsectors, llcyls; - unsigned int ndiv, sec_fac; - int res; - - fprintf(stderr, - _("Building a new Sun disklabel.\n")); -#if BYTE_ORDER == LITTLE_ENDIAN - other_endian = 1; -#else - other_endian = 0; -#endif - - init(); - fdisk_mbr_zeroize(cxt); - - sunlabel->magic = SSWAP16(SUN_LABEL_MAGIC); - sunlabel->sanity = SSWAP32(SUN_LABEL_SANE); - sunlabel->version = SSWAP32(SUN_LABEL_VERSION); - sunlabel->num_partitions = SSWAP16(SUN_NUM_PARTITIONS); - - res = blkdev_get_sectors(cxt->dev_fd, &llsectors); - sec_fac = cxt->sector_size / 512; - -#ifdef HDIO_GETGEO - if (!ioctl(cxt->dev_fd, HDIO_GETGEO, &geometry)) { - cxt->geom.heads = geometry.heads; - cxt->geom.sectors = geometry.sectors; - if (res == 0) { - llcyls = llsectors / (cxt->geom.heads * cxt->geom.sectors * sec_fac); - cxt->geom.cylinders = llcyls; - if (cxt->geom.cylinders != llcyls) - cxt->geom.cylinders = ~0; - } else { - cxt->geom.cylinders = geometry.cylinders; - fprintf(stderr, - _("Warning: BLKGETSIZE ioctl failed on %s. " - "Using geometry cylinder value of %llu.\n" - "This value may be truncated for devices" - " > 33.8 GB.\n"), cxt->dev_path, cxt->geom.cylinders); - } - } else -#endif - { - cxt->geom.heads = read_int(cxt, 1,1,1024,0,_("Heads")); - cxt->geom.sectors = read_int(cxt, 1,1,1024,0,_("Sectors/track")); - cxt->geom.cylinders = read_int(cxt, 1,1,65535,0,_("Cylinders")); - } - - sunlabel->acyl = SSWAP16(2); - sunlabel->pcyl = SSWAP16(cxt->geom.cylinders); - sunlabel->ncyl = SSWAP16(cxt->geom.cylinders - 2); - sunlabel->rpm = SSWAP16(5400); - sunlabel->intrlv = SSWAP16(1); - sunlabel->apc = SSWAP16(0); - - sunlabel->nhead = SSWAP16(cxt->geom.heads); - sunlabel->nsect = SSWAP16(cxt->geom.sectors); - sunlabel->ncyl = SSWAP16(cxt->geom.cylinders); - - snprintf(sunlabel->label_id, sizeof(sunlabel->label_id), - "Linux cyl %llu alt %d hd %d sec %llu", - cxt->geom.cylinders, SSWAP16(sunlabel->acyl), cxt->geom.heads, cxt->geom.sectors); - - if (cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors >= 150 * 2048) { - ndiv = cxt->geom.cylinders - (50 * 2048 / (cxt->geom.heads * cxt->geom.sectors)); /* 50M swap */ - } else - ndiv = cxt->geom.cylinders * 2 / 3; - - set_sun_partition(cxt, 0, 0, ndiv * cxt->geom.heads * cxt->geom.sectors, - SUN_TAG_LINUX_NATIVE); - set_sun_partition(cxt, 1, ndiv * cxt->geom.heads * cxt->geom.sectors, - cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors, - SUN_TAG_LINUX_SWAP); - sunlabel->part_tags[1].flag |= SSWAP16(SUN_FLAG_UNMNT); - - set_sun_partition(cxt, 2, 0, cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors, SUN_TAG_BACKUP); - - { - unsigned short *ush = (unsigned short *)sunlabel; - unsigned short csum = 0; - while(ush < (unsigned short *)(&sunlabel->cksum)) - csum ^= *ush++; - sunlabel->cksum = csum; - } - - set_all_unchanged(); - set_changed(0); -} - -void toggle_sunflags(struct fdisk_context *cxt, int i, uint16_t mask) -{ - struct sun_tag_flag *p = &sunlabel->part_tags[i]; - - p->flag ^= SSWAP16(mask); - - set_changed(i); -} - -static void fetch_sun(struct fdisk_context *cxt, uint32_t *starts, - uint32_t *lens, uint32_t *start, uint32_t *stop) -{ - int i, continuous = 1; - - *start = 0; - *stop = cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors; - - for (i = 0; i < partitions; i++) { - struct sun_partition *part = &sunlabel->partitions[i]; - struct sun_tag_flag *tag = &sunlabel->part_tags[i]; - - if (part->num_sectors && - tag->tag != SSWAP16(SUN_TAG_UNASSIGNED) && - tag->tag != SSWAP16(SUN_TAG_BACKUP)) { - starts[i] = (SSWAP32(part->start_cylinder) * - cxt->geom.heads * cxt->geom.sectors); - lens[i] = SSWAP32(part->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 unsigned int *verify_sun_starts; - -static 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(struct fdisk_context *cxt) -{ - uint32_t starts[SUN_NUM_PARTITIONS], lens[SUN_NUM_PARTITIONS], start, stop; - uint32_t i,j,k,starto,endo; - int array[SUN_NUM_PARTITIONS]; - - verify_sun_starts = starts; - - fetch_sun(cxt, starts, lens, &start, &stop); - - for (k = 0; k < 7; k++) { - for (i = 0; i < SUN_NUM_PARTITIONS; i++) { - if (k && (lens[i] % (cxt->geom.heads * cxt->geom.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 < SUN_NUM_PARTITIONS; i++) { - if (lens[i]) - array[i] = i; - else - array[i] = -1; - } - qsort(array,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 = cxt->geom.cylinders * cxt->geom.heads * cxt->geom.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(struct fdisk_context *cxt, int n, int sys) -{ - uint32_t starts[SUN_NUM_PARTITIONS], lens[SUN_NUM_PARTITIONS]; - struct sun_partition *part = &sunlabel->partitions[n]; - struct sun_tag_flag *tag = &sunlabel->part_tags[n]; - uint32_t start, stop, stop2; - int whole_disk = 0; - - char mesg[256]; - int i; - unsigned int first, last; - - if (part->num_sectors && tag->tag != SSWAP16(SUN_TAG_UNASSIGNED)) { - printf(_("Partition %d is already defined. Delete " - "it before re-adding it.\n"), n + 1); - return; - } - - fetch_sun(cxt, 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; - } - } - snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR)); - for (;;) { - if (whole_disk) - first = read_int(cxt, 0, 0, 0, 0, mesg); - else - first = read_int(cxt, scround(start), scround(stop)+1, - scround(stop), 0, mesg); - if (display_in_cyl_units) - first *= units_per_sector; - else { - /* Starting sector has to be properly aligned */ - int cs = cxt->geom.heads * cxt->geom.sectors; - int x = first % cs; - - if (x) - first += cs - x; - } - if (n == 2 && first != 0) - printf (_("\ -It is highly recommended that the third partition covers the whole disk\n\ -and is of type `Whole disk'\n")); - /* ewt asks to add: "don't start a partition at cyl 0" - However, edmundo@rano.demon.co.uk writes: - "In addition to having a Sun partition table, to be able to - boot from the disc, the first partition, /dev/sdX1, must - start at cylinder 0. This means that /dev/sdX1 contains - the partition table and the boot block, as these are the - first two sectors of the disc. Therefore you must be - careful what you use /dev/sdX1 for. In particular, you must - not use a partition starting at cylinder 0 for Linux swap, - as that would overwrite the partition table and the boot - block. You may, however, use such a partition for a UFS - or EXT2 file system, as these file systems leave the first - 1024 bytes undisturbed. */ - /* On the other hand, one should not use partitions - starting at block 0 in an md, or the label will - be trashed. */ - 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 = cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors; /* ancient */ - stop2 = stop; - for (i = 0; i < partitions; i++) { - if (starts[i] > first && starts[i] < stop) - stop = starts[i]; - } - snprintf(mesg, sizeof(mesg), - _("Last %s or +size or +sizeM or +sizeK"), - str_units(SINGULAR)); - if (whole_disk) - last = read_int(cxt, scround(stop2), scround(stop2), scround(stop2), - 0, mesg); - else if (n == 2 && !first) - last = read_int(cxt, scround(first), scround(stop2), scround(stop2), - scround(first), mesg); - else - last = read_int(cxt, scround(first), scround(stop), scround(stop), - scround(first), mesg); - if (display_in_cyl_units) - last *= units_per_sector; - if (n == 2 && !first) { - if (last >= stop2) { - whole_disk = 1; - last = stop2; - } else if (last > stop) { - printf ( - _("You haven't covered the whole disk with the 3rd partition, but your value\n" - "%d %s covers some other partition. Your entry has been changed\n" - "to %d %s\n"), - scround(last), str_units(SINGULAR), - scround(stop), str_units(SINGULAR)); - last = stop; - } - } else if (!whole_disk && last > stop) - last = stop; - - if (whole_disk) - sys = SUN_TAG_BACKUP; - - set_sun_partition(cxt, n, first, last, sys); -} - -void sun_delete_partition(struct fdisk_context *cxt, int i) -{ - struct sun_partition *part = &sunlabel->partitions[i]; - struct sun_tag_flag *tag = &sunlabel->part_tags[i]; - unsigned int nsec; - - if (i == 2 && - tag->tag == SSWAP16(SUN_TAG_BACKUP) && - !part->start_cylinder && - (nsec = SSWAP32(part->num_sectors)) - == cxt->geom.heads * cxt->geom.sectors * cxt->geom.cylinders) - printf(_("If you want to maintain SunOS/Solaris compatibility, " - "consider leaving this\n" - "partition as Whole disk (5), starting at 0, with %u " - "sectors\n"), nsec); - tag->tag = SSWAP16(SUN_TAG_UNASSIGNED); - part->num_sectors = 0; -} - -int sun_change_sysid(struct fdisk_context *cxt, int i, uint16_t sys) -{ - struct sun_partition *part = &sunlabel->partitions[i]; - struct sun_tag_flag *tag = &sunlabel->part_tags[i]; - - if (sys == SUN_TAG_LINUX_SWAP && !part->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 0; - } - switch (sys) { - case SUN_TAG_SWAP: - case SUN_TAG_LINUX_SWAP: - /* swaps are not mountable by default */ - tag->flag |= SSWAP16(SUN_FLAG_UNMNT); - break; - default: - /* assume other types are mountable; - user can change it anyway */ - tag->flag &= ~SSWAP16(SUN_FLAG_UNMNT); - break; - } - tag->tag = SSWAP16(sys); - return 1; -} - -void sun_list_table(struct fdisk_context *cxt, int xtra) -{ - int i, w; - char *type; - - w = strlen(cxt->dev_path); - if (xtra) - printf( - _("\nDisk %s (Sun disk label): %u heads, %llu sectors, %d rpm\n" - "%llu cylinders, %d alternate cylinders, %d physical cylinders\n" - "%d extra sects/cyl, interleave %d:1\n" - "Label ID: %s\n" - "Volume ID: %s\n" - "Units = %s of %d * 512 bytes\n\n"), - cxt->dev_path, cxt->geom.heads, cxt->geom.sectors, SSWAP16(sunlabel->rpm), - cxt->geom.cylinders, SSWAP16(sunlabel->acyl), - SSWAP16(sunlabel->pcyl), - SSWAP16(sunlabel->apc), - SSWAP16(sunlabel->intrlv), - sunlabel->label_id, - sunlabel->volume_id, - str_units(PLURAL), units_per_sector); - else - printf( - _("\nDisk %s (Sun disk label): %u heads, %llu sectors, %llu cylinders\n" - "Units = %s of %d * 512 bytes\n\n"), - cxt->dev_path, cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders, - str_units(PLURAL), units_per_sector); - - printf(_("%*s Flag Start End Blocks Id System\n"), - w + 1, _("Device")); - for (i = 0 ; i < partitions; i++) { - struct sun_partition *part = &sunlabel->partitions[i]; - struct sun_tag_flag *tag = &sunlabel->part_tags[i]; - - if (part->num_sectors) { - uint32_t start = SSWAP32(part->start_cylinder) * cxt->geom.heads * cxt->geom.sectors; - uint32_t len = SSWAP32(part->num_sectors); - printf( - "%s %c%c %9lu %9lu %9lu%c %2x %s\n", -/* device */ partname(cxt->dev_path, i+1, w), -/* flags */ (tag->flag & SSWAP16(SUN_FLAG_UNMNT)) ? 'u' : ' ', - (tag->flag & SSWAP16(SUN_FLAG_RONLY)) ? 'r' : ' ', -/* start */ (unsigned long) scround(start), -/* end */ (unsigned long) scround(start+len), -/* odd flag on end */ (unsigned long) len / 2, len & 1 ? '+' : ' ', -/* type id */ SSWAP16(tag->tag), -/* type name */ (type = partition_type(SSWAP16(tag->tag))) - ? type : _("Unknown")); - } - } -} - -void sun_set_alt_cyl(struct fdisk_context *cxt) -{ - sunlabel->acyl = - SSWAP16(read_int(cxt, 0,SSWAP16(sunlabel->acyl), 65535, 0, - _("Number of alternate cylinders"))); -} - -void sun_set_ncyl(struct fdisk_context *cxt, int cyl) -{ - sunlabel->ncyl = SSWAP16(cyl); -} - -void sun_set_xcyl(struct fdisk_context *cxt) -{ - sunlabel->apc = - SSWAP16(read_int(cxt, 0, SSWAP16(sunlabel->apc), cxt->geom.sectors, 0, - _("Extra sectors per cylinder"))); -} - -void sun_set_ilfact(struct fdisk_context *cxt) -{ - sunlabel->intrlv = - SSWAP16(read_int(cxt, 1, SSWAP16(sunlabel->intrlv), 32, 0, - _("Interleave factor"))); -} - -void sun_set_rspeed(struct fdisk_context *cxt) -{ - sunlabel->rpm = - SSWAP16(read_int(cxt, 1, SSWAP16(sunlabel->rpm), 100000, 0, - _("Rotation speed (rpm)"))); -} - -void sun_set_pcylcount(struct fdisk_context *cxt) -{ - sunlabel->pcyl = - SSWAP16(read_int(cxt, 0, SSWAP16(sunlabel->pcyl), 65535, 0, - _("Number of physical cylinders"))); -} - -void sun_write_table(struct fdisk_context *cxt) -{ - unsigned short *ush = (unsigned short *)sunlabel; - unsigned short csum = 0; - - while(ush < (unsigned short *)(&sunlabel->cksum)) - csum ^= *ush++; - sunlabel->cksum = csum; - if (lseek(cxt->dev_fd, 0, SEEK_SET) < 0) - fatal(cxt, unable_to_seek); - if (write(cxt->dev_fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE) - fatal(cxt, unable_to_write); -} - -int sun_get_sysid(struct fdisk_context *cxt, int i) -{ - return SSWAP16(sunlabel->part_tags[i].tag); -} diff --git a/fdisk/fdisksunlabel.h b/fdisk/fdisksunlabel.h deleted file mode 100644 index abb29c3b5..000000000 --- a/fdisk/fdisksunlabel.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef FDISK_SUN_LABEL_H -#define FDISK_SUN_LABEL_H - -#include <stdint.h> - -struct sun_partition { - uint32_t start_cylinder; - uint32_t num_sectors; -}; - -struct sun_tag_flag { - uint16_t tag; -#define SUN_TAG_UNASSIGNED 0x00 /* Unassigned partition */ -#define SUN_TAG_BOOT 0x01 /* Boot partition */ -#define SUN_TAG_ROOT 0x02 /* Root filesystem */ -#define SUN_TAG_SWAP 0x03 /* Swap partition */ -#define SUN_TAG_USR 0x04 /* /usr filesystem */ -#define SUN_TAG_BACKUP 0x05 /* Full-disk slice */ -#define SUN_TAG_STAND 0x06 /* Stand partition */ -#define SUN_TAG_VAR 0x07 /* /var filesystem */ -#define SUN_TAG_HOME 0x08 /* /home filesystem */ -#define SUN_TAG_ALTSCTR 0x09 /* Alt sector partition */ -#define SUN_TAG_CACHE 0x0a /* Cachefs partition */ -#define SUN_TAG_RESERVED 0x0b /* SMI reserved data */ -#define SUN_TAG_LINUX_SWAP 0x82 /* Linux SWAP */ -#define SUN_TAG_LINUX_NATIVE 0x83 /* Linux filesystem */ -#define SUN_TAG_LINUX_LVM 0x8e /* Linux LVM */ -#define SUN_TAG_LINUX_RAID 0xfd /* LInux RAID */ - - uint16_t flag; -#define SUN_FLAG_UNMNT 0x01 /* Unmountable partition*/ -#define SUN_FLAG_RONLY 0x10 /* Read only */ -}; - -#define SUN_LABEL_SIZE 512 - -#define SUN_LABEL_ID_SIZE 128 -#define SUN_VOLUME_ID_SIZE 8 - -#define SUN_LABEL_VERSION 0x00000001 -#define SUN_LABEL_SANE 0x600ddeee -#define SUN_NUM_PARTITIONS 8 - -struct sun_disk_label { - char label_id[SUN_LABEL_ID_SIZE]; - uint32_t version; - char volume_id[SUN_VOLUME_ID_SIZE]; - uint16_t num_partitions; - struct sun_tag_flag part_tags[SUN_NUM_PARTITIONS]; - uint32_t bootinfo[3]; - uint32_t sanity; - uint32_t resv[10]; - uint32_t part_timestamps[SUN_NUM_PARTITIONS]; - uint32_t write_reinstruct; - uint32_t read_reinstruct; - uint8_t pad[148]; - uint16_t rpm; - uint16_t pcyl; - uint16_t apc; - uint16_t resv1; - uint16_t resv2; - uint16_t intrlv; - uint16_t ncyl; - uint16_t acyl; - uint16_t nhead; - uint16_t nsect; - uint16_t resv3; - uint16_t resv4; - struct sun_partition partitions[SUN_NUM_PARTITIONS]; - uint16_t magic; - uint16_t cksum; -}; - -#define SUN_LABEL_MAGIC 0xDABE -#define SUN_LABEL_MAGIC_SWAPPED 0xBEDA -#define sunlabel ((struct sun_disk_label *)cxt->mbr) - -/* fdisksunlabel.c */ -extern struct systypes sun_sys_types[]; -extern int check_sun_label(struct fdisk_context *cxt); -extern void create_sunlabel(struct fdisk_context *cxt); -extern void sun_delete_partition(struct fdisk_context *cxt, int i); -extern int sun_change_sysid(struct fdisk_context *cxt, int i, uint16_t sys); -extern void sun_list_table(struct fdisk_context *cxt, int xtra); -extern void verify_sun(struct fdisk_context *cxt); -extern void add_sun_partition(struct fdisk_context *cxt, int n, int sys); -extern void sun_write_table(struct fdisk_context *cxt); -extern void sun_set_alt_cyl(struct fdisk_context *cxt); -extern void sun_set_ncyl(struct fdisk_context *cxt, int cyl); -extern void sun_set_xcyl(struct fdisk_context *cxt); -extern void sun_set_ilfact(struct fdisk_context *cxt); -extern void sun_set_rspeed(struct fdisk_context *cxt); -extern void sun_set_pcylcount(struct fdisk_context *cxt); -extern void toggle_sunflags(struct fdisk_context *cxt, int i, uint16_t mask); -extern int sun_get_sysid(struct fdisk_context *cxt, int i); - -#endif /* FDISK_SUN_LABEL_H */ diff --git a/fdisk/gpt.c b/fdisk/gpt.c deleted file mode 100644 index bb6911a21..000000000 --- a/fdisk/gpt.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - * - * GPT (GUID Partition Table) signature detection. Based on libparted and - * util-linux/partx. - * - * Warning: this code doesn't do all GPT checks (CRC32, Protective MBR, ..). - * It's really GPT signature detection only. - * - * Copyright (C) 2007 Karel Zak <kzak@redhat.com> - * - */ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <inttypes.h> -#include <sys/stat.h> -#include <sys/utsname.h> -#include <sys/types.h> -#include <fcntl.h> -#include <unistd.h> -#include <errno.h> - -#include "gpt.h" -#include "blkdev.h" -#include "bitops.h" -#include "closestream.h" - -#define GPT_HEADER_SIGNATURE 0x5452415020494645LL -#define GPT_PRIMARY_PARTITION_TABLE_LBA 1 - -typedef struct { - uint32_t time_low; - uint16_t time_mid; - uint16_t time_hi_and_version; - uint8_t clock_seq_hi_and_reserved; - uint8_t clock_seq_low; - uint8_t node[6]; -} /* __attribute__ ((packed)) */ efi_guid_t; -/* commented out "__attribute__ ((packed))" to work around gcc bug (fixed - * in gcc3.1): __attribute__ ((packed)) breaks addressing on initialized - * data. It turns out we don't need it in this case, so it doesn't break - * anything :) - */ - -typedef struct _GuidPartitionTableHeader_t { - uint64_t Signature; - uint32_t Revision; - uint32_t HeaderSize; - uint32_t HeaderCRC32; - uint32_t Reserved1; - uint64_t MyLBA; - uint64_t AlternateLBA; - uint64_t FirstUsableLBA; - uint64_t LastUsableLBA; - efi_guid_t DiskGUID; - uint64_t PartitionEntryLBA; - uint32_t NumberOfPartitionEntries; - uint32_t SizeOfPartitionEntry; - uint32_t PartitionEntryArrayCRC32; - uint8_t Reserved2[512 - 92]; -} __attribute__ ((packed)) GuidPartitionTableHeader_t; - -static int -_get_sector_size (int fd) -{ - int sector_size; - - if (blkdev_get_sector_size(fd, §or_size) == -1) - return DEFAULT_SECTOR_SIZE; - return sector_size; -} - -static uint64_t -_get_num_sectors(int fd) -{ - unsigned long long bytes=0; - - if (blkdev_get_size(fd, &bytes) == -1) - return 0; - return bytes / _get_sector_size(fd); -} - -static uint64_t -last_lba(int fd) -{ - int rc; - uint64_t sectors = 0; - struct stat s; - - memset(&s, 0, sizeof (s)); - rc = fstat(fd, &s); - if (rc == -1) - { - fprintf(stderr, "last_lba() could not stat: %m\n"); - return 0; - } - if (S_ISBLK(s.st_mode)) - sectors = _get_num_sectors(fd); - else if (S_ISREG(s.st_mode)) - sectors = s.st_size >> _get_sector_size(fd); - else - { - fprintf(stderr, - "last_lba(): I don't know how to handle files with mode %o\n", - s.st_mode); - sectors = 1; - } - return sectors - 1; -} - -static ssize_t -read_lba(int fd, uint64_t lba, void *buffer, size_t bytes) -{ - int sector_size = _get_sector_size(fd); - off_t offset = lba * sector_size; - - lseek(fd, offset, SEEK_SET); - return read(fd, buffer, bytes); -} - -static GuidPartitionTableHeader_t * -alloc_read_gpt_header(int fd, uint64_t lba) -{ - GuidPartitionTableHeader_t *gpt = - (GuidPartitionTableHeader_t *) malloc(sizeof (GuidPartitionTableHeader_t)); - if (!gpt) - return NULL; - memset(gpt, 0, sizeof (*gpt)); - if (!read_lba(fd, lba, gpt, sizeof (GuidPartitionTableHeader_t))) - { - free(gpt); - return NULL; - } - return gpt; -} - -static int -gpt_check_signature(int fd, uint64_t lba) -{ - GuidPartitionTableHeader_t *gpt; - int res=0; - - if ((gpt = alloc_read_gpt_header(fd, lba))) - { - if (gpt->Signature == cpu_to_le64(GPT_HEADER_SIGNATURE)) - res = 1; - free(gpt); - } - return res; -} - -/* returns: - * 0 not found GPT - * 1 for valid primary GPT header - * 2 for valid alternative GPT header - */ -int -gpt_probe_signature_fd(int fd) -{ - int res = 0; - - /* check primary GPT header */ - if (gpt_check_signature(fd, GPT_PRIMARY_PARTITION_TABLE_LBA)) - res = 1; - else - { - /* check alternative GPT header */ - uint64_t lastlba = last_lba(fd); - if (gpt_check_signature(fd, lastlba)) - res = 2; - } - return res; -} - -int -gpt_probe_signature_devname(char *devname) -{ - int res, fd; - if ((fd = open(devname, O_RDONLY)) < 0) - return 0; - res = gpt_probe_signature_fd(fd); - close(fd); - return res; -} - -#ifdef GPT_TEST_MAIN -int -main(int argc, char **argv) -{ - atexit(close_stdout); - if (argc!=2) - { - fprintf(stderr, "usage: %s <dev>\n", argv[0]); - exit(EXIT_FAILURE); - } - if (gpt_probe_signature_devname(argv[1])) - printf("GPT (GUID Partition Table) detected on %s\n", argv[1]); - exit(EXIT_SUCCESS); -} -#endif diff --git a/fdisk/gpt.h b/fdisk/gpt.h deleted file mode 100644 index e57c24a33..000000000 --- a/fdisk/gpt.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef FDISK_GPT_H -#define FDISK_GPT_H - -extern int gpt_probe_signature_fd(int fd); -extern int gpt_probe_signature_devname(char *devname); - -#endif /* FDISK_GPT_H */ - diff --git a/fdisk/i386_sys_types.c b/fdisk/i386_sys_types.c deleted file mode 100644 index 916daf68b..000000000 --- a/fdisk/i386_sys_types.c +++ /dev/null @@ -1,110 +0,0 @@ -/* DOS partition types */ -#include "common.h" -#include "nls.h" - -struct systypes i386_sys_types[] = { - {0x00, N_("Empty")}, - {0x01, N_("FAT12")}, - {0x02, N_("XENIX root")}, - {0x03, N_("XENIX usr")}, - {0x04, N_("FAT16 <32M")}, - {0x05, N_("Extended")}, /* DOS 3.3+ extended partition */ - {0x06, N_("FAT16")}, /* DOS 16-bit >=32M */ - {0x07, N_("HPFS/NTFS/exFAT")}, /* OS/2 IFS, eg, HPFS or NTFS or QNX or exFAT */ - {0x08, N_("AIX")}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */ - {0x09, N_("AIX bootable")}, /* AIX data or Coherent */ - {0x0a, N_("OS/2 Boot Manager")},/* OS/2 Boot Manager */ - {0x0b, N_("W95 FAT32")}, - {0x0c, N_("W95 FAT32 (LBA)")},/* LBA really is `Extended Int 13h' */ - {0x0e, N_("W95 FAT16 (LBA)")}, - {0x0f, N_("W95 Ext'd (LBA)")}, - {0x10, N_("OPUS")}, - {0x11, N_("Hidden FAT12")}, - {0x12, N_("Compaq diagnostics")}, - {0x14, N_("Hidden FAT16 <32M")}, - {0x16, N_("Hidden FAT16")}, - {0x17, N_("Hidden HPFS/NTFS")}, - {0x18, N_("AST SmartSleep")}, - {0x1b, N_("Hidden W95 FAT32")}, - {0x1c, N_("Hidden W95 FAT32 (LBA)")}, - {0x1e, N_("Hidden W95 FAT16 (LBA)")}, - {0x24, N_("NEC DOS")}, - {0x27, N_("Hidden NTFS WinRE")}, - {0x39, N_("Plan 9")}, - {0x3c, N_("PartitionMagic recovery")}, - {0x40, N_("Venix 80286")}, - {0x41, N_("PPC PReP Boot")}, - {0x42, N_("SFS")}, - {0x4d, N_("QNX4.x")}, - {0x4e, N_("QNX4.x 2nd part")}, - {0x4f, N_("QNX4.x 3rd part")}, - {0x50, N_("OnTrack DM")}, - {0x51, N_("OnTrack DM6 Aux1")}, /* (or Novell) */ - {0x52, N_("CP/M")}, /* CP/M or Microport SysV/AT */ - {0x53, N_("OnTrack DM6 Aux3")}, - {0x54, N_("OnTrackDM6")}, - {0x55, N_("EZ-Drive")}, - {0x56, N_("Golden Bow")}, - {0x5c, N_("Priam Edisk")}, - {0x61, N_("SpeedStor")}, - {0x63, N_("GNU HURD or SysV")}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */ - {0x64, N_("Novell Netware 286")}, - {0x65, N_("Novell Netware 386")}, - {0x70, N_("DiskSecure Multi-Boot")}, - {0x75, N_("PC/IX")}, - {0x80, N_("Old Minix")}, /* Minix 1.4a and earlier */ - {0x81, N_("Minix / old Linux")},/* Minix 1.4b and later */ - {0x82, N_("Linux swap / Solaris")}, - {0x83, N_("Linux")}, - {0x84, N_("OS/2 hidden C: drive")}, - {0x85, N_("Linux extended")}, - {0x86, N_("NTFS volume set")}, - {0x87, N_("NTFS volume set")}, - {0x88, N_("Linux plaintext")}, - {0x8e, N_("Linux LVM")}, - {0x93, N_("Amoeba")}, - {0x94, N_("Amoeba BBT")}, /* (bad block table) */ - {0x9f, N_("BSD/OS")}, /* BSDI */ - {0xa0, N_("IBM Thinkpad hibernation")}, - {0xa5, N_("FreeBSD")}, /* various BSD flavours */ - {0xa6, N_("OpenBSD")}, - {0xa7, N_("NeXTSTEP")}, - {0xa8, N_("Darwin UFS")}, - {0xa9, N_("NetBSD")}, - {0xab, N_("Darwin boot")}, - {0xaf, N_("HFS / HFS+")}, - {0xb7, N_("BSDI fs")}, - {0xb8, N_("BSDI swap")}, - {0xbb, N_("Boot Wizard hidden")}, - {0xbe, N_("Solaris boot")}, - {0xbf, N_("Solaris")}, - {0xc1, N_("DRDOS/sec (FAT-12)")}, - {0xc4, N_("DRDOS/sec (FAT-16 < 32M)")}, - {0xc6, N_("DRDOS/sec (FAT-16)")}, - {0xc7, N_("Syrinx")}, - {0xda, N_("Non-FS data")}, - {0xdb, N_("CP/M / CTOS / ...")},/* CP/M or Concurrent CP/M or - Concurrent DOS or CTOS */ - {0xde, N_("Dell Utility")}, /* Dell PowerEdge Server utilities */ - {0xdf, N_("BootIt")}, /* BootIt EMBRM */ - {0xe1, N_("DOS access")}, /* DOS access or SpeedStor 12-bit FAT - extended partition */ - {0xe3, N_("DOS R/O")}, /* DOS R/O or SpeedStor */ - {0xe4, N_("SpeedStor")}, /* SpeedStor 16-bit FAT extended - partition < 1024 cyl. */ - {0xeb, N_("BeOS fs")}, - {0xee, N_("GPT")}, /* Intel EFI GUID Partition Table */ - {0xef, N_("EFI (FAT-12/16/32)")},/* Intel EFI System Partition */ - {0xf0, N_("Linux/PA-RISC boot")},/* Linux/PA-RISC boot loader */ - {0xf1, N_("SpeedStor")}, - {0xf4, N_("SpeedStor")}, /* SpeedStor large partition */ - {0xf2, N_("DOS secondary")}, /* DOS 3.3+ secondary */ - {0xfb, N_("VMware VMFS")}, - {0xfc, N_("VMware VMKCORE")}, /* VMware kernel dump partition */ - {0xfd, N_("Linux raid autodetect")},/* New (2.2.x) raid partition with - autodetect using persistent - superblock */ - {0xfe, N_("LANstep")}, /* SpeedStor >1024 cyl. or LANstep */ - {0xff, N_("BBT")}, /* Xenix Bad Block Table */ - { 0, 0 } -}; diff --git a/fdisk/partname.c b/fdisk/partname.c deleted file mode 100644 index d2782dca1..000000000 --- a/fdisk/partname.c +++ /dev/null @@ -1,49 +0,0 @@ -#include <ctype.h> -#include <stdio.h> -#include <string.h> - -#include "blkdev.h" -#include "pathnames.h" -#include "common.h" -#include "c.h" - -/* - * return partition name - uses static storage unless buf is supplied - */ -char * -partname(char *dev, int pno, int lth) { - static char bufp[PATH_MAX]; - char *p; - int w, wp; - - w = strlen(dev); - p = ""; - - if (isdigit(dev[w-1])) - p = "p"; - - /* devfs kludge - note: fdisk partition names are not supposed - to equal kernel names, so there is no reason to do this */ - if (strcmp (dev + w - 4, "disc") == 0) { - w -= 4; - p = "part"; - } - - /* udev names partitions by appending -partN - e.g. ata-SAMSUNG_SV8004H_0357J1FT712448-part1 */ - if ((strncmp(dev, _PATH_DEV_BYID, strlen(_PATH_DEV_BYID)) == 0) || - strncmp(dev, _PATH_DEV_BYPATH, strlen(_PATH_DEV_BYPATH)) == 0) { - p = "-part"; - } - - wp = strlen(p); - - if (lth) { - snprintf(bufp, sizeof(bufp), "%*.*s%s%-2u", - lth-wp-2, w, dev, p, pno); - } else { - snprintf(bufp, sizeof(bufp), "%.*s%s%-2u", w, dev, p, pno); - } - return bufp; -} - diff --git a/fdisk/sfdisk.8 b/fdisk/sfdisk.8 deleted file mode 100644 index 32907e3e9..000000000 --- a/fdisk/sfdisk.8 +++ /dev/null @@ -1,603 +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 "August 2011" "util-linux" "System Administration" -.SH NAME -sfdisk \- partition table manipulator for Linux -.SH SYNOPSIS -.B sfdisk -.RI [ options ] -.I device -.br -.B sfdisk \-s -.RI [ 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. - -.B sfdisk -doesn't understand the GUID Partition Table (GPT) format and it is not -designed for large partitions. In these cases use the more advanced GNU -.BR parted (8). - -Note that -.B sfdisk -does not align partitions to block device I/O limits. This functionality is -provided by -.BR fdisk (8). - -.SS "List sizes" -.BI "sfdisk \-s " partition -gives the size of -.I partition -in blocks. This may be useful in connection with programs like -.BR mkswap (8). -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 . - -.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: - -.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 " device -will list the partitions on the specified device. If the -.I device -argument is omitted, the partitions on all hard disks are listed. - -.RS -.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 -.RE - -The trailing \- and + signs indicate that rounding has taken place, -and that the actual value is slightly less or more. To see the -exact values, ask for a listing with sectors as unit (\fB\-u S\fR). - -.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 \fB\-V\fR option can be used -together with \fB\-l\fR. 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 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 - -.LP -(This is not the same as saving the old partition table: -a readable version of the old partition table can be saved -using the \fB\-d\fR option. However, if you create logical partitions, -the sectors describing them are located somewhere on disk, -possibly on sectors that were not part of the partition table -before. Thus, the information the \fB\-O\fR option saves -is not a binary version of the output of \fB\-d\fR.) - -There are many options. - -.SH OPTIONS -.TP -.BR \-v ", " \-\-version -Print version number of -.B sfdisk -and exit immediately. -.TP -.BR \-h ", " \-\-help -Print a usage message and exit immediately. -.TP -.BR \-T ", " \-\-list\-types -Print the recognized types (system Id's). -.TP -.BR \-s ", " \-\-show\-size -List the size of a partition. -.TP -.BR \-g ", " \-\-show\-geometry -List the kernel's idea of the geometry of the indicated disk(s). -.TP -.BR \-G ", " \-\-show\-pt\-geometry -List the geometry of the indicated disks guessed by looking at -the partition table. -.TP -.BR \-l ", " \-\-list -List the partitions of a device. -.TP -.BR \-d ", " \-\-dump -Dump the partitions of a device in a format that is usable as input -to /fBsfdisk/fR. 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 ", " \-\-verify -Test whether partitions seem correct. (See the third invocation type above.) -.TP -.BR \-i ", " \-\-increment -Number cylinders etc. starting from 1 instead of 0. -.TP -.BI \-N " number" -Change only the single partition indicated. For example: -.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 -.BR \-A ", " \-\-activate " \fInumber\fR" -Make the indicated partition(s) active, and all others inactive. -.TP -.BR \-c ", " \-\-id " \fInumber\fR [\fIId\fR]" -If no \fIId\fR argument given: print the partition Id of the indicated -partition. If an \fIId\fR argument is present: change the type (Id) of -the indicated partition to the given value. -This option has two longer forms, \fB\-\-print\-id\fR and \fB\-\-change\-id\fR. -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 \-u ", " \-\-unit " \fIletter\fR" -Interpret the input and show the output in the units specified by -.IR letter . -This \fIletter\fR can be one of S, C, B or M, meaning Sectors, Cylinders, -Blocks and Megabytes, respectively. The default is -cylinders, at least when the geometry is known. -.TP -.BR \-x ", " \-\-show\-extended -Also list non-primary extended partitions on output, -and expect descriptors for them on input. -.TP -.BR \-C ", " \-\-cylinders " \fIcylinders\fR" -Specify the number of cylinders, possibly overriding what the kernel thinks. -.TP -.BR \-H ", " \-\-heads " \fIheads\fR" -Specify the number of heads, possibly overriding what the kernel thinks. -.TP -.BR \-S ", " \-\-sectors " \fIsectors\fR" -Specify the number of sectors, possibly overriding what the kernel thinks. -.TP -.BR \-f ", " \-\-force -Do what I say, even if it is stupid. -.TP -.BR \-q ", " \-\-quiet -Suppress warning messages. -.TP -.BR \-L ", " \-\-Linux -Do not complain about things irrelevant for Linux. -.TP -.BR \-D ", " \-\-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 \-E ", " \-\-DOS\-extended -Take the starting sector numbers of "inner" extended partitions -to be relative to the starting cylinder boundary of the outer one -(like some versions of DOS do), rather than relative to the actual -starting sector (like Linux does). -(The fact that there is a difference here means that one should -always let extended partitions start at cylinder boundaries if -DOS and Linux should interpret the partition table in the same way. -Of course one can only know where cylinder boundaries are when -one knows what geometry DOS will use for this disk.) -.TP -.BR \-\-IBM ", " \-\-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 -.BR \-R ", " \-\-re-read -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, \fBsfdisk\fR 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 \fB\-f\fR -option would force \fBsfdisk\fR to continue even when this test fails.) -.TP -.B \-\-in\-order -Caution, see warning section. To be documented. -.TP -.B \-\-not\-in\-order -Caution, see warning section. To be documented. -.TP -.B \-\-inside\-outer -Caution, see warning section. Chaining order. -.TP -.B \-\-not\-inside\-outer -Caution, see warning section. Chaining order. -.TP -.B \-\-nested -Caution, see warning section. Every partition is contained in the -surrounding partitions and is disjoint from all others. -.TP -.B \-\-chained -Caution, see warning section. 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). -.TP -.B \-\-onesector -Caution, see warning section. All data partitions are mutually -disjoint; extended partitions each use one sector only (except -perhaps for the outermost one). -.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 \fB\-O\fR 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 or f -.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 and f - 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. -.LP -A '+' can be specified instead of a number for size, which means -as much as possible. This is useful with the \-N option. -.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. - -The command -.RS -.nf -.if t .ft CW -sfdisk /dev/hdb << EOF -,3,L -,60,L -,19,S -,,E -,130,L -,130,L -,130,L -,,L -EOF -.if t .ft R -.fi -.RE -will partition /dev/hdb into two Linux partitions of 3 and 60 -cylinders, a swap space of 19 cylinders, and an extended partition -covering the rest. Inside the extended partition there are four -Linux logical partitions, three of 130 cylinders and one -covering the rest. - -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 "CAUTION WARNINGS" - -The options marked with caution in the manual page are dangerous. -For example not all functionality is completely implemented, -which can be a reason for unexpected results. -.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.efdisk: `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 -There are too many options. -.LP -There is no support for non-DOS partition types. - -.\" .SH AUTHOR -.\" A. E. Brouwer (aeb@cwi.nl) -.\" -.SH "SEE ALSO" -.BR cfdisk (8), -.BR fdisk (8), -.BR mkfs (8), -.BR parted (8), -.BR partprobe (8), -.BR kpartx (8) -.SH AVAILABILITY -The sfdisk command is part of the util-linux package and is available from -ftp://ftp.kernel.org/pub/linux/utils/util-linux/. diff --git a/fdisk/sfdisk.c b/fdisk/sfdisk.c deleted file mode 100644 index c9853867a..000000000 --- a/fdisk/sfdisk.c +++ /dev/null @@ -1,3242 +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" - -#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> /* strchr(), strrchr() */ -#include <ctype.h> -#include <getopt.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/utsname.h> -#include <limits.h> - -#include "c.h" -#include "nls.h" -#include "xalloc.h" -#include "blkdev.h" -#include "linux_version.h" -#include "common.h" -#include "wholedisk.h" -#include "gpt.h" -#include "pathnames.h" -#include "canonicalize.h" -#include "rpmatch.h" -#include "closestream.h" -#include "strutils.h" - -/* - * 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 */ -/* IA-64 gcc spec file currently does -DLinux... */ -#undef Linux -int Linux = 0; /* 1: suppress warnings irrelevant for Linux */ -int DOS = 0; /* 1: shift extended partitions by #sectors, not 1 */ -int DOS_extended = 0; /* 1: use starting cylinder boundary of extd partn */ -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; - -static void -my_warn(char *s, ...) { - va_list p; - - va_start(p, s); - if (!quiet) { - fflush(stdout); - vfprintf(stderr, s, p); - fflush(stderr); - } - va_end(p); -} - -static void -error(char *s, ...) { - va_list p; - - va_start(p, s); - fflush(stdout); - fprintf(stderr, "\n" PROGNAME ": "); - vfprintf(stderr, s, p); - fflush(stderr); - va_end(p); -} - -/* - * A. About seeking - */ - -/* - * sseek: seek to specified sector - return 0 on failure - * - * Note: we use 512-byte sectors here, irrespective of the hardware ss. - */ - -static int -sseek(char *dev, int fd, unsigned long s) { - off_t in, out; - in = ((off_t) s << 9); - - if ((out = lseek(fd, in, SEEK_SET)) != in) { - perror("lseek"); - 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"), - (unsigned int)(in >> 32), (unsigned int)(in & 0xffffffff), - (unsigned int)(out >> 32), (unsigned int)(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 long sectornumber; - int to_be_written; - char data[512]; -} *sectorhead; - -static void -free_sectors(void) { - struct sector *s; - - while (sectorhead) { - s = sectorhead; - sectorhead = s->next; - free(s); - } -} - -static struct sector * -get_sector(char *dev, int fd, unsigned long 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; - - s = xmalloc(sizeof(struct sector)); - - if (read(fd, s->data, sizeof(s->data)) != sizeof(s->data)) { - if (errno) /* 0 in case we read past end-of-disk */ - 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; -} - -static int -msdos_signature(struct sector *s) { - unsigned char *data = (unsigned char *)s->data; - if (data[510] == 0x55 && data[511] == 0xaa) - return 1; - return 0; -} - -static 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; -} - -static void -ulong_to_chars(unsigned long u, char *uu) { - int i; - - for (i = 0; i < 4; i++) { - uu[i] = (u & 0xff); - u >>= 8; - } -} - -static 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; -} - -static int -save_sectors(char *dev, int fdin) { - struct sector *s; - char ss[516]; - int fdout = -1; - - 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); - goto err; - } - - for (s = sectorhead; s; s = s->next) - if (s->to_be_written) { - ulong_to_chars(s->sectornumber, ss); - if (!sseek(dev, fdin, s->sectornumber)) - goto err; - if (read(fdin, ss + 4, 512) != 512) { - perror("read"); - error(_("read error on %s - cannot read sector %lu\n"), - dev, s->sectornumber); - goto err; - } - if (write(fdout, ss, sizeof(ss)) != sizeof(ss)) { - perror("write"); - error(_("write error on %s\n"), save_sector_file); - goto err; - } - } - - close(fdout); - return 1; - - err: - if (fdout >= 0) - close(fdout); - return 0; -} - -static int reread_disk_partition(char *dev, int fd); - -static int -restore_sectors(char *dev) { - int fdin = -1, fdout = -1; - int ct; - struct stat statbuf; - char *ss0 = NULL, *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); - goto err; - } - if (statbuf.st_size % 516) { - error(_("partition restore file has wrong size - not restoring\n")); - goto err; - } - - ss0 = xmalloc(statbuf.st_size); - ss = ss0; - - 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); - goto err; - } - if (read(fdin, ss, statbuf.st_size) != statbuf.st_size) { - perror("read"); - error(_("error reading %s\n"), restore_sector_file); - goto err; - } - - fdout = open(dev, O_WRONLY); - if (fdout < 0) { - perror(dev); - error(_("cannot open device %s for writing\n"), dev); - goto err; - } - - ct = statbuf.st_size / 516; - while (ct--) { - sno = chars_to_ulong((unsigned char *)ss); - if (!sseek(dev, fdout, sno)) - goto err; - if (write(fdout, ss + 4, 512) != 512) { - perror(dev); - error(_("error writing sector %lu on %s\n"), sno, dev); - goto err; - } - ss += 516; - } - free(ss0); - ss0 = NULL; - - if (!reread_disk_partition(dev, fdout)) /* closes fdout */ - goto err; - close(fdin); - - return 1; - - err: - free(ss0); - if (fdin >= 0) - close(fdin); - if (fdout >= 0) - close(fdout); - - return 0; -} - -/* - * 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; - * }; - * - * For large disks g.cylinders is truncated, so we use BLKGETSIZE. - */ - -/* - * We consider several geometries for a disk: - * B - the BIOS geometry, gotten from the kernel via HDIO_GETGEO - * F - the fdisk geometry - * U - the user-specified geometry - * - * 0 means unspecified / unknown - */ -struct geometry { - unsigned long long total_size; /* in sectors */ - unsigned long cylindersize; /* in sectors */ - unsigned long heads, sectors, cylinders; - unsigned long start; -} B, F, U; - -static struct geometry -get_geometry(char *dev, int fd, int silent) { - struct hd_geometry g; - unsigned long cyls; - unsigned long long sectors; - struct geometry R; - -#ifdef HDIO_GETGEO - if (ioctl(fd, HDIO_GETGEO, &g)) -#endif - { - g.heads = g.sectors = g.cylinders = g.start = 0; - if (!silent) - warnx(_("Disk %s: cannot get geometry\n"), dev); - } - - R.start = g.start; - R.heads = g.heads; - R.sectors = g.sectors; - R.cylindersize = R.heads * R.sectors; - R.cylinders = 0; - R.total_size = 0; - - if (blkdev_get_sectors(fd, §ors) == -1) { - /* maybe an ordinary file */ - struct stat s; - - if (fstat(fd, &s) == 0 && S_ISREG(s.st_mode)) - R.total_size = (s.st_size >> 9); - else if (!silent) - warnx(_("Disk %s: cannot get size\n"), dev); - } else - R.total_size = sectors; - - if (R.cylindersize && R.total_size) { - sectors /= R.cylindersize; - cyls = sectors; - if (cyls != sectors) - cyls = ~0; - R.cylinders = cyls; - } - - return R; -} - -static void -get_cylindersize(char *dev, int fd, int silent) { - struct geometry R; - - R = get_geometry(dev, fd, silent); - - B.heads = (U.heads ? U.heads : R.heads ? R.heads : 255); - B.sectors = (U.sectors ? U.sectors : R.sectors ? R.sectors : 63); - B.cylinders = (U.cylinders ? U.cylinders : R.cylinders); - - B.cylindersize = B.heads * B.sectors; - B.total_size = R.total_size; - - if (B.cylinders == 0 && B.cylindersize != 0) - B.cylinders = B.total_size / B.cylindersize; - - if (R.start && !force) { - my_warn(_("Warning: start=%lu - 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"), - R.start); - exit(1); - } -#if 0 - if (R.heads && B.heads != R.heads) - my_warn(_("Warning: HDIO_GETGEO says that there are %lu heads\n"), - R.heads); - if (R.sectors && B.sectors != R.sectors) - my_warn(_("Warning: HDIO_GETGEO says that there are %lu sectors\n"), - R.sectors); - if (R.cylinders && B.cylinders != R.cylinders - && B.cylinders < 65536 && R.cylinders < 65536) - my_warn(_("Warning: BLKGETSIZE/HDIO_GETGEO says that there are %lu cylinders\n"), - R.cylinders); -#endif - - if (B.sectors > 63) - my_warn(_("Warning: unlikely number of sectors (%lu) - usually at most 63\n" - "This will give problems with all software that uses C/H/S addressing.\n"), - B.sectors); - if (!silent) - printf(_("\nDisk %s: %lu cylinders, %lu heads, %lu sectors/track\n"), - dev, B.cylinders, B.heads, B.sectors); -} - -typedef struct { - unsigned char h, s, c; -} __attribute__ ((packed)) chs; /* has some c bits in s */ -chs zero_chs = { 0, 0, 0 }; - -typedef struct { - unsigned long h, s, c; -} longchs; -longchs zero_longchs; - -static chs -longchs_to_chs(longchs aa, struct geometry G) { - 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 (G.heads && G.sectors) { - a.h = G.heads - 1; - a.s = G.sectors | 0xc0; - a.c = 0xff; - } else - a = zero_chs; - return a; -} - -static 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; -} - -static longchs -ulong_to_longchs(unsigned long sno, struct geometry G) { - longchs aa; - - if (G.heads && G.sectors && G.cylindersize) { - aa.s = 1 + sno % G.sectors; - aa.h = (sno / G.sectors) % G.heads; - aa.c = sno / G.cylindersize; - return aa; - } else { - return zero_longchs; - } -} - -static chs -ulong_to_chs(unsigned long sno, struct geometry G) { - return longchs_to_chs(ulong_to_longchs(sno, G), G); -} - -#if 0 -static unsigned long -longchs_to_ulong(longchs aa, struct geometry G) { - return (aa.c * G.cylindersize + aa.h * G.sectors + aa.s - 1); -} - -static unsigned long -chs_to_ulong(chs a, struct geometry G) { - return longchs_to_ulong(chs_to_longchs(a), G); -} -#endif - -static int -is_equal_chs(chs a, chs b) { - return (a.h == b.h && a.s == b.s && a.c == b.c); -} - -static 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 (B.heads && aa.h >= B.heads) { - my_warn(_("%s of partition %s has impossible value for head: " - "%lu (should be in 0-%lu)\n"), w, v, aa.h, B.heads - 1); - ret = 0; - } - if (B.sectors && (aa.s == 0 || aa.s > B.sectors)) { - my_warn(_("%s of partition %s has impossible value for sector: " - "%lu (should be in 1-%lu)\n"), w, v, aa.s, B.sectors); - ret = 0; - } - if (B.cylinders && aa.c >= B.cylinders) { - my_warn(_("%s of partition %s has impossible value for cylinders: " - "%lu (should be in 0-%lu)\n"), w, v, aa.c, B.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 -#define NETBSD_PARTITION 0xa9 - -/* List of partition types now in i386_sys_types.c */ - -static const char * -sysname(unsigned char type) { - struct systypes *s; - - for (s = i386_sys_types; s->name; s++) - if (s->type == type) - return _(s->name); - return _("Unknown"); -} - -static void -list_types(void) { - struct systypes *s; - - printf(_("Id Name\n\n")); - for (s = i386_sys_types; s->name; s++) - printf("%2x %s\n", s->type, _(s->name)); -} - -static int -is_extended(unsigned char type) { - return (type == EXTENDED_PARTITION - || type == LINUX_EXTENDED || type == WIN98_EXTENDED); -} - -static int -is_bsd(unsigned char type) { - return (type == BSD_PARTITION || type == NETBSD_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 */ -} __attribute__ ((packed)); - -/* Unfortunately, partitions are not aligned, and non-Intel machines - are unhappy with non-aligned integers. So, we need a copy by hand. */ -static int -copy_to_int(unsigned char *cp) { - unsigned int m; - - m = *cp++; - m += (*cp++ << 8); - m += (*cp++ << 16); - m += (*cp++ << 24); - return m; -} - -static 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); -} - -static 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((unsigned char *)cp); - p->nr_sects = copy_to_int((unsigned char *)cp + 4); -} - -static 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 long start; - unsigned long long size; - unsigned long 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; - -static struct part_desc * -outer_extended_partition(struct part_desc *p) { - while (p->ep) - p = p->ep; - return p; -} - -static 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[512]; - int partno; -} oldp, newp; - -/* determine where on the disk this information goes */ -static 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 */ -static int -reread_ioctl(int fd) { -#ifdef BLKRRPART - if (ioctl(fd, BLKRRPART)) -#else - errno = ENOSYS; -#endif - { - /* perror might change errno */ - int err = errno; - - perror("BLKRRPART"); - - /* 2.6.8 returns EIO for a zero table */ - if (err == EBUSY) - return -1; - } - return 0; -} - -/* reread after writing */ -static int -reread_disk_partition(char *dev, int fd) { - printf(_("Re-reading the partition table ...\n")); - fflush(stdout); - sync(); - - if (reread_ioctl(fd) && is_blkdev(fd)) { - warnx(_("The command to re-read the partition table failed.\n" - "Run partprobe(8), kpartx(8) or reboot your system now,\n" - "before using mkfs\n")); - return 0; - } - - if (fsync(fd) || close(fd)) { - perror(dev); - warnx(_("Error closing %s\n"), dev); - return 0; - } - printf("\n"); - - return 1; -} - -/* find Linux name of this partition, assuming that it will have a name */ -static 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; -} - -static 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; -} - -static 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)) - errx(EXIT_FAILURE, _("%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; - -static void -set_format(char c) { - switch (c) { - default: - warnx(_("unrecognized format - using sectors\n")); - /* fallthrough */ - 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; - } -} - -static unsigned long -unitsize(int format) { - default_format = (B.cylindersize ? F_CYLINDER : F_MEGABYTE); - if (!format && !(format = specified_format)) - format = default_format; - - switch (format) { - default: - case F_CYLINDER: - if (B.cylindersize) - return B.cylindersize; - case F_SECTOR: - return 1; - case F_BLOCK: - return 2; - case F_MEGABYTE: - return 2048; - } -} - -static unsigned long long -get_disksize(int format) { - if (B.total_size && leave_last) - /* don't use last cylinder (--leave-last option) */ - return (B.total_size - B.cylindersize) / unitsize(format); - - return B.total_size / unitsize(format); -} - -static void -out_partition_header(char *dev, int format, struct geometry G) { - if (dump) { - printf("# partition table of %s\n", dev); - printf("unit: sectors\n\n"); - return; - } - - default_format = (G.cylindersize ? F_CYLINDER : F_MEGABYTE); - if (!format && !(format = specified_format)) - format = default_format; - - switch (format) { - default: - warnx(_("unimplemented format - using %s\n"), - G.cylindersize ? _("cylinders") : _("sectors")); - case F_CYLINDER: - if (G.cylindersize) { - printf(_("Units: cylinders of %lu bytes, blocks of 1024 bytes" - ", counting from %d\n\n"), G.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: 1MiB = 1024*1024 bytes, blocks of 1024 bytes" - ", counting from %d\n\n"), increment); - printf(_(" Device Boot Start End MiB #blocks Id System\n")); - break; - } -} - -static void -out_rounddown(int width, unsigned long long n, unsigned long unit, int inc) { - printf("%*llu", width, inc + n / unit); - if (unit != 1) - putchar((n % unit) ? '+' : ' '); - putchar(' '); -} - -static void -out_roundup(int width, unsigned long long n, unsigned long unit, int inc) { - if (n == (unsigned long long)(-1)) - printf("%*s", width, "-"); - else - printf("%*llu", width, inc + n / unit); - if (unit != 1) - putchar(((n + 1) % unit) ? '-' : ' '); - putchar(' '); -} - -static void -out_roundup_size(int width, unsigned long long n, unsigned long unit) { - printf("%*llu", width, (n + unit - 1) / unit); - if (unit != 1) - putchar((n % unit) ? '-' : ' '); - putchar(' '); -} - -static struct geometry -get_fdisk_geometry_one(struct part_desc *p) { - struct geometry G; - - memset(&G, 0, sizeof(struct geometry)); - chs b = p->p.end_chs; - longchs bb = chs_to_longchs(b); - G.heads = bb.h + 1; - G.sectors = bb.s; - G.cylindersize = G.heads * G.sectors; - return G; -} - -static int -get_fdisk_geometry(struct disk_desc *z) { - struct part_desc *p; - int pno, agree; - struct geometry G0, G; - - memset(&G0, 0, sizeof(struct geometry)); - agree = 0; - for (pno = 0; pno < z->partno; pno++) { - p = &(z->partitions[pno]); - if (p->size != 0 && p->p.sys_type != 0) { - G = get_fdisk_geometry_one(p); - if (!G0.heads) { - G0 = G; - agree = 1; - } else if (G.heads != G0.heads || G.sectors != G0.sectors) { - agree = 0; - break; - } - } - } - F = (agree ? G0 : B); - return (F.sectors != B.sectors || F.heads != B.heads); -} - -static void -out_partition(char *dev, int format, struct part_desc *p, - struct disk_desc *z, struct geometry G) { - unsigned long 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("%s", partname(dev, lpno, 10)); /* 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=%9llu", start); - printf(", size=%9llu", 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 (G.cylindersize) { - out_rounddown(6, start, G.cylindersize, increment); - out_roundup(6, end, G.cylindersize, increment); - out_roundup_size(6, size, G.cylindersize); - out_rounddown(9, size, 2, 0); - break; - } - /* fall through */ - default: - case F_SECTOR: - out_rounddown(9, start, 1, increment); - out_roundup(9, end, 1, increment); - out_rounddown(10, 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(9, 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(9, 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, G) : 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)) - warnx(_("\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, G) : 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)) - warnx(_("\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 (G.cylinders && G.cylinders < 1024 && bb.c > G.cylinders) - warnx(_("partition ends on cylinder %ld, beyond the end of the disk\n"), - bb.c); - } -} - -static void -out_partitions(char *dev, struct disk_desc *z) { - int pno, format = 0; - - if (z->partno == 0) { - if (!opt_list) - warnx(_("No partitions found\n")); - } else { - if (get_fdisk_geometry(z) && !dump) { - warnx(_("Warning: The partition table looks like it was made\n" - " for C/H/S=*/%ld/%ld (instead of %ld/%ld/%ld).\n" - "For this listing I'll assume that geometry.\n"), - F.heads, F.sectors, B.cylinders, B.heads, B.sectors); - } - - out_partition_header(dev, format, F); - for (pno = 0; pno < z->partno; pno++) { - out_partition(dev, format, &(z->partitions[pno]), z, F); - 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)); -} - -static 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; -} - -static int -partitions_ok(int fd, 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) - errx(EXIT_FAILURE, _("no partition table present.")); - else - errx(EXIT_FAILURE, _("strange, only %d partitions defined."), 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) - my_warn(_("Warning: partition %s has size 0 but is not marked Empty\n"), - PNO(p)); - else if (p->p.bootable != 0) - my_warn(_("Warning: partition %s has size 0 and is bootable\n"), - PNO(p)); - else if (p->p.start_sect != 0) - my_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) { - my_warn(_("Warning: partition %s is not contained in " - "partition %s\n"), PNO(p), 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))) { - my_warn(_("Warning: partitions %s and %s overlap\n"), - PNO(p), 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) { - my_warn(_("Warning: partition %s contains part of " - "the partition table (sector %llu),\n" - "and will destroy it when filled\n"), - PNO(p), q->start); - return 0; - } - - /* Do they start past zero and end before end-of-disk? */ - { - unsigned long long ds = get_disksize(F_SECTOR); - for (p = partitions; p < partitions + partno; p++) - if (p->size) { - if (p->start == 0) { - my_warn(_("Warning: partition %s starts at sector 0\n"), - PNO(p)); - return 0; - } - if (p->size && p->start + p->size > ds) { - my_warn(_("Warning: partition %s extends past end of disk\n"), - PNO(p)); - return 0; - } - } - } - - int sector_size; - if (blkdev_get_sector_size(fd, §or_size) == -1) - sector_size = DEFAULT_SECTOR_SIZE; - - /* Is the size of partitions less than 2^32 sectors limit? */ - for (p = partitions; p < partitions + partno; p++) - if (p->size > UINT_MAX) { - unsigned long long bytes = p->size * sector_size; - int giga = bytes / 1000000000; - int hectogiga = (giga + 50) / 100; - my_warn(_("Warning: partition %s has size %d.%d TB (%llu bytes),\n" - "which is larger than the %llu bytes limit imposed\n" - "by the DOS partition table for %d-byte sectors\n"), - PNO(p), hectogiga / 10, hectogiga % 10, - bytes, - (unsigned long long) UINT_MAX * sector_size, - sector_size); - return 0; - } - - /* Do the partitions start below the 2^32 sectors limit? */ - for (p = partitions; p < partitions + partno; p++) - if (p->start > UINT_MAX) { - unsigned long long bytes = p->start * sector_size; - int giga = bytes / 1000000000; - int hectogiga = (giga + 50) / 100; - my_warn(_("Warning: partition %s starts at sector %llu (%d.%d TB for %d-byte sectors),\n" - "which exceeds the DOS partition table limit of %llu sectors\n"), - PNO(p), - p->start, - hectogiga / 10, - hectogiga % 10, - sector_size, - (unsigned long long) UINT_MAX); - 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) { - my_warn(_("Among the primary partitions, at most one can be extended\n" - " (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 (B.cylindersize && !Linux) { - for (p = partitions; p < partitions + partno; p++) - if (p->size) { - if (p->start % B.cylindersize != 0 - && (!p->ep - || p->start / B.cylindersize != - p->ep->start / B.cylindersize) - && (p->p.start_sect >= B.cylindersize)) { - my_warn(_("Warning: partition %s does not start " - "at a cylinder boundary\n"), PNO(p)); - if (specified_format == F_CYLINDER) - return 0; - } - if ((p->start + p->size) % B.cylindersize) { - my_warn(_("Warning: partition %s does not end " - "at a cylinder boundary\n"), PNO(p)); - if (specified_format == F_CYLINDER) - 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) { - my_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) { - my_warn(_("Warning: usually one can boot from primary partitions " - "only\nLILO disregards the `bootable' flag.\n")); - break; - } - } - if (pno == -1 || pno >= 4) - my_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, B) : zero_chs; - b = p->p.begin_chs; - aa = chs_to_longchs(a); - bb = chs_to_longchs(b); - if (!Linux && !chs_ok(b, PNO(p), _("start"))) - return 0; - if (a.s && !is_equal_chs(a, b)) - my_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, B) : zero_chs; - b = p->p.end_chs; - aa = chs_to_longchs(a); - bb = chs_to_longchs(b); - if (!Linux && !chs_ok(b, PNO(p), _("end"))) - return 0; - if (a.s && !is_equal_chs(a, b)) - my_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 (B.cylinders && B.cylinders < 1024 && bb.c > B.cylinders) - my_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 long start, here, next; - int i, moretodo = 1; - struct partition p; - struct part_desc *partitions = &(z->partitions[0]); - size_t pno = z->partno; - - here = start = ep->start; - - if (B.cylindersize && start % B.cylindersize) { - /* This is BAD */ - if (DOS_extended) { - here = start -= (start % B.cylindersize); - warnx(_("Warning: shifted start of the extd partition " - "from %lld to %lld\n" - "(For listing purposes only. " - "Do not change its contents.)\n"), ep->start, start); - } else { - warnx(_("Warning: extended partition does not start at a " - "cylinder boundary.\n" - "DOS and Linux will interpret the contents differently.\n")); - } - } - - while (moretodo) { - moretodo = 0; - - if (!(s = get_sector(dev, fd, here))) - break; - - if (!msdos_signature(s)) { - error(_("ERROR: sector %lu does not have an msdos signature\n"), - s->sectornumber); - break; - } - cp = s->data + 0x1be; - - if (pno + 4 >= ARRAY_SIZE(z->partitions)) { - warnx(_("too many partitions - ignoring those past nr (%ld)\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)) { - partitions[pno].start = start + p.start_sect; - if (next) - warnx(_("tree of partitions?\n")); - else - next = partitions[pno].start; /* follow `upper' branch */ - 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 16 -#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 long start = ep->start; - struct sector *s; - struct part_desc *partitions = &(z->partitions[0]); - size_t pno = z->partno; - - if (!(s = get_sector(dev, fd, start + 1))) - return; - l = (struct bsd_disklabel *)(s->data); - if (l->d_magic != BSD_DISKMAGIC || l->d_magic2 != BSD_DISKMAGIC) - return; - - bp = bp0 = &l->d_partitions[0]; - while (bp - bp0 < BSD_MAXPARTITIONS && bp - bp0 < l->d_npartitions) { - if (pno + 1 >= ARRAY_SIZE(z->partitions)) { - warnx(_("too many partitions - ignoring those " - "past nr (%ld)\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; - int bsd_later = 1; -#ifdef __linux__ - bsd_later = (get_linux_version() >= KERNEL_VERSION(2, 3, 40)); -#endif - - 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) { - warnx(_("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))) { - warnx(_("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) { - warnx(_("strange..., an extended partition of size 0?\n")); - continue; - } - extended_partition(dev, fd, &partitions[i], z); - } - if (!bsd_later && is_bsd(partitions[i].p.sys_type)) { - if (!partitions[i].size) { - warnx(_("strange..., a BSD partition of size 0?\n")); - continue; - } - bsd_partition(dev, fd, &partitions[i], z); - } - } - - if (bsd_later) { - for (i = 0; i < 4; i++) { - if (is_bsd(partitions[i].p.sys_type)) { - if (!partitions[i].size) { - warnx(_("strange..., a BSD partition of size 0?\n")); - continue; - } - bsd_partition(dev, fd, &partitions[i], z); - } - } - } - - return 1; -} - -static int -osf_partition(char *dev __attribute__ ((__unused__)), - int fd __attribute__ ((__unused__)), - unsigned long start __attribute__ ((__unused__)), - struct disk_desc *z __attribute__ ((__unused__))) { - return 0; -} - -static int -sun_partition(char *dev __attribute__ ((__unused__)), - int fd __attribute__ ((__unused__)), - unsigned long start __attribute__ ((__unused__)), - struct disk_desc *z __attribute__ ((__unused__))) { - return 0; -} - -static int -amiga_partition(char *dev __attribute__ ((__unused__)), - int fd __attribute__ ((__unused__)), - unsigned long start __attribute__ ((__unused__)), - struct disk_desc *z __attribute__ ((__unused__))) { - return 0; -} - -static 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)) { - if (!opt_list) - warnx(_(" %s: unrecognized partition table type\n"), dev); - return; - } -} - -static 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) { - warnx(_("-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; - if (p->ptype == DOS_TYPE) { - copy_from_part(&(p->p), s->data + p->offset); - s->data[510] = 0x55; - s->data[511] = (unsigned char)0xaa; - } - } - if (save_sector_file) { - if (!save_sectors(dev, fd)) { - errx(EXIT_FAILURE, _("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; - } - if (fsync(fd)) { - perror(dev); - 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) - -static int -read_stdin(char **fields, char *line, int fieldssize, int linesize) { - 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 - 2, stdin); - if (lp == NULL) { - eof = 1; - return RD_EOF; - } - if (!(lp = strchr(lp, '\n'))) - errx(EXIT_FAILURE, _("long or incomplete input line - quitting")); - *lp = 0; - - /* remove comments, if any */ - if ((lp = strchr(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 = strchr(line + 2, ':')) != 0) { - struct dumpfld *d; - - nxtfld: - ip++; - while (isspace(*ip)) - ip++; - if (*ip == 0) - return fno; - for (d = dumpflds; (size_t) (d - dumpflds) < ARRAY_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 - errx(EXIT_FAILURE, _("input error: `=' expected after %s field"), - d->fldname); - if (fno <= d->fldno) - fno = d->fldno + 1; - if (*ip == 0) - return fno; - if (*ip != ',' && *ip != ';') - errx(EXIT_FAILURE, _("input error: unexpected character %c after %s field"), - *ip, d->fldname); - *ip = 0; - goto nxtfld; - } - } - errx(EXIT_FAILURE, _("unrecognized input: %s"), 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 */ -/* a sign gives an offset from the default */ -static int -get_ul(char *u, unsigned long *up, unsigned long def, int base) { - char *nu; - int sign = 0; - unsigned long val; - - if (*u == '+') { - sign = 1; - u++; - } else if (*u == '-') { - sign = -1; - u++; - } - if (*u) { - errno = 0; - val = strtoul(u, &nu, base); - if (errno == ERANGE) { - warnx(_("number too big\n")); - return -1; - } - if (*nu) { - warnx(_("trailing junk after number\n")); - return -1; - } - if (sign == 1) - val = def + val; - else if (sign == -1) - val = def - val; - *up = val; - } else - *up = def; - return 0; -} - - -/* read a number, use default if absent */ -/* a sign gives an offset from the default */ -static int -get_ull(char *u, unsigned long long *up, unsigned long long def, int base) { - char *nu; - int sign = 0; - unsigned long long val; - - if (*u == '+') { - sign = 1; - u++; - } else if (*u == '-') { - sign = -1; - u++; - } - if (*u) { - errno = 0; - val = strtoull(u, &nu, base); - if (errno == ERANGE) { - warnx(_("number too big\n")); - return -1; - } - if (*nu) { - warnx(_("trailing junk after number\n")); - return -1; - } - if (sign == 1) - val = def + val; - else if (sign == -1) - val = def - val; - *up = val; - } 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 */ -static unsigned long long -first_free(int pno, int is_extended, struct part_desc *ep, int format, - unsigned long long mid, struct disk_desc *z) { - unsigned long 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 */ -static unsigned long long -max_length(int pno, int is_extended, struct part_desc *ep, int format, - unsigned long long start, struct disk_desc *z) { - unsigned long 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 */ -/* return 0 on failure */ -/* ep is 0 or points to surrounding extended partition */ -static int -compute_start_sect(struct part_desc *p, struct part_desc *ep) { - unsigned long long base; - int inc = (DOS && B.sectors) ? B.sectors : 1; - long long 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) { - unsigned long long old_size = p->size; - p->start -= delta; - p->size += delta; - if (is_extended(p->p.sys_type) && boxes == ONESECTOR) - p->size = inc; - else if ((long long) old_size <= -delta) { - my_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, B); - p->p.end_chs = ulong_to_chs(p->start + p->size - 1, B); - } - p->p.nr_sects = p->size; - return 1; -} - -/* build the extended partition surrounding a given logical partition */ -static int -build_surrounding_extended(struct part_desc *p, struct part_desc *ep, - struct disk_desc *z) { - int inc = (DOS && B.sectors) ? B.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) { - my_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; -} - -static int -read_line(int pno, struct part_desc *ep, char *dev, int interactive, - struct disk_desc *z) { - char line[1000]; - char *fields[11]; - int fno, pct = pno % 4; - struct part_desc p, *orig; - unsigned long 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)) - my_warn("\n"); - my_warn("%s:", partname(dev, lpno, 10)); - } - - /* read input line - skip blank lines when reading from a file */ - do { - fno = read_stdin(fields, line, ARRAY_SIZE(fields), ARRAY_SIZE(line)); - } while (fno == RD_CMD || (fno == 0 && !interactive)); - if (fno == RD_EOF) { - return -1; - } else if (fno > 10 && *(fields[10]) != 0) { - warnx(_("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 (B.cylindersize && specified_format == F_MEGABYTE && !Linux) - 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 */ - my_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_ull(fields[2], &ul, LINUX_NATIVE, 16)) - return 0; - if (ul > 255) { - my_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_ull(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 (!strcmp(fields[1], "+")) - p.size = ml1; - else { - if (get_ull(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) { - my_warn(_("Warning: given size (%lu) exceeds max allowable size (%lu)\n"), - (p.size + unitsize(0) - 1) / unitsize(0), ml1 / unitsize(0)); - if (!force) - return 0; - } - if (p.size == 0 && pno >= 4 && (fno < 2 || !*(fields[1]))) { - my_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) { - my_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 { - my_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) { - my_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, B); - } - { - longchs aa = chs_to_longchs(p.p.end_chs), bb; - - if (fno < 8) { - bb = aa; - } else if (fno < 10) { - my_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, B); - } - - if (pno > 3 && p.size && show_extended && p.p.sys_type != EMPTY_PARTITION - && (is_extended(p.p.sys_type) != (pct == 1))) { - my_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, B); - - 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 */ -static 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) - errx(EXIT_FAILURE, _("bad input")); - if (i < 0) { - p->ep = ep; - return 0; - } - - ret: - p->ep = ep; - if (pno >= z->partno) - z->partno += 4; - return 1; -} - -static void -read_partition_chain(char *dev, int interactive, struct part_desc *ep, - struct disk_desc *z) { - int i; - size_t base; - - eob = 0; - while (1) { - base = z->partno; - if (base + 4 > ARRAY_SIZE(z->partitions)) { - warnx(_("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; - } - } -} - -static void -read_input(char *dev, int interactive, struct disk_desc *z) { - size_t i; - struct part_desc *partitions = &(z->partitions[0]), *ep; - - for (i = 0; i < ARRAY_SIZE(z->partitions); i++) - partitions[i] = zero_part_desc; - z->partno = 0; - - if (interactive) - my_warn(_("Input in the following format; absent fields get a default value.\n" - "<start> <size> <type [E,S,L,X,hex]> <bootable [-,*]> <c,h,s> <c,h,s>\n" - "Usually you only need to specify <start> and <size> (and perhaps <type>).\n")); - 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 usage(FILE * out) -{ - fputs(_("\nUsage:\n"), out); - fprintf(out, - _(" %s [options] <device> [...]\n"), program_invocation_short_name); - - fputs(_("\nOptions:\n"), out); - fputs(_(" -s, --show-size list size of a partition\n" - " -c, --id change or print partition Id\n" - " --change-id change Id\n" - " --print-id print Id\n"), out); - fputs(_(" -l, --list list partitions of each device\n" - " -d, --dump idem, but in a format suitable for later input\n" - " -i, --increment number cylinders etc. from 1 instead of from 0\n" - " -u, --unit <letter> units to be used; <letter> can be one of\n" - " S (sectors), C (cylinders), B (blocks), or M (MB)\n"), out); - fputs(_(" -1, --one-only reserved option that does nothing currently\n" - " -T, --list-types list the known partition types\n" - " -D, --DOS for DOS-compatibility: waste a little space\n" - " -E, --DOS-extended DOS extended partition compatibility\n" - " -R, --re-read make the kernel reread the partition table\n"), out); - fputs(_(" -N <number> change only the partition with this <number>\n" - " -n do not actually write to disk\n" - " -O <file> save the sectors that will be overwritten to <file>\n" - " -I <file> restore sectors from <file>\n"), out); - fputs(_(" -V, --verify check that the listed partitions are reasonable\n" - " -v, --version display version information and exit\n" - " -h, --help display this help text and exit\n"), out); - - fputs(_("\nDangerous options:\n"), out); - fputs(_(" -f, --force disable all consistency checking\n" - " --no-reread do not check whether the partition is in use\n" - " -q, --quiet suppress warning messages\n" - " -L, --Linux do not complain about things irrelevant for Linux\n"), out); - fputs(_(" -g, --show-geometry print the kernel's idea of the geometry\n" - " -G, --show-pt-geometry print geometry guessed from the partition table\n"), out); - fputs(_(" -A, --activate[=<device>] activate bootable flag\n" - " -U, --unhide[=<dev>] set partition unhidden\n" - " -x, --show-extended also list extended partitions in the output,\n" - " or expect descriptors for them in the input\n"), out); - fputs(_(" --leave-last do not allocate the last cylinder\n" - " --IBM same as --leave-last\n"), out); - fputs(_(" --in-order partitions are in order\n" - " --not-in-order partitions are not in order\n" - " --inside-outer all logicals inside outermost extended\n" - " --not-inside-outer not all logicals inside outermost extended\n"), out); - fputs(_(" --nested every partition is disjoint from all others\n" - " --chained like nested, but extended partitions may lie outside\n" - " --onesector partitions are mutually disjoint\n"), out); - - fputs(_("\nOverride the detected geometry using:\n" - " -C, --cylinders <number> set the number of cylinders to use\n" - " -H, --heads <number> set the number of heads to use\n" - " -S, --sectors <number> set the number of sectors to use\n\n"), out); - - exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); -} - -static void -activate_usage(char *progn) { - puts(_("Usage:")); - printf(_("%s device list active partitions on device\n"), progn); - printf(_("%s device n1 n2 ... activate partitions n1 ..., inactivate the rest\n"), - progn); - printf(_("%s -An device activate partition n, inactivate the other ones\n"), - PROGNAME); - exit(1); -} - -static void -unhide_usage(char *progn __attribute__ ((__unused__))) { - exit(1); -} - -static const char short_opts[] = "cdfghilnqsu:vx1A::C:DGH:I:LN:O:RS:TU::V"; - -#define PRINT_ID 0400 -#define CHANGE_ID 01000 - -enum { - OPT_NO_REREAD = CHAR_MAX + 1, - OPT_LEAVE_LAST, - OPT_IN_ORDER, - OPT_NOT_IN_ORDER, - OPT_INSIDE_OUTER, - OPT_NOT_INSIDE_OUTER, - OPT_NESTED, - OPT_CHAINED, - OPT_ONESECTOR -}; - -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' }, - { "help", no_argument, NULL, 'h' }, - { "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' }, - { "one-only", no_argument, NULL, '1' }, - { "cylinders", required_argument, NULL, 'C' }, - { "heads", required_argument, NULL, 'H' }, - { "sectors", required_argument, NULL, 'S' }, - { "show-pt-geometry", no_argument, NULL, 'G' }, - { "activate", optional_argument, NULL, 'A' }, - { "DOS", no_argument, NULL, 'D' }, - { "DOS-extended", no_argument, NULL, 'E' }, - { "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, OPT_NO_REREAD }, - { "IBM", no_argument, NULL, OPT_LEAVE_LAST }, - { "leave-last", no_argument, NULL, OPT_LEAVE_LAST }, -/* dangerous flags - not all completely implemented */ - { "in-order", no_argument, NULL, OPT_IN_ORDER }, - { "not-in-order", no_argument, NULL, OPT_NOT_IN_ORDER }, - { "inside-outer", no_argument, NULL, OPT_INSIDE_OUTER }, - { "not-inside-outer", no_argument, NULL, OPT_NOT_INSIDE_OUTER }, - { "nested", no_argument, NULL, OPT_NESTED }, - { "chained", no_argument, NULL, OPT_CHAINED }, - { "onesector", no_argument, NULL, OPT_ONESECTOR }, - { NULL, 0, NULL, 0 } -}; - -static int is_ide_cdrom_or_tape(char *device) -{ - int fd, ret; - - if ((fd = open(device, O_RDONLY)) < 0) - return 0; - ret = blkdev_is_cdrom(fd); - - close(fd); - return ret; -} - -static char * -nextproc(FILE * procf) { - static char devname[256]; - char line[1024], ptname[128]; - int ma, mi; - unsigned long long sz; - - if (procf == NULL) - return NULL; - while (fgets(line, sizeof(line), procf) != NULL) { - if (sscanf(line, " %d %d %llu %128[^\n ]", &ma, &mi, &sz, ptname) != 4) - continue; - snprintf(devname, sizeof(devname), "/dev/%s", ptname); - if (!is_whole_disk(devname)) - continue; - return canonicalize_path(devname); - } - - return NULL; -} - -static void -gpt_warning(char *dev, int warn_only) { - if (force) - warn_only = 1; - - if (dev && gpt_probe_signature_devname(dev)) { - fflush(stdout); - fprintf(stderr, - _("\nWARNING: GPT (GUID Partition Table) detected on '%s'! " - "The util sfdisk doesn't support GPT. Use GNU Parted.\n\n"), - dev); - if (!warn_only) { - fprintf(stderr, - _("Use the --force flag to overrule this check.\n")); - exit(1); - } - } -} - -static void do_list(char *dev, int silent); -static void do_size(char *dev, int silent); -static void do_geom(char *dev, int silent); -static void do_pt_geom(char *dev, int silent); -static void do_fdisk(char *dev); -static void do_reread(char *dev); -static void do_change_id(char *dev, char *part, char *id); -static void do_unhide(char **av, int ac, char *arg); -static void do_activate(char **av, int ac, char *arg); - -unsigned long long 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_out_pt_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; - - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - atexit(close_stdout); - - if (argc < 1) - errx(EXIT_FAILURE, _("no command?")); - if ((progn = strrchr(argv[0], '/')) == NULL) - progn = argv[0]; - else - progn++; - if (!strcmp(progn, "activate")) - activate = 1; /* equivalent to `sfdisk -A' */ -#if 0 /* not important enough to deserve a name */ - else if (!strcmp(progn, "unhide")) - unhide = 1; /* equivalent to `sfdisk -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 'G': - opt_out_pt_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': - printf(_("%s from %s\n"), program_invocation_short_name, - PACKAGE_STRING); - return EXIT_SUCCESS; - case 'h': - usage(stdout); - return EXIT_SUCCESS; - case 'x': - show_extended = 1; - break; - case 'A': - activatearg = optarg; - activate = 1; - break; - case 'C': - U.cylinders = strtoul_or_err(optarg, _("invalid cylinders argument")); - break; - case 'D': - DOS = 1; - break; - case 'E': - DOS_extended = 1; - break; - case 'H': - U.heads = strtoul_or_err(optarg, _("invalid heads argument")); - break; - case 'L': - Linux = 1; - break; - case 'N': - one_only = strtol_or_err(optarg, _("invalid number of partitions argument")); - break; - case 'I': - restore_sector_file = optarg; - break; - case 'O': - save_sector_file = optarg; - break; - case 'R': - opt_reread = 1; - break; - case 'S': - U.sectors = strtoul_or_err(optarg, _("invalid sectors argument")); - break; - case 'T': - list_types(); - exit(0); - case 'U': - unhidearg = optarg; - unhide = 1; - break; - case 'V': - verify = 1; - break; - default: - usage(stderr); - break; - - /* dangerous flags */ - case OPT_IN_ORDER: - partitions_in_order = 1; - break; - case OPT_NOT_IN_ORDER: - partitions_in_order = 0; - break; - case OPT_INSIDE_OUTER: - all_logicals_inside_outermost_extended = 1; - break; - case OPT_NOT_INSIDE_OUTER: - all_logicals_inside_outermost_extended = 0; - break; - case OPT_NESTED: - boxes = NESTED; - break; - case OPT_CHAINED: - boxes = CHAINED; - break; - case OPT_ONESECTOR: - boxes = ONESECTOR; - break; - - /* more flags */ - case OPT_NO_REREAD: - no_reread = 1; - break; - case OPT_LEAVE_LAST: - leave_last = 1; - break; - } - } - - if (optind == argc && - (opt_list || opt_out_geom || opt_out_pt_geom || opt_size || verify)) { - FILE *procf; - - /* try all known devices */ - total_size = 0; - - procf = fopen(_PATH_PROC_PARTITIONS, "r"); - if (!procf) - fprintf(stderr, _("cannot open %s\n"), _PATH_PROC_PARTITIONS); - else { - while ((dev = nextproc(procf)) != NULL) { - if (!is_ide_cdrom_or_tape(dev)) { - gpt_warning(dev, 1); - if (opt_out_geom) - do_geom(dev, 1); - if (opt_out_pt_geom) - do_pt_geom(dev, 1); - if (opt_size) - do_size(dev, 1); - if (opt_list || verify) - do_list(dev, 1); - } - free(dev); - } - fclose(procf); - } - - if (opt_size) - printf(_("total: %llu blocks\n"), total_size); - - exit(exit_status); - } - - if (optind == argc) { - if (activate) - activate_usage(fdisk ? "sfdisk -A" : progn); - else if (unhide) - unhide_usage(fdisk ? "sfdisk -U" : progn); - else - usage(stderr); - } - - if (opt_list || opt_out_geom || opt_out_pt_geom || opt_size || verify) { - while (optind < argc) { - gpt_warning(argv[optind], 1); - if (opt_out_geom) - do_geom(argv[optind], 0); - if (opt_out_pt_geom) - do_pt_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 (optind != argc - 1) - gpt_warning(argv[optind], 0); - - 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) - errx(EXIT_FAILURE, _("usage: sfdisk --print-id device partition-number")); - else if ((do_id & CHANGE_ID) != 0 && optind != argc - 3) - errx(EXIT_FAILURE, _("usage: sfdisk --change-id device partition-number Id")); - else if (optind != argc - 3 && optind != argc - 2) - errx(EXIT_FAILURE, _("usage: sfdisk --id device partition-number [Id]")); - do_change_id(argv[optind], argv[optind + 1], - (optind == argc - 2) ? 0 : argv[optind + 2]); - exit(exit_status); - } - - if (optind != argc - 1) - errx(EXIT_FAILURE, _("can specify only one device (except with -l or -s)")); - 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 - */ - -static 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); - if (rw) - errx(EXIT_FAILURE, _("cannot open %s read-write"), dev); - else - errx(EXIT_FAILURE, _("cannot open %s for reading"), dev); - } - return fd; -} - -static 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(fd, z)) - my_warn(_("%s: OK\n"), dev); - else - exit_status = 1; - } - - close(fd); -} - -static void -do_geom(char *dev, int silent) { - int fd; - struct geometry R; - - fd = my_open(dev, 0, silent); - if (fd < 0) - return; - - R = get_geometry(dev, fd, silent); - if (R.cylinders) - printf(_("%s: %ld cylinders, %ld heads, %ld sectors/track\n"), - dev, R.cylinders, R.heads, R.sectors); - - close(fd); -} - -static void -do_pt_geom(char *dev, int silent) { - int fd; - struct disk_desc *z; - struct geometry R; - - fd = my_open(dev, 0, silent); - if (fd < 0) - return; - - z = &oldp; - - free_sectors(); - get_cylindersize(dev, fd, 1); - get_partitions(dev, fd, z); - - R = B; - - if (z->partno != 0 && get_fdisk_geometry(z)) { - R.heads = F.heads; - R.sectors = F.sectors; - R.cylindersize = R.heads * R.sectors; - R.cylinders = (R.cylindersize == 0) ? 0 : R.total_size / R.cylindersize; - } - - if (R.cylinders) - printf(_("%s: %ld cylinders, %ld heads, %ld sectors/track\n"), - dev, R.cylinders, R.heads, R.sectors); - - close(fd); -} - -/* for compatibility with earlier fdisk: provide option -s */ -static void -do_size(char *dev, int silent) { - int fd; - unsigned long long size; - - fd = my_open(dev, 0, silent); - if (fd < 0) - return; - - if (blkdev_get_sectors(fd, &size) == -1) { - if (!silent) { - perror(dev); - errx(EXIT_FAILURE, _("Cannot get size of %s"), dev); - } - goto done; - } - - size /= 2; /* convert sectors to blocks */ - - /* a CDROM drive without mounted CD yields MAXINT */ - if (silent && size == ((1 << 30) - 1)) - goto done; - - if (silent) - printf("%s: %9llu\n", dev, size); - else - printf("%llu\n", size); - - total_size += size; - -done: - close(fd); -} - -/* - * 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: sfdisk -A /dev/hda 2 5 7 - * - * If only a single partition must be active, one may also use the form - * sfdisk -A2 /dev/hda - * - * With "activate /dev/hda" or "sfdisk -A /dev/hda" the active partitions - * are listed but not changed. To get zero active partitions, use - * "activate /dev/hda none" or "sfdisk -A /dev/hda none". - * Use something like `echo ",,,*" | sfdisk -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. - */ -static void -set_active(struct disk_desc *z, char *pnam) { - int pno; - - pno = asc_to_index(pnam, z); - if (z->partitions[pno].ptype == DOS_TYPE) - z->partitions[pno].p.bootable = 0x80; -} - -static 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\n", partname(dev, lpno, 0)); - else - printf("%s#%d\n", dev, pno); - if (z->partitions[pno].p.bootable != 0x80) - my_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++) - if (z->partitions[pno].ptype == DOS_TYPE) - 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)) - my_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) - my_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); - - close(fd); -} - -static 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 - errx(EXIT_FAILURE, _("partition %s has id %x and is not hidden"), pnam, id); - z->partitions[pno].p.sys_type = id; -} - -/* - * maybe remove and make part of --change-id - */ -static 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)) - my_warn(_("Done\n\n")); - else - exit_status = 1; - - close(fd); -} - -static 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); - goto done; - } - i = strtoul(id, NULL, 16); - if (i > 255) - errx(EXIT_FAILURE, _("Bad Id %lx"), i); - z->partitions[pno].p.sys_type = i; - - if (write_partitions(dev, fd, z)) - my_warn(_("Done\n\n")); - else - exit_status = 1; - -done: - close(fd); -} - -static void -do_reread(char *dev) { - int fd; - - fd = my_open(dev, 0, 0); - if (reread_ioctl(fd)) { - warnx(_("This disk is currently in use.\n")); - exit(1); - } - - close(fd); -} - -/* - * I. Writing the new situation - */ - -static void -do_fdisk(char *dev) { - int fd; - char answer[32]; - struct stat statbuf; - int interactive = isatty(0); - struct disk_desc *z; - - if (stat(dev, &statbuf) < 0) { - perror(dev); - errx(EXIT_FAILURE, _("Fatal error: cannot find %s"), dev); - } - if (!S_ISBLK(statbuf.st_mode)) { - warnx(_("Warning: %s is not a block device\n"), dev); - no_reread = 1; - } - fd = my_open(dev, !no_write, 0); - - if (!no_write && !no_reread) { - my_warn(_("Checking that no-one is using this disk right now ...\n")); - if (reread_ioctl(fd)) { - warnx(_("\nThis disk is currently in use - repartitioning is probably a bad idea.\n" - "Umount all file systems, and swapoff all swap partitions on this disk.\n" - "Use the --no-reread flag to suppress this check.\n")); - if (!force) { - warnx(_("Use the --force flag to overrule all checks.\n")); - exit(1); - } - } else - my_warn(_("OK\n")); - } - - 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) - errx(EXIT_FAILURE, _("Partition %d does not exist, cannot change it"), one_only); - - z = &newp; - - while (1) { - - read_input(dev, interactive, z); - - printf(_("New situation:\n")); - out_partitions(dev, z); - - if (!partitions_ok(fd, z) && !force) { - if (!interactive) - errx(EXIT_FAILURE, _("I don't like these partitions - nothing changed.\n" - "(If you really want this, use the --force option.)")); - else - warnx(_("I don't like this - probably you should answer No\n")); - } - if (interactive) { - ask: - if (no_write) - /* TRANSLATORS: sfdisk uses rpmatch which means the answers y and n - * should be translated, but that is not the case with q answer. */ - printf(_("Are you satisfied with this? [ynq] ")); - else - printf(_("Do you want to write this to disk? [ynq] ")); - ignore_result( fgets(answer, sizeof(answer), stdin) ); - if (answer[0] == 'q' || answer[0] == 'Q') { - errx(EXIT_FAILURE, _("Quitting - nothing changed")); - } else if (rpmatch(answer) == 1) { - continue; - } else if (rpmatch(answer) == 0) { - 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; - - if (!reread_disk_partition(dev, fd)) { /* close fd on success */ - close(fd); - exit_status = 1; - } - my_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 */ - exit(exit_status); -} diff --git a/fdisk/utils.c b/fdisk/utils.c deleted file mode 100644 index 04ad0a56e..000000000 --- a/fdisk/utils.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) 2012 Davidlohr Bueso <dave@gnu.org> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include <errno.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#ifdef HAVE_LIBBLKID -#include <blkid.h> -#endif - -#include "nls.h" -#include "blkdev.h" -#include "common.h" -#include "fdisk.h" - -int fdisk_debug_mask; - -static int __init_mbr_buffer(struct fdisk_context *cxt) -{ - DBG(TOPOLOGY, dbgprint("initialize MBR buffer")); - - cxt->mbr = calloc(1, MAX_SECTOR_SIZE); - if (!cxt->mbr) - goto fail; - - /* read MBR */ - if (512 != read(cxt->dev_fd, cxt->mbr, 512)) - goto fail; - - return 0; -fail: - return -1; -} - -static unsigned long __get_sector_size(int fd) -{ - int sect_sz; - - if (!blkdev_get_sector_size(fd, §_sz)) - return (unsigned long) sect_sz; - return DEFAULT_SECTOR_SIZE; -} - -/** - * fdisk_geom_set_cyls - * @cxt: fdisk context - * - * Sets the cylinders based on sectors and heads - */ -void fdisk_geom_set_cyls(struct fdisk_context *cxt) -{ - cxt->geom.cylinders = cxt->total_sectors / - (cxt->geom.heads * cxt->geom.sectors); -} - -static int __discover_geometry(struct fdisk_context *cxt) -{ - sector_t nsects; - unsigned int h = 0, s = 0; - - /* get number of 512-byte sectors, and convert it the real sectors */ - if (!blkdev_get_sectors(cxt->dev_fd, &nsects)) - cxt->total_sectors = (nsects / (cxt->sector_size >> 9)); - - get_partition_table_geometry(cxt, &h, &s); - if (h && s) - goto hs_ok; - - /* what the kernel/bios thinks the geometry is */ - blkdev_get_geometry(cxt->dev_fd, &h, &s); - if (h && s) - goto hs_ok; - - /* unable to discover geometry, use default values */ - s = 63; - h = 255; - -hs_ok: /* obtained heads and sectors */ - cxt->geom.heads = h; - cxt->geom.sectors = s; - fdisk_geom_set_cyls(cxt); - update_sector_offset(cxt); - - DBG(GEOMETRY, dbgprint("geometry discovered for %s: C/H/S: %lld/%d/%lld", - cxt->dev_path, cxt->geom.cylinders, - cxt->geom.heads, cxt->geom.sectors)); - - return 0; -} - -static int __discover_topology(struct fdisk_context *cxt) -{ -#ifdef HAVE_LIBBLKID - blkid_probe pr; - - DBG(TOPOLOGY, dbgprint("initialize libblkid prober")); - - pr = blkid_new_probe(); - if (pr && blkid_probe_set_device(pr, cxt->dev_fd, 0, 0) == 0) { - blkid_topology tp = blkid_probe_get_topology(pr); - - if (tp) { - cxt->min_io_size = blkid_topology_get_minimum_io_size(tp); - cxt->optimal_io_size = blkid_topology_get_optimal_io_size(tp); - cxt->phy_sector_size = blkid_topology_get_physical_sector_size(tp); - cxt->alignment_offset = blkid_topology_get_alignment_offset(tp); - - /* I/O size used by fdisk */ - cxt->io_size = cxt->optimal_io_size; - if (!cxt->io_size) - /* optimal IO is optional, default to minimum IO */ - cxt->io_size = cxt->min_io_size; - } - } - blkid_free_probe(pr); -#endif - - /* no blkid or error, use default values */ - if (!cxt->min_io_size) - cxt->min_io_size = DEFAULT_SECTOR_SIZE; - if (!cxt->io_size) - cxt->io_size = DEFAULT_SECTOR_SIZE; - - cxt->sector_size = __get_sector_size(cxt->dev_fd); - if (!cxt->phy_sector_size) /* could not discover physical size */ - cxt->phy_sector_size = cxt->sector_size; - - DBG(TOPOLOGY, dbgprint("topology discovered for %s:\n" - "\tlogical/physical sector sizes: %ld/%ld\n" - "\tfdisk/minimal/optimal io sizes: %ld/%ld/%ld\n", - cxt->dev_path, cxt->sector_size, cxt->phy_sector_size, - cxt->io_size, cxt->optimal_io_size, cxt->min_io_size)); - return 0; -} - -/** - * fdisk_mbr_zeroize: - * @cxt: fdisk context - * - * Zero's MBR buffer - */ -void fdisk_mbr_zeroize(struct fdisk_context *cxt) -{ - if (cxt->mbr) { - DBG(CONTEXT, dbgprint("zeroize in-memory MBR")); - memset(cxt->mbr, 0, MAX_SECTOR_SIZE); - } -} - -/** - * fdisk_dev_sectsz_is_default: - * @cxt: fdisk context - * - * Returns 1 if the device's sector size is the default value, otherwise 0. - */ -int fdisk_dev_sectsz_is_default(struct fdisk_context *cxt) -{ - return cxt->sector_size == DEFAULT_SECTOR_SIZE; -} - -/** - * fdisk_dev_has_topology: - * @cxt: fdisk context - * - * Returns 1 if the device provides topology information, otherwise 0. - */ -int fdisk_dev_has_topology(struct fdisk_context *cxt) -{ - /* - * Assume that the device provides topology info if - * optimal_io_size is set or alignment_offset is set or - * minimum_io_size is not power of 2. - */ - if (cxt->optimal_io_size || cxt->alignment_offset || - !is_power_of_2(cxt->min_io_size)) - return 1; - return 0; -} - -/** - * fdisk_init_debug: - * @mask: debug mask (0xffff to enable full debuging) - * - * If the @mask is not specified then this function reads - * FDISK_DEBUG environment variable to get the mask. - * - * Already initialized debugging stuff cannot be changed. It does not - * have effect to call this function twice. - */ -void fdisk_init_debug(int mask) -{ - if (fdisk_debug_mask & FDISK_DEBUG_INIT) - return; - if (!mask) { - char *str = getenv("FDISK_DEBUG"); - if (str) - fdisk_debug_mask = strtoul(str, 0, 0); - } else - fdisk_debug_mask = mask; - - if (fdisk_debug_mask) - fprintf(stderr, "fdisk: debug mask set to 0x%04x.\n", - fdisk_debug_mask); - fdisk_debug_mask |= FDISK_DEBUG_INIT; -} - -/** - * fdisk_new_context: - * @filename: path to the device to be handled - * @readonly: how to open the device - * - * If the @readonly flag is set to false, fdisk will attempt to open - * the device with read-write mode and will fallback to read-only if - * unsuccessful. - * - * Returns: newly allocated fdisk context - */ -struct fdisk_context *fdisk_new_context_from_filename(const char *fname, int readonly) -{ - int fd, errsv = 0; - struct fdisk_context *cxt = NULL; - - DBG(CONTEXT, dbgprint("initializing context for %s", fname)); - - if (readonly == 1 || (fd = open(fname, O_RDWR)) < 0) { - if ((fd = open(fname, O_RDONLY)) < 0) - return NULL; - readonly = 1; - } - - cxt = calloc(1, sizeof(*cxt)); - if (!cxt) - goto fail; - - cxt->dev_fd = fd; - cxt->dev_path = strdup(fname); - if (!cxt->dev_path) - goto fail; - - if (__init_mbr_buffer(cxt) < 0) - goto fail; - - __discover_topology(cxt); - __discover_geometry(cxt); - - DBG(CONTEXT, dbgprint("context initialized for %s [%s]", - fname, readonly ? "READ-ONLY" : "READ-WRITE")); - return cxt; -fail: - errsv = errno; - fdisk_free_context(cxt); - errno = errsv; - - DBG(CONTEXT, dbgprint("failed to initialize context for %s: %m", fname)); - return NULL; -} - -/** - * fdisk_free_context: - * @cxt: fdisk context - * - * Deallocates context struct. - */ -void fdisk_free_context(struct fdisk_context *cxt) -{ - if (!cxt) - return; - - DBG(CONTEXT, dbgprint("freeing context for %s", cxt->dev_path)); - close(cxt->dev_fd); - free(cxt->dev_path); - free(cxt->mbr); - free(cxt); -} |