2002-11-26 22:00:21 +00:00
/* fdisk.c -- Partition table manipulator for Linux.
*
* Copyright ( C ) 1992 A . V . Le Blanc ( LeBlanc @ mcc . ac . uk )
2006-02-25 07:42:02 +00:00
* Copyright ( C ) 2001 , 2002 Vladimir Oleynik < dzo @ simtreas . ru > ( initial bb port )
2002-11-26 22:00:21 +00:00
*
2006-02-24 16:29:00 +00:00
* Licensed under the GPL v2 or later , see the file LICENSE in this tarball .
2002-11-26 22:00:21 +00:00
*/
2006-02-25 07:20:15 +00:00
/* Current changes have not compatibility with this version */
2003-08-08 20:04:56 +00:00
# define UTIL_LINUX_VERSION "2.12"
2002-11-26 22:00:21 +00:00
2006-02-25 07:20:15 +00:00
2006-05-29 05:00:44 +00:00
# define _(x) x
2002-11-26 22:00:21 +00:00
# define PROC_PARTITIONS " / proc / partitions"
2004-05-19 09:00:00 +00:00
# include <features.h>
2002-11-26 22:00:21 +00:00
# include <sys/types.h>
# include <sys/stat.h> /* stat */
# include <ctype.h>
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
# include <errno.h>
# include <unistd.h>
# include <fcntl.h>
# include <setjmp.h>
# include <assert.h> /* assert */
# include <getopt.h>
# include <endian.h>
# include <sys/ioctl.h>
# include <sys/param.h>
2003-07-30 08:40:37 +00:00
# include <sys/sysmacros.h> /* major */
2002-11-26 22:00:21 +00:00
2002-12-11 03:49:33 +00:00
# include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
/* Copied from linux/major.h */
2003-01-04 11:56:06 +00:00
# define FLOPPY_MAJOR 2
2002-11-26 22:00:21 +00:00
# include <sys/utsname.h>
# include "busybox.h"
# define DKTYPENAMES
/*
fdisk . 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 SUNOS_SWAP 3
# define WHOLE_DISK 5
# define IS_EXTENDED(i) \
( ( i ) = = EXTENDED | | ( i ) = = WIN98_EXTENDED | | ( i ) = = LINUX_EXTENDED )
# define SIZE(a) (sizeof(a) / sizeof((a)[0]))
# define cround(n) (display_in_cyl_units ? ((n) / units_per_sector)+1 : (n))
# define scround(x) (((x)+units_per_sector-1) / units_per_sector)
2004-02-06 05:26:58 +00:00
# ifdef CONFIG_FEATURE_SUN_LABEL
# define SCSI_IOCTL_GET_IDLUN 0x5382
# endif
2003-08-06 09:07:37 +00:00
2002-11-26 22:00:21 +00:00
/* including <linux/hdreg.h> also fails */
struct hd_geometry {
2006-02-24 16:29:00 +00:00
unsigned char heads ;
unsigned char sectors ;
unsigned short cylinders ;
unsigned long start ;
2002-11-26 22:00:21 +00:00
} ;
# define HDIO_GETGEO 0x0301 /* get device geometry */
struct systypes {
2005-12-02 10:06:04 +00:00
const char * name ;
2002-11-26 22:00:21 +00:00
} ;
2006-02-24 16:29:00 +00:00
static uint sector_size = DEFAULT_SECTOR_SIZE ;
static uint user_set_sector_size ;
static uint sector_offset = 1 ;
2002-11-26 22:00:21 +00:00
/*
* Raw disk label . For DOS - type partition tables the MBR ,
* with descriptions of the primary partitions .
*/
2005-11-24 12:10:13 +00:00
# if (MAX_SECTOR_SIZE) > (BUFSIZ+1)
2002-11-26 22:00:21 +00:00
static char MBRbuffer [ MAX_SECTOR_SIZE ] ;
2005-11-24 12:10:13 +00:00
# else
# define MBRbuffer bb_common_bufsiz1
# endif
2005-12-02 10:06:04 +00:00
2002-11-26 22:00:21 +00:00
# ifdef CONFIG_FEATURE_OSF_LABEL
2006-02-24 16:29:00 +00:00
static int possibly_osf_label ;
2002-11-26 22:00:21 +00:00
# endif
static uint heads , sectors , cylinders ;
static void update_units ( void ) ;
/*
* return partition name - uses static storage unless buf is supplied
*/
static const char *
2006-02-24 16:29:00 +00:00
partname ( const char * dev , int pno , int lth )
{
2002-11-26 22:00:21 +00:00
static char buffer [ 80 ] ;
const char * p ;
int w , wp ;
int bufsiz ;
char * bufp ;
bufp = buffer ;
bufsiz = sizeof ( buffer ) ;
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 */
2006-02-24 16:29:00 +00:00
if ( strcmp ( dev + w - 4 , " disc " ) = = 0 ) {
2002-11-26 22:00:21 +00:00
w - = 4 ;
p = " part " ;
}
wp = strlen ( p ) ;
if ( lth ) {
snprintf ( bufp , bufsiz , " %*.*s%s%-2u " ,
lth - wp - 2 , w , dev , p , pno ) ;
} else {
snprintf ( bufp , bufsiz , " %.*s%s%-2u " , w , dev , p , pno ) ;
}
return bufp ;
}
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 */
2006-01-22 22:55:11 +00:00
} ATTRIBUTE_PACKED ;
2002-11-26 22:00:21 +00:00
enum failure {
ioctl_error , unable_to_open , unable_to_read , unable_to_seek ,
unable_to_write
} ;
2006-02-25 03:46:10 +00:00
enum label_type {
label_dos , label_sun , label_sgi , label_aix , label_osf
} ;
2006-02-24 16:29:00 +00:00
enum action { fdisk , require , try_only , create_empty_dos , create_empty_sun } ;
2002-11-26 22:00:21 +00:00
2006-02-25 03:46:10 +00:00
static enum label_type current_label_type ;
2002-11-26 22:00:21 +00:00
static const char * disk_device ;
static int fd ; /* the disk */
static int partitions = 4 ; /* maximum partition + 1 */
static uint display_in_cyl_units = 1 ;
static uint units_per_sector = 1 ;
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
static char * line_ptr ;
2002-11-26 22:00:21 +00:00
static void change_units ( void ) ;
2003-01-04 11:56:06 +00:00
static void reread_partition_table ( int leave ) ;
static void delete_partition ( int i ) ;
2006-02-24 16:29:00 +00:00
static int get_partition ( int warn , int max ) ;
2002-11-26 22:00:21 +00:00
static void list_types ( const struct systypes * sys ) ;
static uint read_int ( uint low , uint dflt , uint high , uint base , char * mesg ) ;
2003-01-04 11:56:06 +00:00
# endif
static const char * partition_type ( unsigned char type ) ;
2006-01-22 22:55:11 +00:00
static void fdisk_fatal ( enum failure why ) ATTRIBUTE_NORETURN ;
2003-01-04 11:56:06 +00:00
static void get_geometry ( void ) ;
static int get_boot ( enum action what ) ;
2002-11-26 22:00:21 +00:00
# define PLURAL 0
# define SINGULAR 1
# define hex_val(c) ({ \
char _c = ( c ) ; \
isdigit ( _c ) ? _c - ' 0 ' : \
tolower ( _c ) + 10 - ' a ' ; \
} )
# define LINE_LENGTH 800
# define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
( n ) * sizeof ( struct partition ) ) )
# define sector(s) ((s) & 0x3f)
# define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
# define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
( ( h ) + heads * cylinder ( s , c ) ) )
# define set_hsc(h,s,c,sector) { \
s = sector % sectors + 1 ; \
sector / = sectors ; \
h = sector % heads ; \
sector / = heads ; \
c = sector & 0xff ; \
s | = ( sector > > 2 ) & 0xc0 ; \
}
2004-06-28 23:50:31 +00:00
static int32_t get_start_sect ( const struct partition * p ) ;
static int32_t get_nr_sects ( const struct partition * p ) ;
2002-11-26 22:00:21 +00:00
/*
* 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 .
*/
static struct pte {
struct partition * part_table ; /* points into sectorbuffer */
struct partition * ext_pointer ; /* points into sectorbuffer */
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
char changed ; /* boolean */
2003-01-04 11:56:06 +00:00
# endif
2004-06-28 23:50:31 +00:00
off_t offset ; /* disk sector number */
2002-11-26 22:00:21 +00:00
char * sectorbuffer ; /* disk sector contents */
} ptes [ MAXIMUM_PARTS ] ;
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
set_all_unchanged ( void )
{
2002-11-26 22:00:21 +00:00
int i ;
for ( i = 0 ; i < MAXIMUM_PARTS ; i + + )
ptes [ i ] . changed = 0 ;
}
static void
2006-02-24 16:29:00 +00:00
set_changed ( int i )
{
2002-11-26 22:00:21 +00:00
ptes [ i ] . changed = 1 ;
}
2003-01-04 11:56:06 +00:00
# endif /* CONFIG_FEATURE_FDISK_WRITABLE */
2002-11-26 22:00:21 +00:00
# if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
static struct partition *
2006-02-24 16:29:00 +00:00
get_part_table ( int i )
{
2002-11-26 22:00:21 +00:00
return ptes [ i ] . part_table ;
}
# endif
static const char *
2006-02-24 16:29:00 +00:00
str_units ( int n )
{ /* n==1: use singular */
2002-11-26 22:00:21 +00:00
if ( n = = 1 )
return display_in_cyl_units ? _ ( " cylinder " ) : _ ( " sector " ) ;
else
return display_in_cyl_units ? _ ( " cylinders " ) : _ ( " sectors " ) ;
}
2003-01-04 11:56:06 +00:00
static int
2005-12-02 10:06:04 +00:00
valid_part_table_flag ( const char * mbuffer ) {
const unsigned char * b = ( const unsigned char * ) mbuffer ;
2003-01-04 11:56:06 +00:00
return ( b [ 510 ] = = 0x55 & & b [ 511 ] = = 0xaa ) ;
}
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
static char line_buffer [ LINE_LENGTH ] ;
2002-11-26 22:00:21 +00:00
/* read line; return 0 or first char */
static int
read_line ( void )
{
static int got_eof = 0 ;
fflush ( stdout ) ; /* requested by niles@scyld.com */
line_ptr = line_buffer ;
if ( ! fgets ( line_buffer , LINE_LENGTH , stdin ) ) {
if ( feof ( stdin ) )
got_eof + + ; /* user typed ^D ? */
if ( got_eof > = 3 ) {
fprintf ( stderr , _ ( " \n got EOF thrice - exiting.. \n " ) ) ;
exit ( 1 ) ;
}
return 0 ;
}
while ( * line_ptr & & ! isgraph ( * line_ptr ) )
line_ptr + + ;
return * line_ptr ;
}
static char
read_char ( const char * mesg )
{
do {
fputs ( mesg , stdout ) ;
} while ( ! read_line ( ) ) ;
return * line_ptr ;
}
static char
read_chars ( const char * mesg )
{
fputs ( mesg , stdout ) ;
if ( ! read_line ( ) ) {
* line_ptr = ' \n ' ;
line_ptr [ 1 ] = 0 ;
}
return * line_ptr ;
}
static int
read_hex ( const struct systypes * sys )
{
int hex ;
2006-02-24 16:29:00 +00:00
while ( 1 ) {
read_char ( _ ( " Hex code (type L to list codes): " ) ) ;
if ( * line_ptr = = ' l ' | | * 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 ;
}
2002-11-26 22:00:21 +00:00
}
}
2003-01-04 11:56:06 +00:00
# endif /* CONFIG_FEATURE_FDISK_WRITABLE */
2002-11-26 22:00:21 +00:00
# ifdef CONFIG_FEATURE_AIX_LABEL
/*
* 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
# define aixlabel ((aix_partition *)MBRbuffer)
/*
Changes :
2003-07-30 08:40:37 +00:00
* 1999 - 03 - 20 Arnaldo Carvalho de Melo < acme @ conectiva . com . br >
* Internationalization
*
* 2003 - 03 - 20 Phillip Kesling < pkesling @ sgi . com >
* Some fixes
2002-11-26 22:00:21 +00:00
*/
2006-02-24 16:29:00 +00:00
static int aix_other_endian ;
static short aix_volumes = 1 ;
2002-11-26 22:00:21 +00:00
/*
* only dealing with free blocks here
*/
static void
2006-02-24 16:29:00 +00:00
aix_info ( void )
{
puts (
_ ( " \n \t There is a valid AIX label on this disk. \n "
" \t Unfortunately Linux cannot handle these \n "
" \t disks at the moment. Nevertheless some \n "
" \t advice: \n "
" \t 1. fdisk will destroy its contents on write. \n "
" \t 2. 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 "
" \t 3. 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). " )
) ;
2002-11-26 22:00:21 +00:00
}
static int
2006-02-24 16:29:00 +00:00
check_aix_label ( void )
2002-11-26 22:00:21 +00:00
{
2006-02-24 16:29:00 +00:00
if ( aixlabel - > magic ! = AIX_LABEL_MAGIC & &
aixlabel - > magic ! = AIX_LABEL_MAGIC_SWAPPED ) {
2006-02-25 03:46:10 +00:00
current_label_type = 0 ;
2006-02-24 16:29:00 +00:00
aix_other_endian = 0 ;
return 0 ;
}
aix_other_endian = ( aixlabel - > magic = = AIX_LABEL_MAGIC_SWAPPED ) ;
update_units ( ) ;
2006-02-25 03:46:10 +00:00
current_label_type = label_aix ;
2006-02-24 16:29:00 +00:00
partitions = 1016 ;
aix_volumes = 15 ;
aix_info ( ) ;
2006-02-25 03:46:10 +00:00
/*aix_nolabel();*/ /* %% */
/*aix_label = 1;*/ /* %% */
2006-02-24 16:29:00 +00:00
return 1 ;
2002-11-26 22:00:21 +00:00
}
# endif /* AIX_LABEL */
# ifdef CONFIG_FEATURE_OSF_LABEL
/*
* 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
2004-04-14 17:51:38 +00:00
* must display the following acknowledgment :
2002-11-26 22:00:21 +00:00
* 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 .
*/
# ifndef BSD_DISKMAGIC
2002-12-11 03:49:33 +00:00
# define BSD_DISKMAGIC ((uint32_t) 0x82564557)
2002-11-26 22:00:21 +00:00
# endif
# ifndef BSD_MAXPARTITIONS
# define BSD_MAXPARTITIONS 16
# endif
# define BSD_LINUX_BOOTDIR " / usr / ucb / mdec"
2006-06-30 02:53:56 +00:00
# if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__m68k__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
2002-11-26 22:00:21 +00:00
# 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
2003-07-30 08:40:37 +00:00
# elif defined (__s390__) || defined (__s390x__)
# define BSD_LABELSECTOR 1
# define BSD_LABELOFFSET 0
2002-11-26 22:00:21 +00:00
# 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 {
2002-12-11 03:49:33 +00:00
uint32_t d_magic ; /* the magic number */
2006-02-24 16:29:00 +00:00
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 */
2002-11-26 22:00:21 +00:00
/* disk geometry: */
2002-12-11 03:49:33 +00:00
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 */
2002-11-26 22:00:21 +00:00
/*
* 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 .
*/
2002-12-11 03:49:33 +00:00
uint16_t d_sparespertrack ; /* # of spare sectors per track */
uint16_t d_sparespercyl ; /* # of spare sectors per cylinder */
2002-11-26 22:00:21 +00:00
/*
* Alternate cylinders include maintenance , replacement ,
* configuration description areas , etc .
*/
2002-12-11 03:49:33 +00:00
uint32_t d_acylinders ; /* # of alt. cylinders per unit */
2002-11-26 22:00:21 +00:00
/* 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.
*/
2002-12-11 03:49:33 +00:00
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 */
2002-11-26 22:00:21 +00:00
# define NDDATA 5
2002-12-11 03:49:33 +00:00
uint32_t d_drivedata [ NDDATA ] ; /* drive-type specific information */
2002-11-26 22:00:21 +00:00
# define NSPARE 5
2002-12-11 03:49:33 +00:00
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 */
2002-11-26 22:00:21 +00:00
/* filesystem and partition information: */
2002-12-11 03:49:33 +00:00
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 */
2002-11-26 22:00:21 +00:00
struct xbsd_partition { /* the partition table */
2002-12-11 03:49:33 +00:00
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 */
2002-11-26 22:00:21 +00:00
} 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 const char * const 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 const struct systypes xbsd_fstypes [ ] = {
2006-02-24 16:29:00 +00:00
{ " \x00 " " unused " } , /* BSD_FS_UNUSED */
{ " \x01 " " swap " } , /* BSD_FS_SWAP */
{ " \x02 " " Version 6 " } , /* BSD_FS_V6 */
{ " \x03 " " Version 7 " } , /* BSD_FS_V7 */
{ " \x04 " " System V " } , /* BSD_FS_SYSV */
{ " \x05 " " 4.1BSD " } , /* BSD_FS_V71K */
{ " \x06 " " Eighth Edition " } , /* BSD_FS_V8 */
{ " \x07 " " 4.2BSD " } , /* BSD_FS_BSDFFS */
2002-11-26 22:00:21 +00:00
# ifdef __alpha__
2006-02-24 16:29:00 +00:00
{ " \x08 " " ext2 " } , /* BSD_FS_EXT2 */
2002-11-26 22:00:21 +00:00
# else
2006-02-24 16:29:00 +00:00
{ " \x08 " " MS-DOS " } , /* BSD_FS_MSDOS */
# endif
{ " \x09 " " 4.4LFS " } , /* BSD_FS_BSDLFS */
{ " \x0a " " unknown " } , /* BSD_FS_OTHER */
{ " \x0b " " HPFS " } , /* BSD_FS_HPFS */
{ " \x0c " " ISO-9660 " } , /* BSD_FS_ISO9660 */
{ " \x0d " " boot " } , /* BSD_FS_BOOT */
{ " \x0e " " ADOS " } , /* BSD_FS_ADOS */
{ " \x0f " " HFS " } , /* BSD_FS_HFS */
{ " \x10 " " AdvFS " } , /* BSD_FS_ADVFS */
{ NULL }
2002-11-26 22:00:21 +00:00
} ;
# define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
# endif
/*
* flags shared by various drives :
*/
# define BSD_D_REMOVABLE 0x01 /* removable media */
# define BSD_D_ECC 0x02 /* supports ECC */
# define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
# define BSD_D_RAMDISK 0x08 /* disk emulator */
# define BSD_D_CHAIN 0x10 /* can do back-back transfers */
# define BSD_D_DOSPART 0x20 /* within MSDOS partition */
# endif /* OSF_LABEL */
/*
* 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 ENABLE_CMDTAGQ 0x40
typedef struct {
unsigned int magic ; /* expect SGI_LABEL_MAGIC */
unsigned short boot_part ; /* active boot partition */
unsigned 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 SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
2002-12-11 03:49:33 +00:00
: ( uint16_t ) ( x ) )
2002-11-26 22:00:21 +00:00
# define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
2002-12-11 03:49:33 +00:00
: ( uint32_t ) ( x ) )
2002-11-26 22:00:21 +00:00
# define sgilabel ((sgi_partition *)MBRbuffer)
# define sgiparam (sgilabel->devparam)
typedef struct {
unsigned char info [ 128 ] ; /* Informative text string */
unsigned char spare0 [ 14 ] ;
struct sun_info {
unsigned char spare1 ;
unsigned char id ;
unsigned char spare2 ;
unsigned char flags ;
} infos [ 8 ] ;
unsigned char spare1 [ 246 ] ; /* Boot information etc. */
unsigned short rspeed ; /* Disk rotational speed */
unsigned short pcylcount ; /* Physical cylinder count */
unsigned short sparecyl ; /* extra sects per cylinder */
unsigned char spare2 [ 4 ] ; /* More magic... */
unsigned short ilfact ; /* Interleave factor */
unsigned short ncyl ; /* Data cylinder count */
unsigned short nacyl ; /* Alt. cylinder count */
unsigned short ntrks ; /* Tracks per cylinder */
unsigned short nsect ; /* Sectors per track */
unsigned char spare3 [ 4 ] ; /* Even more magic... */
struct sun_partition {
2002-12-11 03:49:33 +00:00
uint32_t start_cylinder ;
uint32_t num_sectors ;
2002-11-26 22:00:21 +00:00
} partitions [ 8 ] ;
unsigned short magic ; /* Magic number */
unsigned short csum ; /* Label xor'd checksum */
} sun_partition ;
2003-07-30 08:40:37 +00:00
2002-11-26 22:00:21 +00:00
# define SUN_LABEL_MAGIC 0xDABE
# define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
# define sunlabel ((sun_partition *)MBRbuffer)
# define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
2002-12-11 03:49:33 +00:00
: ( uint16_t ) ( x ) )
2002-11-26 22:00:21 +00:00
# define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
2002-12-11 03:49:33 +00:00
: ( uint32_t ) ( x ) )
2002-11-26 22:00:21 +00:00
2003-08-06 09:07:37 +00:00
2002-11-26 22:00:21 +00:00
# ifdef CONFIG_FEATURE_OSF_LABEL
/*
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 ( )
*/
# define FREEBSD_PARTITION 0xa5
# define NETBSD_PARTITION 0xa9
2006-02-24 16:29:00 +00:00
static void xbsd_delete_part ( void ) ;
static void xbsd_new_part ( void ) ;
static void xbsd_write_disklabel ( void ) ;
static int xbsd_create_disklabel ( void ) ;
static void xbsd_edit_disklabel ( void ) ;
static void xbsd_write_bootstrap ( void ) ;
static void xbsd_change_fstype ( void ) ;
static int xbsd_get_part_index ( int max ) ;
static int xbsd_check_new_partition ( int * i ) ;
static void xbsd_list_types ( void ) ;
static u_short xbsd_dkcksum ( struct xbsd_disklabel * lp ) ;
static int xbsd_initlabel ( struct partition * p , struct xbsd_disklabel * d ) ;
static int xbsd_readlabel ( struct partition * p , struct xbsd_disklabel * d ) ;
static int xbsd_writelabel ( struct partition * p , struct xbsd_disklabel * d ) ;
2002-11-26 22:00:21 +00:00
# if defined (__alpha__)
2006-02-24 16:29:00 +00:00
static void alpha_bootblock_checksum ( char * boot ) ;
2002-11-26 22:00:21 +00:00
# endif
# if !defined (__alpha__)
2006-02-24 16:29:00 +00:00
static int xbsd_translate_fstype ( int linux_type ) ;
static void xbsd_link_part ( void ) ;
2002-11-26 22:00:21 +00:00
static struct partition * xbsd_part ;
static int xbsd_part_index ;
# endif
# if defined (__alpha__)
2004-01-30 22:54:20 +00:00
/* We access this through a uint64_t * when checksumming */
2006-01-31 09:53:53 +00:00
static char disklabelbuffer [ BSD_BBSIZE ] ATTRIBUTE_ALIGNED ( 8 ) ;
2002-11-26 22:00:21 +00:00
# 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 .
*/
static int
2006-02-24 16:29:00 +00:00
check_osf_label ( void )
{
if ( xbsd_readlabel ( NULL , & xbsd_dlabel ) = = 0 )
2002-11-26 22:00:21 +00:00
return 0 ;
return 1 ;
}
static void xbsd_print_disklabel ( int ) ;
static int
2006-02-24 16:29:00 +00:00
btrydev ( const char * dev )
{
2002-11-26 22:00:21 +00:00
if ( xbsd_readlabel ( NULL , & xbsd_dlabel ) = = 0 )
return - 1 ;
printf ( _ ( " \n BSD label for device: %s \n " ) , dev ) ;
xbsd_print_disklabel ( 0 ) ;
return 0 ;
}
static void
2006-02-24 16:29:00 +00:00
bmenu ( void )
{
puts ( _ ( " Command action " ) ) ;
puts ( _ ( " \t d \t delete a BSD partition " ) ) ;
puts ( _ ( " \t e \t edit drive data " ) ) ;
puts ( _ ( " \t i \t install bootstrap " ) ) ;
puts ( _ ( " \t l \t list known filesystem types " ) ) ;
puts ( _ ( " \t m \t print this menu " ) ) ;
puts ( _ ( " \t n \t add a new BSD partition " ) ) ;
puts ( _ ( " \t p \t print BSD partition table " ) ) ;
puts ( _ ( " \t q \t quit without saving changes " ) ) ;
puts ( _ ( " \t r \t return to main menu " ) ) ;
puts ( _ ( " \t s \t show complete disklabel " ) ) ;
puts ( _ ( " \t t \t change a partition's filesystem id " ) ) ;
puts ( _ ( " \t u \t change units (cylinders/sectors) " ) ) ;
puts ( _ ( " \t w \t write disklabel to disk " ) ) ;
2002-11-26 22:00:21 +00:00
# if !defined (__alpha__)
2006-02-24 16:29:00 +00:00
puts ( _ ( " \t x \t link BSD partition to non-BSD partition " ) ) ;
2002-11-26 22:00:21 +00:00
# endif
}
# if !defined (__alpha__)
static int
2006-02-24 16:29:00 +00:00
hidden ( int type )
{
2002-11-26 22:00:21 +00:00
return type ^ 0x10 ;
}
static int
2006-02-24 16:29:00 +00:00
is_bsd_partition_type ( int type )
{
2002-11-26 22:00:21 +00:00
return ( type = = FREEBSD_PARTITION | |
type = = hidden ( FREEBSD_PARTITION ) | |
type = = NETBSD_PARTITION | |
type = = hidden ( NETBSD_PARTITION ) ) ;
}
# endif
static void
2006-02-24 16:29:00 +00:00
bselect ( void )
{
2002-11-26 22:00:21 +00:00
# if !defined (__alpha__)
2006-02-24 16:29:00 +00:00
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 ( disk_device , t + 1 , 0 ) ) ;
return ;
}
printf ( _ ( " Reading disklabel of %s at sector %d. \n " ) ,
partname ( disk_device , t + 1 , 0 ) , ss + BSD_LABELSECTOR ) ;
if ( xbsd_readlabel ( xbsd_part , & xbsd_dlabel ) = = 0 )
if ( xbsd_create_disklabel ( ) = = 0 )
return ;
break ;
}
}
if ( t = = 4 ) {
printf ( _ ( " There is no *BSD partition on %s. \n " ) , disk_device ) ;
return ;
}
2002-11-26 22:00:21 +00:00
# elif defined (__alpha__)
2006-02-24 16:29:00 +00:00
if ( xbsd_readlabel ( NULL , & xbsd_dlabel ) = = 0 )
if ( xbsd_create_disklabel ( ) = = 0 )
exit ( EXIT_SUCCESS ) ;
# endif
while ( 1 ) {
putchar ( ' \n ' ) ;
switch ( tolower ( read_char ( _ ( " BSD disklabel command (m for help): " ) ) ) ) {
case ' d ' :
xbsd_delete_part ( ) ;
break ;
case ' e ' :
xbsd_edit_disklabel ( ) ;
break ;
case ' i ' :
xbsd_write_bootstrap ( ) ;
break ;
case ' l ' :
xbsd_list_types ( ) ;
break ;
case ' n ' :
xbsd_new_part ( ) ;
break ;
case ' p ' :
xbsd_print_disklabel ( 0 ) ;
break ;
case ' q ' :
close ( fd ) ;
exit ( EXIT_SUCCESS ) ;
case ' r ' :
return ;
case ' s ' :
xbsd_print_disklabel ( 1 ) ;
break ;
case ' t ' :
xbsd_change_fstype ( ) ;
break ;
case ' u ' :
change_units ( ) ;
break ;
case ' w ' :
xbsd_write_disklabel ( ) ;
break ;
2002-11-26 22:00:21 +00:00
# if !defined (__alpha__)
2006-02-24 16:29:00 +00:00
case ' x ' :
xbsd_link_part ( ) ;
break ;
2002-11-26 22:00:21 +00:00
# endif
2006-02-24 16:29:00 +00:00
default :
bmenu ( ) ;
break ;
}
}
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
xbsd_delete_part ( void )
2002-11-26 22:00:21 +00:00
{
2006-02-24 16:29:00 +00:00
int i ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
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 - - ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
xbsd_new_part ( void )
2002-11-26 22:00:21 +00:00
{
2006-02-24 16:29:00 +00:00
off_t begin , end ;
char mesg [ 256 ] ;
int i ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
if ( ! xbsd_check_new_partition ( & i ) )
return ;
2002-11-26 22:00:21 +00:00
# if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
2006-02-24 16:29:00 +00:00
begin = get_start_sect ( xbsd_part ) ;
end = begin + get_nr_sects ( xbsd_part ) - 1 ;
2002-11-26 22:00:21 +00:00
# else
2006-02-24 16:29:00 +00:00
begin = 0 ;
end = xbsd_dlabel . d_secperunit - 1 ;
2002-11-26 22:00:21 +00:00
# endif
2006-02-24 16:29:00 +00:00
snprintf ( mesg , sizeof ( mesg ) , _ ( " First %s " ) , str_units ( SINGULAR ) ) ;
begin = read_int ( bsd_cround ( begin ) , bsd_cround ( begin ) , bsd_cround ( end ) ,
0 , mesg ) ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
if ( display_in_cyl_units )
begin = ( begin - 1 ) * xbsd_dlabel . d_secpercyl ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
snprintf ( mesg , sizeof ( mesg ) , _ ( " Last %s or +size or +sizeM or +sizeK " ) ,
str_units ( SINGULAR ) ) ;
end = read_int ( bsd_cround ( begin ) , bsd_cround ( end ) , bsd_cround ( end ) ,
bsd_cround ( begin ) , mesg ) ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
if ( display_in_cyl_units )
end = end * xbsd_dlabel . d_secpercyl - 1 ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
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 ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
xbsd_print_disklabel ( int show_all )
{
struct xbsd_disklabel * lp = & xbsd_dlabel ;
struct xbsd_partition * pp ;
int i , j ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
if ( show_all ) {
2002-11-26 22:00:21 +00:00
# if defined (__alpha__)
2006-02-24 16:29:00 +00:00
printf ( " # %s: \n " , disk_device ) ;
2002-11-26 22:00:21 +00:00
# else
2006-02-24 16:29:00 +00:00
printf ( " # %s: \n " , partname ( disk_device , xbsd_part_index + 1 , 0 ) ) ;
# endif
if ( ( unsigned ) lp - > d_type < BSD_DKMAXTYPES )
printf ( _ ( " type: %s \n " ) , xbsd_dktypenames [ lp - > d_type ] ) ;
else
printf ( _ ( " type: %d \n " ) , lp - > d_type ) ;
printf ( _ ( " disk: %.*s \n " ) , ( int ) sizeof ( lp - > d_typename ) , lp - > d_typename ) ;
printf ( _ ( " label: %.*s \n " ) , ( int ) sizeof ( lp - > d_packname ) , lp - > d_packname ) ;
printf ( _ ( " flags: " ) ) ;
if ( lp - > d_flags & BSD_D_REMOVABLE )
printf ( _ ( " removable " ) ) ;
if ( lp - > d_flags & BSD_D_ECC )
printf ( _ ( " ecc " ) ) ;
if ( lp - > d_flags & BSD_D_BADSECT )
printf ( _ ( " badsect " ) ) ;
printf ( " \n " ) ;
/* On various machines the fields of *lp are short/int/long */
/* In order to avoid problems, we cast them all to long. */
printf ( _ ( " bytes/sector: %ld \n " ) , ( long ) lp - > d_secsize ) ;
printf ( _ ( " sectors/track: %ld \n " ) , ( long ) lp - > d_nsectors ) ;
printf ( _ ( " tracks/cylinder: %ld \n " ) , ( long ) lp - > d_ntracks ) ;
printf ( _ ( " sectors/cylinder: %ld \n " ) , ( long ) lp - > d_secpercyl ) ;
printf ( _ ( " cylinders: %ld \n " ) , ( long ) lp - > d_ncylinders ) ;
printf ( _ ( " rpm: %d \n " ) , lp - > d_rpm ) ;
printf ( _ ( " interleave: %d \n " ) , lp - > d_interleave ) ;
printf ( _ ( " trackskew: %d \n " ) , lp - > d_trackskew ) ;
printf ( _ ( " cylinderskew: %d \n " ) , lp - > d_cylskew ) ;
printf ( _ ( " headswitch: %ld \t \t # milliseconds \n " ) ,
( long ) lp - > d_headswitch ) ;
printf ( _ ( " track-to-track seek: %ld \t # milliseconds \n " ) ,
( long ) lp - > d_trkseek ) ;
printf ( _ ( " 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 + + )
printf ( " %ld " , ( long ) lp - > d_drivedata [ j ] ) ;
}
printf ( _ ( " \n %d partitions: \n " ) , lp - > d_npartitions ) ;
printf ( _ ( " # 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 ) {
printf ( " %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 {
printf ( " %c: %8ld %8ld %8ld " ,
' a ' + i ,
( long ) pp - > p_offset ,
( long ) pp - > p_offset + pp - > p_size - 1 ,
( long ) pp - > p_size
) ;
}
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
if ( ( unsigned ) pp - > p_fstype < BSD_FSMAXTYPES )
printf ( " %8.8s " , xbsd_fstypes [ pp - > p_fstype ] . name ) ;
else
printf ( " %8x " , pp - > p_fstype ) ;
switch ( pp - > p_fstype ) {
case BSD_FS_UNUSED :
printf ( " %5ld %5ld %5.5s " ,
( long ) pp - > p_fsize , ( long ) pp - > p_fsize * pp - > p_frag , " " ) ;
break ;
case BSD_FS_BSDFFS :
printf ( " %5ld %5ld %5d " ,
( long ) pp - > p_fsize , ( long ) pp - > p_fsize * pp - > p_frag , pp - > p_cpg ) ;
break ;
default :
printf ( " %22.22s " , " " ) ;
break ;
}
printf ( " \n " ) ;
}
}
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
xbsd_write_disklabel ( void )
{
2002-11-26 22:00:21 +00:00
# if defined (__alpha__)
2006-02-24 16:29:00 +00:00
printf ( _ ( " Writing disklabel to %s. \n " ) , disk_device ) ;
xbsd_writelabel ( NULL , & xbsd_dlabel ) ;
2002-11-26 22:00:21 +00:00
# else
2006-02-24 16:29:00 +00:00
printf ( _ ( " Writing disklabel to %s. \n " ) ,
partname ( disk_device , xbsd_part_index + 1 , 0 ) ) ;
xbsd_writelabel ( xbsd_part , & xbsd_dlabel ) ;
2002-11-26 22:00:21 +00:00
# endif
reread_partition_table ( 0 ) ; /* no exit yet */
}
static int
2006-02-24 16:29:00 +00:00
xbsd_create_disklabel ( void )
{
2002-11-26 22:00:21 +00:00
char c ;
# if defined (__alpha__)
2006-02-24 16:29:00 +00:00
fprintf ( stderr , _ ( " %s contains no disklabel. \n " ) , disk_device ) ;
2002-11-26 22:00:21 +00:00
# else
2006-02-24 16:29:00 +00:00
fprintf ( stderr , _ ( " %s contains no disklabel. \n " ) ,
partname ( disk_device , xbsd_part_index + 1 , 0 ) ) ;
2002-11-26 22:00:21 +00:00
# endif
while ( 1 ) {
2006-02-24 16:29:00 +00:00
c = read_char ( _ ( " Do you want to create a disklabel? (y/n) " ) ) ;
2002-11-26 22:00:21 +00:00
if ( c = = ' y ' | | c = = ' Y ' ) {
2006-02-24 16:29:00 +00:00
if ( xbsd_initlabel (
2003-07-30 08:40:37 +00:00
# if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
2006-02-24 16:29:00 +00:00
defined ( __s390__ ) | | defined ( __s390x__ )
2006-01-31 09:53:53 +00:00
NULL , & xbsd_dlabel
2002-11-26 22:00:21 +00:00
# else
2006-01-31 09:53:53 +00:00
xbsd_part , & xbsd_dlabel /* not used, xbsd_part_index*/
2002-11-26 22:00:21 +00:00
# endif
) = = 1 ) {
xbsd_print_disklabel ( 1 ) ;
return 1 ;
} else
return 0 ;
} else if ( c = = ' n ' )
return 0 ;
}
}
static int
2006-02-24 16:29:00 +00:00
edit_int ( int def , char * mesg )
2002-11-26 22:00:21 +00:00
{
2006-02-24 16:29:00 +00:00
do {
fputs ( mesg , stdout ) ;
printf ( " (%d): " , def ) ;
if ( ! read_line ( ) )
return def ;
}
while ( ! isdigit ( * line_ptr ) ) ; /* FIXME: ?!! */
return atoi ( line_ptr ) ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
xbsd_edit_disklabel ( void )
2002-11-26 22:00:21 +00:00
{
2006-02-24 16:29:00 +00:00
struct xbsd_disklabel * d ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
d = & xbsd_dlabel ;
2002-11-26 22:00:21 +00:00
# if defined (__alpha__) || defined (__ia64__)
2006-02-24 16:29:00 +00:00
d - > d_secsize = ( u_long ) edit_int ( ( u_long ) d - > d_secsize , _ ( " bytes/sector " ) ) ;
d - > d_nsectors = ( u_long ) edit_int ( ( u_long ) d - > d_nsectors , _ ( " sectors/track " ) ) ;
d - > d_ntracks = ( u_long ) edit_int ( ( u_long ) d - > d_ntracks , _ ( " tracks/cylinder " ) ) ;
d - > d_ncylinders = ( u_long ) edit_int ( ( u_long ) d - > d_ncylinders , _ ( " cylinders " ) ) ;
2002-11-26 22:00:21 +00:00
# endif
2006-02-24 16:29:00 +00:00
/* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */
while ( 1 ) {
d - > d_secpercyl = ( u_long ) edit_int ( ( u_long ) d - > d_nsectors * d - > d_ntracks ,
_ ( " sectors/cylinder " ) ) ;
if ( d - > d_secpercyl < = d - > d_nsectors * d - > d_ntracks )
break ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
printf ( _ ( " Must be <= sectors/track * tracks/cylinder (default). \n " ) ) ;
}
d - > d_rpm = ( u_short ) edit_int ( ( u_short ) d - > d_rpm , _ ( " rpm " ) ) ;
d - > d_interleave = ( u_short ) edit_int ( ( u_short ) d - > d_interleave , _ ( " interleave " ) ) ;
d - > d_trackskew = ( u_short ) edit_int ( ( u_short ) d - > d_trackskew , _ ( " trackskew " ) ) ;
d - > d_cylskew = ( u_short ) edit_int ( ( u_short ) d - > d_cylskew , _ ( " cylinderskew " ) ) ;
d - > d_headswitch = ( u_long ) edit_int ( ( u_long ) d - > d_headswitch , _ ( " headswitch " ) ) ;
d - > d_trkseek = ( u_long ) edit_int ( ( u_long ) d - > d_trkseek , _ ( " track-to-track seek " ) ) ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
d - > d_secperunit = d - > d_secpercyl * d - > d_ncylinders ;
2002-11-26 22:00:21 +00:00
}
static int
xbsd_get_bootstrap ( char * path , void * ptr , int size )
{
2006-02-24 16:29:00 +00:00
int fdb ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
if ( ( fdb = open ( path , O_RDONLY ) ) < 0 ) {
perror ( path ) ;
return 0 ;
}
if ( read ( fdb , ptr , size ) < 0 ) {
perror ( path ) ;
close ( fdb ) ;
return 0 ;
}
printf ( " ... %s \n " , path ) ;
close ( fdb ) ;
return 1 ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
sync_disks ( void )
2002-11-26 22:00:21 +00:00
{
2006-02-24 16:29:00 +00:00
printf ( _ ( " \n Syncing disks. \n " ) ) ;
sync ( ) ;
sleep ( 4 ) ; /* What? */
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
xbsd_write_bootstrap ( void )
{
char * bootdir = BSD_LINUX_BOOTDIR ;
char path [ MAXPATHLEN ] ;
char * dkbasename ;
struct xbsd_disklabel dl ;
char * d , * p , * e ;
int sector ;
if ( xbsd_dlabel . d_type = = BSD_DTYPE_SCSI )
dkbasename = " sd " ;
else
dkbasename = " wd " ;
printf ( _ ( " Bootstrap: %sboot -> boot%s (%s): " ) ,
dkbasename , dkbasename , dkbasename ) ;
if ( read_line ( ) ) {
line_ptr [ strlen ( line_ptr ) - 1 ] = ' \0 ' ;
dkbasename = line_ptr ;
}
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 ] ;
2006-04-16 05:58:21 +00:00
memmove ( & dl , d , sizeof ( struct xbsd_disklabel ) ) ;
2006-02-24 16:29:00 +00:00
/* 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 ] ,
2002-11-26 22:00:21 +00:00
( int ) xbsd_dlabel . d_bbsize - xbsd_dlabel . d_secsize ) )
2006-02-24 16:29:00 +00:00
return ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
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 ) ;
}
2002-11-26 22:00:21 +00:00
2006-04-16 05:58:21 +00:00
memmove ( d , & dl , sizeof ( struct xbsd_disklabel ) ) ;
2002-11-26 22:00:21 +00:00
# if defined (__powerpc__) || defined (__hppa__)
2006-02-24 16:29:00 +00:00
sector = 0 ;
2002-11-26 22:00:21 +00:00
# elif defined (__alpha__)
2006-02-24 16:29:00 +00:00
sector = 0 ;
alpha_bootblock_checksum ( disklabelbuffer ) ;
2002-11-26 22:00:21 +00:00
# else
2006-02-24 16:29:00 +00:00
sector = get_start_sect ( xbsd_part ) ;
2002-11-26 22:00:21 +00:00
# endif
2006-02-24 16:29:00 +00:00
if ( lseek ( fd , sector * SECTOR_SIZE , SEEK_SET ) = = - 1 )
fdisk_fatal ( unable_to_seek ) ;
if ( BSD_BBSIZE ! = write ( fd , disklabelbuffer , BSD_BBSIZE ) )
fdisk_fatal ( unable_to_write ) ;
2002-11-26 22:00:21 +00:00
# if defined (__alpha__)
2006-02-24 16:29:00 +00:00
printf ( _ ( " Bootstrap installed on %s. \n " ) , disk_device ) ;
2002-11-26 22:00:21 +00:00
# else
2006-02-24 16:29:00 +00:00
printf ( _ ( " Bootstrap installed on %s. \n " ) ,
partname ( disk_device , xbsd_part_index + 1 , 0 ) ) ;
2002-11-26 22:00:21 +00:00
# endif
2006-02-24 16:29:00 +00:00
sync_disks ( ) ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
xbsd_change_fstype ( void )
2002-11-26 22:00:21 +00:00
{
2006-02-24 16:29:00 +00:00
int i ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
i = xbsd_get_part_index ( xbsd_dlabel . d_npartitions ) ;
xbsd_dlabel . d_partitions [ i ] . p_fstype = read_hex ( xbsd_fstypes ) ;
2002-11-26 22:00:21 +00:00
}
static int
2006-02-24 16:29:00 +00:00
xbsd_get_part_index ( int max )
2002-11-26 22:00:21 +00:00
{
2006-02-24 16:29:00 +00:00
char prompt [ 256 ] ;
char l ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
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 ' ;
2002-11-26 22:00:21 +00:00
}
static int
2006-02-24 16:29:00 +00:00
xbsd_check_new_partition ( int * i )
{
2002-11-26 22:00:21 +00:00
/* 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 ) {
2006-02-24 16:29:00 +00:00
fprintf ( stderr , _ ( " The maximum number of partitions "
2002-11-26 22:00:21 +00:00
" 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 ) {
2006-02-24 16:29:00 +00:00
fprintf ( stderr , _ ( " This partition already exists. \n " ) ) ;
2002-11-26 22:00:21 +00:00
return 0 ;
}
return 1 ;
}
static void
2006-02-24 16:29:00 +00:00
xbsd_list_types ( void )
{
list_types ( xbsd_fstypes ) ;
2002-11-26 22:00:21 +00:00
}
static u_short
2006-02-24 16:29:00 +00:00
xbsd_dkcksum ( struct xbsd_disklabel * lp )
{
2002-11-26 22:00:21 +00:00
u_short * start , * end ;
u_short sum = 0 ;
start = ( u_short * ) lp ;
end = ( u_short * ) & lp - > d_partitions [ lp - > d_npartitions ] ;
while ( start < end )
sum ^ = * start + + ;
return sum ;
}
static int
2006-02-24 16:29:00 +00:00
xbsd_initlabel ( struct partition * p , struct xbsd_disklabel * d )
{
2002-11-26 22:00:21 +00:00
struct xbsd_partition * pp ;
2006-02-24 16:29:00 +00:00
get_geometry ( ) ;
memset ( d , 0 , sizeof ( struct xbsd_disklabel ) ) ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
d - > d_magic = BSD_DISKMAGIC ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
if ( strncmp ( disk_device , " /dev/sd " , 7 ) = = 0 )
d - > d_type = BSD_DTYPE_SCSI ;
2002-11-26 22:00:21 +00:00
else
2006-02-24 16:29:00 +00:00
d - > d_type = BSD_DTYPE_ST506 ;
2002-11-26 22:00:21 +00:00
#if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
2006-02-24 16:29:00 +00:00
d - > d_subtype = BSD_DSTYPE_INDOSPART & pindex ;
2002-11-26 22:00:21 +00:00
# endif
# if !defined (__alpha__)
2006-02-24 16:29:00 +00:00
d - > d_flags = BSD_D_DOSPART ;
2002-11-26 22:00:21 +00:00
# else
2006-02-24 16:29:00 +00:00
d - > d_flags = 0 ;
# endif
d - > d_secsize = SECTOR_SIZE ; /* bytes/sector */
d - > d_nsectors = sectors ; /* sectors/track */
d - > d_ntracks = heads ; /* tracks/cylinder (heads) */
d - > d_ncylinders = cylinders ;
d - > d_secpercyl = sectors * 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 ;
2002-11-26 22:00:21 +00:00
# if !defined (__alpha__)
2006-02-24 16:29:00 +00:00
d - > d_npartitions = 4 ;
pp = & d - > d_partitions [ 2 ] ; /* Partition C should be
2002-11-26 22:00:21 +00:00
the NetBSD partition */
2006-02-24 16:29:00 +00:00
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
2002-11-26 22:00:21 +00:00
the whole disk */
2006-02-24 16:29:00 +00:00
pp - > p_offset = 0 ;
pp - > p_size = d - > d_secperunit ;
pp - > p_fstype = BSD_FS_UNUSED ;
2002-11-26 22:00:21 +00:00
# elif defined (__alpha__)
2006-02-24 16:29:00 +00:00
d - > d_npartitions = 3 ;
pp = & d - > d_partitions [ 2 ] ; /* Partition C should be
2002-11-26 22:00:21 +00:00
the whole disk */
2006-02-24 16:29:00 +00:00
pp - > p_offset = 0 ;
pp - > p_size = d - > d_secperunit ;
pp - > p_fstype = BSD_FS_UNUSED ;
2002-11-26 22:00:21 +00:00
# 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 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
2006-02-24 16:29:00 +00:00
if ( lseek ( fd , sector * SECTOR_SIZE , SEEK_SET ) = = - 1 )
fdisk_fatal ( unable_to_seek ) ;
if ( BSD_BBSIZE ! = read ( fd , disklabelbuffer , BSD_BBSIZE ) )
fdisk_fatal ( unable_to_read ) ;
2002-11-26 22:00:21 +00:00
2006-04-16 05:58:21 +00:00
memmove ( d , & disklabelbuffer [ BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET ] ,
sizeof ( struct xbsd_disklabel ) ) ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
if ( d - > d_magic ! = BSD_DISKMAGIC | | d - > d_magic2 ! = BSD_DISKMAGIC )
2002-11-26 22:00:21 +00:00
return 0 ;
2006-02-24 16:29:00 +00:00
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 ;
2002-11-26 22:00:21 +00:00
}
2006-02-24 16:29:00 +00:00
if ( d - > d_npartitions > BSD_MAXPARTITIONS )
fprintf ( stderr , _ ( " Warning: too many partitions "
" (%d, maximum is %d). \n " ) ,
d - > d_npartitions , BSD_MAXPARTITIONS ) ;
2002-11-26 22:00:21 +00:00
return 1 ;
}
static int
xbsd_writelabel ( struct partition * p , struct xbsd_disklabel * d )
{
2006-02-24 16:29:00 +00:00
unsigned int sector ;
2002-11-26 22:00:21 +00:00
# if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
2006-02-24 16:29:00 +00:00
sector = get_start_sect ( p ) + BSD_LABELSECTOR ;
2002-11-26 22:00:21 +00:00
# else
2006-02-24 16:29:00 +00:00
sector = BSD_LABELSECTOR ;
2002-11-26 22:00:21 +00:00
# endif
2006-02-24 16:29:00 +00:00
d - > d_checksum = 0 ;
d - > d_checksum = xbsd_dkcksum ( d ) ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
/* This is necessary if we want to write the bootstrap later,
otherwise we ' d write the old disklabel with the bootstrap .
*/
2006-04-16 05:58:21 +00:00
memmove ( & disklabelbuffer [ BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET ] ,
d , sizeof ( struct xbsd_disklabel ) ) ;
2002-11-26 22:00:21 +00:00
# if defined (__alpha__) && BSD_LABELSECTOR == 0
2006-02-24 16:29:00 +00:00
alpha_bootblock_checksum ( disklabelbuffer ) ;
if ( lseek ( fd , 0 , SEEK_SET ) = = - 1 )
fdisk_fatal ( unable_to_seek ) ;
if ( BSD_BBSIZE ! = write ( fd , disklabelbuffer , BSD_BBSIZE ) )
fdisk_fatal ( unable_to_write ) ;
2002-11-26 22:00:21 +00:00
# else
2006-02-24 16:29:00 +00:00
if ( lseek ( fd , sector * SECTOR_SIZE + BSD_LABELOFFSET , SEEK_SET ) = = - 1 )
fdisk_fatal ( unable_to_seek ) ;
if ( sizeof ( struct xbsd_disklabel ) ! = write ( fd , d , sizeof ( struct xbsd_disklabel ) ) )
fdisk_fatal ( unable_to_write ) ;
2002-11-26 22:00:21 +00:00
# endif
2006-02-24 16:29:00 +00:00
sync_disks ( ) ;
return 1 ;
2002-11-26 22:00:21 +00:00
}
# if !defined (__alpha__)
static int
2006-02-24 16:29:00 +00:00
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 ;
}
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
xbsd_link_part ( void )
2002-11-26 22:00:21 +00:00
{
2006-02-24 16:29:00 +00:00
int k , i ;
struct partition * p ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
k = get_partition ( 1 , partitions ) ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
if ( ! xbsd_check_new_partition ( & i ) )
return ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
p = get_part_table ( k ) ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
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 ) ;
2002-11-26 22:00:21 +00:00
}
# endif
# if defined (__alpha__)
# if !defined(__GLIBC__)
2004-01-30 22:54:20 +00:00
typedef unsigned long long uint64_t ;
2002-11-26 22:00:21 +00:00
# endif
static void
2006-02-24 16:29:00 +00:00
alpha_bootblock_checksum ( char * boot )
2002-11-26 22:00:21 +00:00
{
2006-02-24 16:29:00 +00:00
uint64_t * dp , sum ;
int i ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
dp = ( uint64_t * ) boot ;
sum = 0 ;
for ( i = 0 ; i < 63 ; i + + )
sum + = dp [ i ] ;
dp [ 63 ] = sum ;
2002-11-26 22:00:21 +00:00
}
# endif /* __alpha__ */
# endif /* OSF_LABEL */
# if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
static inline unsigned short
2006-02-24 16:29:00 +00:00
__swap16 ( unsigned short x )
{
2002-12-11 03:49:33 +00:00
return ( ( ( uint16_t ) ( x ) & 0xFF ) < < 8 ) | ( ( ( uint16_t ) ( x ) & 0xFF00 ) > > 8 ) ;
2002-11-26 22:00:21 +00:00
}
2002-12-11 03:49:33 +00:00
static inline uint32_t
2006-02-24 16:29:00 +00:00
__swap32 ( uint32_t x )
{
return ( ( ( x & 0xFF ) < < 24 ) |
2003-07-30 08:40:37 +00:00
( ( x & 0xFF00 ) < < 8 ) |
( ( x & 0xFF0000 ) > > 8 ) |
( ( x & 0xFF000000 ) > > 24 ) ) ;
2002-11-26 22:00:21 +00:00
}
# endif
# ifdef CONFIG_FEATURE_SGI_LABEL
/*
*
* fdisksgilabel . c
*
* Copyright ( C ) Andreas Neuper , Sep 1998.
* This file may be modified and redistributed under
* the terms of the GNU Public License .
*
* Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo < acme @ conectiva . com . br >
* Internationalization
*/
2006-02-24 16:29:00 +00:00
static int sgi_other_endian ;
static int debug ;
static short sgi_volumes = 1 ;
2002-11-26 22:00:21 +00:00
/*
* only dealing with free blocks here
*/
2006-02-24 16:29:00 +00:00
typedef struct {
unsigned int first ;
unsigned int last ;
} freeblocks ;
2002-11-26 22:00:21 +00:00
static freeblocks freelist [ 17 ] ; /* 16 partitions can produce 17 vacant slots */
static void
2006-02-24 16:29:00 +00:00
setfreelist ( int i , unsigned int f , unsigned int l )
{
2002-11-26 22:00:21 +00:00
freelist [ i ] . first = f ;
freelist [ i ] . last = l ;
}
static void
2006-02-24 16:29:00 +00:00
add2freelist ( unsigned int f , unsigned int l )
{
int i ;
for ( i = 0 ; i < 17 ; i + + )
2003-07-30 08:40:37 +00:00
if ( freelist [ i ] . last = = 0 )
break ;
setfreelist ( i , f , l ) ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
clearfreelist ( void )
{
2003-07-30 08:40:37 +00:00
int i ;
for ( i = 0 ; i < 17 ; i + + )
setfreelist ( i , 0 , 0 ) ;
2002-11-26 22:00:21 +00:00
}
2003-07-30 08:40:37 +00:00
static unsigned int
2006-02-24 16:29:00 +00:00
isinfreelist ( unsigned int b )
{
2003-07-30 08:40:37 +00:00
int i ;
for ( i = 0 ; i < 17 ; i + + )
if ( freelist [ i ] . first < = b & & freelist [ i ] . last > = b )
2002-11-26 22:00:21 +00:00
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
*/
static const struct systypes sgi_sys_types [ ] = {
2006-02-24 16:29:00 +00:00
/* SGI_VOLHDR */ { " \x00 " " SGI volhdr " } ,
/* 0x01 */ { " \x01 " " SGI trkrepl " } ,
/* 0x02 */ { " \x02 " " SGI secrepl " } ,
/* SGI_SWAP */ { " \x03 " " SGI raw " } ,
/* 0x04 */ { " \x04 " " SGI bsd " } ,
/* 0x05 */ { " \x05 " " SGI sysv " } ,
/* ENTIRE_DISK */ { " \x06 " " SGI volume " } ,
/* SGI_EFS */ { " \x07 " " SGI efs " } ,
/* 0x08 */ { " \x08 " " SGI lvol " } ,
/* 0x09 */ { " \x09 " " SGI rlvol " } ,
/* SGI_XFS */ { " \x0a " " SGI xfs " } ,
/* SGI_XFSLOG */ { " \x0b " " SGI xfslog " } ,
/* SGI_XLV */ { " \x0c " " SGI xlv " } ,
/* SGI_XVM */ { " \x0d " " SGI xvm " } ,
/* LINUX_SWAP */ { " \x82 " " Linux swap " } ,
/* LINUX_NATIVE */ { " \x83 " " Linux native " } ,
/* LINUX_LVM */ { " \x8d " " Linux LVM " } ,
/* LINUX_RAID */ { " \xfd " " Linux RAID " } ,
{ NULL }
2002-11-26 22:00:21 +00:00
} ;
static int
2006-02-24 16:29:00 +00:00
sgi_get_nsect ( void )
{
return SGI_SSWAP16 ( sgilabel - > devparam . nsect ) ;
2002-11-26 22:00:21 +00:00
}
static int
2006-02-24 16:29:00 +00:00
sgi_get_ntrks ( void )
{
return SGI_SSWAP16 ( sgilabel - > devparam . ntrks ) ;
2002-11-26 22:00:21 +00:00
}
static unsigned int
2006-02-24 16:29:00 +00:00
two_s_complement_32bit_sum ( unsigned int * base , int size /* in bytes */ )
{
int i = 0 ;
unsigned int sum = 0 ;
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
size / = sizeof ( unsigned int ) ;
for ( i = 0 ; i < size ; i + + )
sum - = SGI_SSWAP32 ( base [ i ] ) ;
return sum ;
2002-11-26 22:00:21 +00:00
}
static int
2006-02-24 16:29:00 +00:00
check_sgi_label ( void )
{
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 ) {
2006-02-25 03:46:10 +00:00
current_label_type = label_dos ;
2006-02-24 16:29:00 +00:00
return 0 ;
}
sgi_other_endian = ( sgilabel - > magic = = SGI_LABEL_MAGIC_SWAPPED ) ;
/*
* test for correct checksum
*/
if ( two_s_complement_32bit_sum ( ( unsigned int * ) sgilabel ,
sizeof ( * sgilabel ) ) ) {
2003-07-30 08:40:37 +00:00
fprintf ( stderr ,
_ ( " Detected sgi disklabel with wrong checksum. \n " ) ) ;
2006-02-24 16:29:00 +00:00
}
update_units ( ) ;
2006-02-25 03:46:10 +00:00
current_label_type = label_sgi ;
2006-02-24 16:29:00 +00:00
partitions = 16 ;
sgi_volumes = 15 ;
return 1 ;
2002-11-26 22:00:21 +00:00
}
2003-07-30 08:40:37 +00:00
static unsigned int
2006-02-24 16:29:00 +00:00
sgi_get_start_sector ( int i )
{
return SGI_SSWAP32 ( sgilabel - > partitions [ i ] . start_sector ) ;
2002-11-26 22:00:21 +00:00
}
2003-07-30 08:40:37 +00:00
static unsigned int
2006-02-24 16:29:00 +00:00
sgi_get_num_sectors ( int i )
{
return SGI_SSWAP32 ( sgilabel - > partitions [ i ] . num_sectors ) ;
2002-11-26 22:00:21 +00:00
}
static int
2003-07-30 08:40:37 +00:00
sgi_get_sysid ( int i )
2002-11-26 22:00:21 +00:00
{
2006-02-24 16:29:00 +00:00
return SGI_SSWAP32 ( sgilabel - > partitions [ i ] . id ) ;
2002-11-26 22:00:21 +00:00
}
static int
sgi_get_bootpartition ( void )
{
2006-02-24 16:29:00 +00:00
return SGI_SSWAP16 ( sgilabel - > boot_part ) ;
2002-11-26 22:00:21 +00:00
}
static int
sgi_get_swappartition ( void )
{
2006-02-24 16:29:00 +00:00
return SGI_SSWAP16 ( sgilabel - > swap_part ) ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
sgi_list_table ( int xtra )
{
int i , w , wd ;
int kpi = 0 ; /* kernel partition ID */
if ( xtra ) {
printf ( _ ( " \n Disk %s (SGI disk label): %d heads, %d sectors \n "
" %d cylinders, %d physical cylinders \n "
" %d extra sects/cyl, interleave %d:1 \n "
" %s \n "
" Units = %s of %d * 512 bytes \n \n " ) ,
disk_device , heads , sectors , cylinders ,
SGI_SSWAP16 ( sgiparam . pcylcount ) ,
SGI_SSWAP16 ( sgiparam . sparecyl ) ,
SGI_SSWAP16 ( sgiparam . ilfact ) ,
( char * ) sgilabel ,
str_units ( PLURAL ) , units_per_sector ) ;
} else {
printf ( _ ( " \n Disk %s (SGI disk label): "
" %d heads, %d sectors, %d cylinders \n "
" Units = %s of %d * 512 bytes \n \n " ) ,
disk_device , heads , sectors , cylinders ,
str_units ( PLURAL ) , units_per_sector ) ;
}
2003-08-08 20:04:56 +00:00
2006-02-24 16:29:00 +00:00
w = strlen ( disk_device ) ;
wd = strlen ( _ ( " Device " ) ) ;
if ( w < wd )
2003-08-08 20:04:56 +00:00
w = wd ;
2006-02-24 16:29:00 +00:00
printf ( _ ( " ----- partitions ----- \n "
" Pt# %*s Info Start End Sectors Id System \n " ) ,
w + 2 , _ ( " Device " ) ) ;
for ( i = 0 ; i < partitions ; i + + ) {
if ( sgi_get_num_sectors ( i ) | | debug ) {
uint32_t start = sgi_get_start_sector ( i ) ;
uint32_t len = sgi_get_num_sectors ( i ) ;
kpi + + ; /* only count nonempty partitions */
printf (
" %2d: %s %4s %9ld %9ld %9ld %2x %s \n " ,
/* fdisk part number */ i + 1 ,
/* device */ partname ( disk_device , kpi , w + 3 ) ,
/* flags */ ( sgi_get_swappartition ( ) = = i ) ? " swap " :
/* flags */ ( sgi_get_bootpartition ( ) = = i ) ? " boot " : " " ,
/* start */ ( long ) scround ( start ) ,
/* end */ ( long ) scround ( start + len ) - 1 ,
/* no odd flag on end */ ( long ) len ,
/* type id */ sgi_get_sysid ( i ) ,
/* type name */ partition_type ( sgi_get_sysid ( i ) ) ) ;
}
}
printf ( _ ( " ----- Bootinfo ----- \n Bootfile: %s \n "
" ----- Directory Entries ----- \n " ) ,
sgilabel - > boot_file ) ;
2003-07-30 08:40:37 +00:00
for ( i = 0 ; i < sgi_volumes ; i + + ) {
2006-02-24 16:29:00 +00:00
if ( sgilabel - > directory [ i ] . vol_file_size ) {
uint32_t start = SGI_SSWAP32 ( sgilabel - > directory [ i ] . vol_file_start ) ;
uint32_t len = SGI_SSWAP32 ( sgilabel - > directory [ i ] . vol_file_size ) ;
unsigned char * name = sgilabel - > directory [ i ] . vol_file_name ;
2003-07-30 08:40:37 +00:00
2006-02-24 16:29:00 +00:00
printf ( _ ( " %2d: %-10s sector%5u size%8u \n " ) ,
i , ( char * ) name , ( unsigned int ) start , ( unsigned int ) len ) ;
}
2002-11-26 22:00:21 +00:00
}
}
static void
2006-02-24 16:29:00 +00:00
sgi_set_bootpartition ( int i )
2002-11-26 22:00:21 +00:00
{
2006-02-24 16:29:00 +00:00
sgilabel - > boot_part = SGI_SSWAP16 ( ( ( short ) i ) ) ;
2002-11-26 22:00:21 +00:00
}
2003-07-30 08:40:37 +00:00
static unsigned int
2006-02-24 16:29:00 +00:00
sgi_get_lastblock ( void )
{
return heads * sectors * cylinders ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
sgi_set_swappartition ( int i )
{
sgilabel - > swap_part = SGI_SSWAP16 ( ( ( short ) i ) ) ;
2002-11-26 22:00:21 +00:00
}
static int
2006-02-24 16:29:00 +00:00
sgi_check_bootfile ( const char * aFile )
{
if ( strlen ( aFile ) < 3 ) /* "/a\n" is minimum */ {
printf ( _ ( " \n Invalid Bootfile! \n "
" \t The bootfile must be an absolute non-zero pathname, \n "
" \t e.g. \" /unix \" or \" /unix.save \" . \n " ) ) ;
return 0 ;
2003-07-30 08:40:37 +00:00
} else {
if ( strlen ( aFile ) > 16 ) {
printf ( _ ( " \n \t Name of Bootfile too long: "
2006-02-24 16:29:00 +00:00
" 16 bytes maximum. \n " ) ) ;
return 0 ;
2003-07-30 08:40:37 +00:00
} else {
if ( aFile [ 0 ] ! = ' / ' ) {
printf ( _ ( " \n \t Bootfile must have a "
2006-02-24 16:29:00 +00:00
" fully qualified pathname. \n " ) ) ;
return 0 ;
}
2003-07-30 08:40:37 +00:00
}
2006-02-24 16:29:00 +00:00
}
2006-01-30 23:09:20 +00:00
if ( strncmp ( aFile , ( char * ) sgilabel - > boot_file , 16 ) ) {
2003-07-30 08:40:37 +00:00
printf ( _ ( " \n \t Be aware, that the bootfile is not checked for existence. \n \t "
" SGI's default is \" /unix \" and for backup \" /unix.save \" . \n " ) ) ;
2006-02-24 16:29:00 +00:00
/* filename is correct and did change */
return 1 ;
}
return 0 ; /* filename did not change */
2002-11-26 22:00:21 +00:00
}
static const char *
2006-02-24 16:29:00 +00:00
sgi_get_bootfile ( void )
{
2006-01-30 23:09:20 +00:00
return ( char * ) sgilabel - > boot_file ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
sgi_set_bootfile ( const char * aFile )
{
int i = 0 ;
2003-07-30 08:40:37 +00:00
2006-02-24 16:29:00 +00:00
if ( sgi_check_bootfile ( aFile ) ) {
while ( i < 16 ) {
if ( ( aFile [ i ] ! = ' \n ' ) /* in principle caught again by next line */
& & ( strlen ( aFile ) > i ) )
sgilabel - > boot_file [ i ] = aFile [ i ] ;
else
sgilabel - > boot_file [ i ] = 0 ;
i + + ;
}
printf ( _ ( " \n \t Bootfile is changed to \" %s \" . \n " ) , sgilabel - > boot_file ) ;
2002-11-26 22:00:21 +00:00
}
}
static void
create_sgiinfo ( void )
{
2006-02-24 16:29:00 +00:00
/* I keep SGI's habit to write the sgilabel to the second block */
sgilabel - > directory [ 0 ] . vol_file_start = SGI_SSWAP32 ( 2 ) ;
sgilabel - > directory [ 0 ] . vol_file_size = SGI_SSWAP32 ( sizeof ( sgiinfo ) ) ;
2006-06-25 22:39:24 +00:00
strcpy ( ( char * ) sgilabel - > directory [ 0 ] . vol_file_name , " sgilabel " ) ;
2002-11-26 22:00:21 +00:00
}
2003-07-30 08:40:37 +00:00
static sgiinfo * fill_sgiinfo ( void ) ;
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
sgi_write_table ( void )
{
sgilabel - > csum = 0 ;
sgilabel - > csum = SGI_SSWAP32 ( two_s_complement_32bit_sum (
( unsigned int * ) sgilabel , sizeof ( * sgilabel ) ) ) ;
assert ( two_s_complement_32bit_sum (
2003-07-30 08:40:37 +00:00
( unsigned int * ) sgilabel , sizeof ( * sgilabel ) ) = = 0 ) ;
2006-02-24 16:29:00 +00:00
if ( lseek ( fd , 0 , SEEK_SET ) < 0 )
fdisk_fatal ( unable_to_seek ) ;
if ( write ( fd , sgilabel , SECTOR_SIZE ) ! = SECTOR_SIZE )
fdisk_fatal ( 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 = SGI_SSWAP32 ( sgilabel - > directory [ 0 ] . vol_file_start ) ;
if ( lseek ( fd , infostartblock * SECTOR_SIZE , SEEK_SET ) < 0 )
fdisk_fatal ( unable_to_seek ) ;
if ( write ( fd , info , SECTOR_SIZE ) ! = SECTOR_SIZE )
fdisk_fatal ( unable_to_write ) ;
free ( info ) ;
}
2002-11-26 22:00:21 +00:00
}
static int
2006-02-24 16:29:00 +00:00
compare_start ( int * x , int * y )
{
/*
* sort according to start sectors
* and prefers largest partition :
* entry zero is entire disk entry
*/
unsigned int i = * x ;
unsigned int j = * y ;
unsigned int a = sgi_get_start_sector ( i ) ;
unsigned int b = sgi_get_start_sector ( j ) ;
unsigned int c = sgi_get_num_sectors ( i ) ;
unsigned int d = sgi_get_num_sectors ( j ) ;
2003-07-30 08:40:37 +00:00
2006-02-24 16:29:00 +00:00
if ( a = = b )
return ( d > c ) ? 1 : ( d = = c ) ? 0 : - 1 ;
return ( a > b ) ? 1 : - 1 ;
2002-11-26 22:00:21 +00:00
}
static int
2003-07-30 08:40:37 +00:00
verify_sgi ( int verbose )
2002-11-26 22:00:21 +00:00
{
2006-02-24 16:29:00 +00:00
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 ( ) ;
clearfreelist ( ) ;
for ( i = 0 ; i < 16 ; i + + ) {
if ( sgi_get_num_sectors ( i ) ! = 0 ) {
Index [ sortcount + + ] = i ;
if ( sgi_get_sysid ( i ) = = ENTIRE_DISK ) {
if ( entire + + = = 1 ) {
if ( verbose )
printf ( _ ( " More than one entire disk entry present. \n " ) ) ;
}
}
2002-11-26 22:00:21 +00:00
}
2006-02-24 16:29:00 +00:00
}
if ( sortcount = = 0 ) {
if ( verbose )
printf ( _ ( " No partitions defined \n " ) ) ;
return ( lastblock > 0 ) ? 1 : ( lastblock = = 0 ) ? 0 : - 1 ;
}
qsort ( Index , sortcount , sizeof ( Index [ 0 ] ) , ( void * ) compare_start ) ;
if ( sgi_get_sysid ( 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 ( Index [ 0 ] ) ! = 0 ) & & verbose )
printf ( _ ( " The entire disk partition should start "
2003-07-30 08:40:37 +00:00
" at block 0, \n "
" not at diskblock %d. \n " ) ,
2006-02-24 16:29:00 +00:00
sgi_get_start_sector ( Index [ 0 ] ) ) ;
2003-07-30 08:40:37 +00:00
if ( debug ) /* I do not understand how some disks fulfil it */
2006-02-24 16:29:00 +00:00
if ( ( sgi_get_num_sectors ( 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 ( Index [ 0 ] ) , lastblock ) ;
2003-07-30 08:40:37 +00:00
lastblock = sgi_get_num_sectors ( Index [ 0 ] ) ;
2006-02-24 16:29:00 +00:00
} else {
2003-07-30 08:40:37 +00:00
if ( verbose )
2006-02-24 16:29:00 +00:00
printf ( _ ( " One Partition (#11) should cover the entire disk. \n " ) ) ;
if ( debug > 2 )
printf ( " sysid=%d \t partition=%d \n " ,
sgi_get_sysid ( Index [ 0 ] ) , Index [ 0 ] + 1 ) ;
}
for ( i = 1 , start = 0 ; i < sortcount ; i + + ) {
int cylsize = sgi_get_nsect ( ) * sgi_get_ntrks ( ) ;
if ( ( sgi_get_start_sector ( 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 ( 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 ( Index [ i ] ) = = ENTIRE_DISK ) continue ;
if ( start > sgi_get_start_sector ( 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 ( Index [ i ] ) ) ;
if ( gap > 0 ) gap = - gap ;
if ( gap = = 0 ) gap = - 1 ;
}
if ( start < sgi_get_start_sector ( Index [ i ] ) ) {
if ( verbose )
printf ( _ ( " Unused gap of %8u sectors - sectors %8u-%u \n " ) ,
sgi_get_start_sector ( Index [ i ] ) - start ,
start , sgi_get_start_sector ( Index [ i ] ) - 1 ) ;
gap + = sgi_get_start_sector ( Index [ i ] ) - start ;
add2freelist ( start , sgi_get_start_sector ( Index [ i ] ) ) ;
}
start = sgi_get_start_sector ( Index [ i ] )
+ sgi_get_num_sectors ( Index [ i ] ) ;
if ( debug > 1 ) {
if ( verbose )
printf ( " %2d:%12d \t %12d \t %12d \n " , Index [ i ] ,
sgi_get_start_sector ( Index [ i ] ) ,
sgi_get_num_sectors ( Index [ i ] ) ,
sgi_get_sysid ( Index [ i ] ) ) ;
}
}
if ( start < lastblock ) {
2003-07-30 08:40:37 +00:00
if ( verbose )
2006-02-24 16:29:00 +00:00
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_num_sectors ( sgi_get_bootpartition ( ) ) ) {
printf ( _ ( " \n The boot partition does not exist. \n " ) ) ;
}
if ( ! sgi_get_num_sectors ( sgi_get_swappartition ( ) ) ) {
printf ( _ ( " \n The swap partition does not exist. \n " ) ) ;
} else {
if ( ( sgi_get_sysid ( sgi_get_swappartition ( ) ) ! = SGI_SWAP )
& & ( sgi_get_sysid ( sgi_get_swappartition ( ) ) ! = LINUX_SWAP ) )
printf ( _ ( " \n The swap partition has no swap type. \n " ) ) ;
}
if ( sgi_check_bootfile ( " /unix " ) )
printf ( _ ( " \t You have chosen an unusual boot file name. \n " ) ) ;
2002-11-26 22:00:21 +00:00
}
2006-02-24 16:29:00 +00:00
return ( gap > 0 ) ? 1 : ( gap = = 0 ) ? 0 : - 1 ;
2002-11-26 22:00:21 +00:00
}
static int
2006-02-24 16:29:00 +00:00
sgi_gaps ( void )
{
/*
* 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 ( 0 ) ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
sgi_change_sysid ( int i , int sys )
2002-11-26 22:00:21 +00:00
{
2006-02-24 16:29:00 +00:00
if ( sgi_get_num_sectors ( i ) = = 0 ) { /* caught already before, ... */
printf ( _ ( " Sorry You may change the Tag of non-empty partitions. \n " ) ) ;
return ;
}
if ( ( ( sys ! = ENTIRE_DISK ) & & ( sys ! = SGI_VOLHDR ) )
& & ( sgi_get_start_sector ( 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 ;
}
sgilabel - > partitions [ i ] . id = SGI_SSWAP32 ( sys ) ;
2002-11-26 22:00:21 +00:00
}
/* returns partition index of first entry marked as entire disk */
static int
2006-02-24 16:29:00 +00:00
sgi_entire ( void )
{
int i ;
2003-07-30 08:40:37 +00:00
2006-02-24 16:29:00 +00:00
for ( i = 0 ; i < 16 ; i + + )
if ( sgi_get_sysid ( i ) = = SGI_VOLUME )
return i ;
return - 1 ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
sgi_set_partition ( int i , unsigned int start , unsigned int length , int sys )
{
sgilabel - > partitions [ i ] . id = SGI_SSWAP32 ( sys ) ;
sgilabel - > partitions [ i ] . num_sectors = SGI_SSWAP32 ( length ) ;
sgilabel - > partitions [ i ] . start_sector = SGI_SSWAP32 ( start ) ;
set_changed ( i ) ;
if ( sgi_gaps ( ) < 0 ) /* rebuild freelist */
printf ( _ ( " Do You know, You got a partition overlap on the disk? \n " ) ) ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
sgi_set_entire ( void )
{
int n ;
2003-07-30 08:40:37 +00:00
2006-02-24 16:29:00 +00:00
for ( n = 10 ; n < partitions ; n + + ) {
if ( ! sgi_get_num_sectors ( n ) ) {
sgi_set_partition ( n , 0 , sgi_get_lastblock ( ) , SGI_VOLUME ) ;
break ;
}
2002-11-26 22:00:21 +00:00
}
}
static void
sgi_set_volhdr ( void )
{
2006-02-24 16:29:00 +00:00
int n ;
for ( n = 8 ; n < partitions ; n + + ) {
if ( ! sgi_get_num_sectors ( n ) ) {
/*
* 5 cylinders is an arbitrary value I like
* IRIX 5.3 stored files in the volume header
* ( like sash , symmon , fx , ide ) with ca . 3200
* sectors .
*/
if ( heads * sectors * 5 < sgi_get_lastblock ( ) )
sgi_set_partition ( n , 0 , heads * sectors * 5 , SGI_VOLHDR ) ;
break ;
}
2002-11-26 22:00:21 +00:00
}
}
static void
2006-02-24 16:29:00 +00:00
sgi_delete_partition ( int i )
2002-11-26 22:00:21 +00:00
{
2006-02-24 16:29:00 +00:00
sgi_set_partition ( i , 0 , 0 , 0 ) ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
sgi_add_partition ( 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 ( n ) ) {
printf ( _ ( " Partition %d is already defined. Delete "
" it before re-adding it. \n " ) , n + 1 ) ;
return ;
}
if ( ( sgi_entire ( ) = = - 1 ) & & ( sys ! = SGI_VOLUME ) ) {
printf ( _ ( " Attempting to generate entire disk entry automatically. \n " ) ) ;
sgi_set_entire ( ) ;
sgi_set_volhdr ( ) ;
}
if ( ( sgi_gaps ( ) = = 0 ) & & ( sys ! = SGI_VOLUME ) ) {
printf ( _ ( " The entire disk is already covered with partitions. \n " ) ) ;
return ;
}
if ( sgi_gaps ( ) < 0 ) {
printf ( _ ( " You got a partition overlap on the disk. Fix it first! \n " ) ) ;
return ;
2002-11-26 22:00:21 +00:00
}
2006-02-24 16:29:00 +00:00
snprintf ( mesg , sizeof ( mesg ) , _ ( " First %s " ) , str_units ( SINGULAR ) ) ;
while ( 1 ) {
if ( sys = = SGI_VOLUME ) {
last = sgi_get_lastblock ( ) ;
first = read_int ( 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 ( 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 ( scround ( first ) , scround ( last ) - 1 , scround ( last ) - 1 ,
scround ( first ) , mesg ) + 1 ;
2002-11-26 22:00:21 +00:00
if ( display_in_cyl_units )
2006-02-24 16:29:00 +00:00
last * = units_per_sector ;
2002-11-26 22:00:21 +00:00
else
2006-02-24 16:29:00 +00:00
last = last ; /* align to cylinder if You know how ... */
if ( ( sys = = SGI_VOLUME ) & & ( first ! = 0 | | last ! = sgi_get_lastblock ( ) ) )
printf ( _ ( " It is highly recommended that eleventh partition \n "
" covers the entire disk and is of type `SGI volume' \n " ) ) ;
sgi_set_partition ( n , first , last - first , sys ) ;
2002-11-26 22:00:21 +00:00
}
2003-07-30 08:40:37 +00:00
# ifdef CONFIG_FEATURE_FDISK_ADVANCED
2002-11-26 22:00:21 +00:00
static void
create_sgilabel ( void )
{
2006-02-24 16:29:00 +00:00
struct hd_geometry geometry ;
struct {
unsigned int start ;
unsigned int nsect ;
int sysid ;
} old [ 4 ] ;
int i = 0 ;
long longsectors ; /* the number of sectors on the device */
int res ; /* the result from the ioctl */
int sec_fac ; /* the sector factor */
sec_fac = sector_size / 512 ; /* determine the sector factor */
fprintf ( stderr ,
_ ( " Building a new SGI disklabel. Changes will remain in memory only, \n "
" until you decide to write them. After that, of course, the previous \n "
" content will be unrecoverably lost. \n \n " ) ) ;
2006-05-05 16:54:40 +00:00
sgi_other_endian = ( BB_LITTLE_ENDIAN ) ;
2006-02-24 16:29:00 +00:00
res = ioctl ( fd , BLKGETSIZE , & longsectors ) ;
if ( ! ioctl ( fd , HDIO_GETGEO , & geometry ) ) {
heads = geometry . heads ;
sectors = geometry . sectors ;
if ( res = = 0 ) {
/* the get device size ioctl was successful */
cylinders = longsectors / ( heads * sectors ) ;
cylinders / = sec_fac ;
} else {
/* otherwise print error and use truncated version */
cylinders = geometry . cylinders ;
fprintf ( stderr ,
_ ( " Warning: BLKGETSIZE ioctl failed on %s. "
" Using geometry cylinder value of %d. \n "
" This value may be truncated for devices "
" > 33.8 GB. \n " ) , disk_device , cylinders ) ;
}
}
for ( i = 0 ; i < 4 ; i + + ) {
old [ i ] . sysid = 0 ;
if ( valid_part_table_flag ( MBRbuffer ) ) {
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 ) ) ;
printf ( _ ( " Trying to keep parameters of partition %d. \n " ) , i ) ;
if ( debug )
printf ( _ ( " ID=%02x \t START=%d \t LENGTH=%d \n " ) ,
old [ i ] . sysid , old [ i ] . start , old [ i ] . nsect ) ;
}
}
}
memset ( MBRbuffer , 0 , sizeof ( MBRbuffer ) ) ;
sgilabel - > magic = SGI_SSWAP32 ( SGI_LABEL_MAGIC ) ;
sgilabel - > boot_part = SGI_SSWAP16 ( 0 ) ;
sgilabel - > swap_part = SGI_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 = SGI_SSWAP16 ( geometry . cylinders ) ;
sgilabel - > devparam . head_vol0 = SGI_SSWAP16 ( 0 ) ;
sgilabel - > devparam . ntrks = SGI_SSWAP16 ( geometry . heads ) ;
2002-11-26 22:00:21 +00:00
/* tracks/cylinder (heads) */
2006-02-24 16:29:00 +00:00
sgilabel - > devparam . cmd_tag_queue_depth = ( 0 ) ;
sgilabel - > devparam . unused0 = ( 0 ) ;
sgilabel - > devparam . unused1 = SGI_SSWAP16 ( 0 ) ;
sgilabel - > devparam . nsect = SGI_SSWAP16 ( geometry . sectors ) ;
2002-11-26 22:00:21 +00:00
/* sectors/track */
2006-02-24 16:29:00 +00:00
sgilabel - > devparam . bytes = SGI_SSWAP16 ( 512 ) ;
sgilabel - > devparam . ilfact = SGI_SSWAP16 ( 1 ) ;
sgilabel - > devparam . flags = SGI_SSWAP32 ( TRACK_FWD |
2002-11-26 22:00:21 +00:00
IGNORE_ERRORS | RESEEK ) ;
2006-02-24 16:29:00 +00:00
sgilabel - > devparam . datarate = SGI_SSWAP32 ( 0 ) ;
sgilabel - > devparam . retries_on_error = SGI_SSWAP32 ( 1 ) ;
sgilabel - > devparam . ms_per_word = SGI_SSWAP32 ( 0 ) ;
sgilabel - > devparam . xylogics_gap1 = SGI_SSWAP16 ( 0 ) ;
sgilabel - > devparam . xylogics_syncdelay = SGI_SSWAP16 ( 0 ) ;
sgilabel - > devparam . xylogics_readdelay = SGI_SSWAP16 ( 0 ) ;
sgilabel - > devparam . xylogics_gap2 = SGI_SSWAP16 ( 0 ) ;
sgilabel - > devparam . xylogics_readgate = SGI_SSWAP16 ( 0 ) ;
sgilabel - > devparam . xylogics_writecont = SGI_SSWAP16 ( 0 ) ;
memset ( & ( sgilabel - > directory ) , 0 , sizeof ( struct volume_directory ) * 15 ) ;
memset ( & ( sgilabel - > partitions ) , 0 , sizeof ( struct sgi_partition ) * 16 ) ;
2006-02-25 03:46:10 +00:00
current_label_type = label_sgi ;
2006-02-24 16:29:00 +00:00
partitions = 16 ;
sgi_volumes = 15 ;
sgi_set_entire ( ) ;
sgi_set_volhdr ( ) ;
for ( i = 0 ; i < 4 ; i + + ) {
if ( old [ i ] . sysid ) {
sgi_set_partition ( i , old [ i ] . start , old [ i ] . nsect , old [ i ] . sysid ) ;
}
}
2002-11-26 22:00:21 +00:00
}
static void
sgi_set_xcyl ( void )
{
2006-02-24 16:29:00 +00:00
/* do nothing in the beginning */
2002-11-26 22:00:21 +00:00
}
2003-07-30 08:40:37 +00:00
# endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2002-11-26 22:00:21 +00:00
/* _____________________________________________________________
*/
2003-07-30 08:40:37 +00:00
static sgiinfo *
2002-11-26 22:00:21 +00:00
fill_sgiinfo ( void )
{
2006-02-24 16:29:00 +00:00
sgiinfo * info = calloc ( 1 , sizeof ( sgiinfo ) ) ;
info - > magic = SGI_SSWAP32 ( SGI_INFO_MAGIC ) ;
info - > b1 = SGI_SSWAP32 ( - 1 ) ;
info - > b2 = SGI_SSWAP16 ( - 1 ) ;
info - > b3 = SGI_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 = SGI_SSWAP16 ( 18 * 256 + 16 ) ;
strcpy ( ( char * ) info - > installer , " Sfx version 5.3, Oct 18, 1994 " ) ;
return info ;
2002-11-26 22:00:21 +00:00
}
# endif /* SGI_LABEL */
# ifdef CONFIG_FEATURE_SUN_LABEL
/*
* 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
*/
2006-02-24 16:29:00 +00:00
static int sun_other_endian ;
static int scsi_disk ;
static int floppy ;
2002-11-26 22:00:21 +00:00
# ifndef IDE0_MAJOR
# define IDE0_MAJOR 3
# endif
# ifndef IDE1_MAJOR
# define IDE1_MAJOR 22
# endif
2003-07-30 08:40:37 +00:00
2006-02-24 16:29:00 +00:00
static void
guess_device_type ( void )
{
2002-11-26 22:00:21 +00:00
struct stat bootstat ;
2006-02-24 16:29:00 +00:00
if ( fstat ( fd , & bootstat ) < 0 ) {
2002-11-26 22:00:21 +00:00
scsi_disk = 0 ;
floppy = 0 ;
} else if ( S_ISBLK ( bootstat . st_mode )
2006-02-24 16:29:00 +00:00
& & ( major ( bootstat . st_rdev ) = = IDE0_MAJOR | |
major ( bootstat . st_rdev ) = = IDE1_MAJOR ) ) {
2002-11-26 22:00:21 +00:00
scsi_disk = 0 ;
floppy = 0 ;
} else if ( S_ISBLK ( bootstat . st_mode )
2006-02-24 16:29:00 +00:00
& & major ( bootstat . st_rdev ) = = FLOPPY_MAJOR ) {
2002-11-26 22:00:21 +00:00
scsi_disk = 0 ;
floppy = 1 ;
} else {
scsi_disk = 1 ;
floppy = 0 ;
}
}
static const struct systypes sun_sys_types [ ] = {
2006-02-24 16:29:00 +00:00
{ " \x00 " " Empty " } , /* 0 */
{ " \x01 " " Boot " } , /* 1 */
{ " \x02 " " SunOS root " } , /* 2 */
{ " \x03 " " SunOS swap " } , /* SUNOS_SWAP */
{ " \x04 " " SunOS usr " } , /* 4 */
{ " \x05 " " Whole disk " } , /* WHOLE_DISK */
{ " \x06 " " SunOS stand " } , /* 6 */
{ " \x07 " " SunOS var " } , /* 7 */
{ " \x08 " " SunOS home " } , /* 8 */
{ " \x82 " " Linux swap " } , /* LINUX_SWAP */
{ " \x83 " " Linux native " } , /* LINUX_NATIVE */
{ " \x8e " " Linux LVM " } , /* 0x8e */
2002-11-26 22:00:21 +00:00
/* New (2.2.x) raid partition with autodetect using persistent superblock */
2006-02-24 16:29:00 +00:00
{ " \xfd " " Linux raid autodetect " } , /* 0xfd */
{ NULL }
2002-11-26 22:00:21 +00:00
} ;
static void
2006-02-24 16:29:00 +00:00
set_sun_partition ( int i , uint start , uint stop , int sysid )
{
2002-11-26 22:00:21 +00:00
sunlabel - > infos [ i ] . id = sysid ;
sunlabel - > partitions [ i ] . start_cylinder =
SUN_SSWAP32 ( start / ( heads * sectors ) ) ;
sunlabel - > partitions [ i ] . num_sectors =
SUN_SSWAP32 ( stop - start ) ;
set_changed ( i ) ;
}
static int
2006-02-24 16:29:00 +00:00
check_sun_label ( void )
{
2002-11-26 22:00:21 +00:00
unsigned short * ush ;
int csum ;
2006-02-24 16:29:00 +00:00
if ( sunlabel - > magic ! = SUN_LABEL_MAGIC
& & sunlabel - > magic ! = SUN_LABEL_MAGIC_SWAPPED ) {
2006-02-25 03:46:10 +00:00
current_label_type = label_dos ;
2002-11-26 22:00:21 +00:00
sun_other_endian = 0 ;
return 0 ;
}
sun_other_endian = ( sunlabel - > magic = = SUN_LABEL_MAGIC_SWAPPED ) ;
ush = ( ( unsigned short * ) ( sunlabel + 1 ) ) - 1 ;
for ( csum = 0 ; ush > = ( unsigned short * ) sunlabel ; ) csum ^ = * ush - - ;
if ( csum ) {
fprintf ( stderr , _ ( " Detected sun disklabel with wrong checksum. \n "
" Probably you'll have to set all the values, \n "
" e.g. heads, sectors, cylinders and partitions \n "
" or force a fresh label (s command in main menu) \n " ) ) ;
} else {
heads = SUN_SSWAP16 ( sunlabel - > ntrks ) ;
cylinders = SUN_SSWAP16 ( sunlabel - > ncyl ) ;
sectors = SUN_SSWAP16 ( sunlabel - > nsect ) ;
}
update_units ( ) ;
2006-02-25 03:46:10 +00:00
current_label_type = label_sun ;
2002-11-26 22:00:21 +00:00
partitions = 8 ;
return 1 ;
}
static const struct sun_predefined_drives {
const char * vendor ;
const char * model ;
unsigned short sparecyl ;
unsigned short ncyl ;
unsigned short nacyl ;
unsigned short pcylcount ;
unsigned short ntrks ;
unsigned short nsect ;
unsigned short rspeed ;
} sun_drives [ ] = {
2006-02-24 16:29:00 +00:00
{ " Quantum " , " ProDrive 80S " , 1 , 832 , 2 , 834 , 6 , 34 , 3662 } ,
{ " Quantum " , " ProDrive 105S " , 1 , 974 , 2 , 1019 , 6 , 35 , 3662 } ,
{ " CDC " , " Wren IV 94171-344 " , 3 , 1545 , 2 , 1549 , 9 , 46 , 3600 } ,
{ " IBM " , " DPES-31080 " , 0 , 4901 , 2 , 4903 , 4 , 108 , 5400 } ,
{ " IBM " , " DORS-32160 " , 0 , 1015 , 2 , 1017 , 67 , 62 , 5400 } ,
{ " IBM " , " DNES-318350 " , 0 , 11199 , 2 , 11474 , 10 , 320 , 7200 } ,
{ " SEAGATE " , " ST34371 " , 0 , 3880 , 2 , 3882 , 16 , 135 , 7228 } ,
{ " " , " SUN0104 " , 1 , 974 , 2 , 1019 , 6 , 35 , 3662 } ,
{ " " , " SUN0207 " , 4 , 1254 , 2 , 1272 , 9 , 36 , 3600 } ,
{ " " , " SUN0327 " , 3 , 1545 , 2 , 1549 , 9 , 46 , 3600 } ,
{ " " , " SUN0340 " , 0 , 1538 , 2 , 1544 , 6 , 72 , 4200 } ,
{ " " , " SUN0424 " , 2 , 1151 , 2 , 2500 , 9 , 80 , 4400 } ,
{ " " , " SUN0535 " , 0 , 1866 , 2 , 2500 , 7 , 80 , 5400 } ,
{ " " , " SUN0669 " , 5 , 1614 , 2 , 1632 , 15 , 54 , 3600 } ,
{ " " , " SUN1.0G " , 5 , 1703 , 2 , 1931 , 15 , 80 , 3597 } ,
{ " " , " SUN1.05 " , 0 , 2036 , 2 , 2038 , 14 , 72 , 5400 } ,
{ " " , " SUN1.3G " , 6 , 1965 , 2 , 3500 , 17 , 80 , 5400 } ,
{ " " , " SUN2.1G " , 0 , 2733 , 2 , 3500 , 19 , 80 , 5400 } ,
{ " IOMEGA " , " Jaz " , 0 , 1019 , 2 , 1021 , 64 , 32 , 5394 } ,
2002-11-26 22:00:21 +00:00
} ;
static const struct sun_predefined_drives *
2006-02-24 16:29:00 +00:00
sun_autoconfigure_scsi ( void )
{
const struct sun_predefined_drives * p = NULL ;
2002-11-26 22:00:21 +00:00
# ifdef SCSI_IOCTL_GET_IDLUN
2006-02-24 16:29:00 +00:00
unsigned int id [ 2 ] ;
char buffer [ 2048 ] ;
char buffer2 [ 2048 ] ;
FILE * pfd ;
char * vendor ;
char * model ;
char * q ;
int i ;
if ( ! ioctl ( fd , SCSI_IOCTL_GET_IDLUN , & id ) ) {
sprintf ( buffer ,
" Host: scsi%d Channel: %02d Id: %02d Lun: %02d \n " ,
2002-11-26 22:00:21 +00:00
#if 0
2006-02-24 16:29:00 +00:00
( ( id [ 0 ] > > 24 ) & 0xff ) - /*PROC_SCSI_SCSI+PROC_SCSI_FILE*/ 33 ,
2002-11-26 22:00:21 +00:00
# else
2006-02-24 16:29:00 +00:00
/* This is very wrong (works only if you have one HBA),
but I haven ' t found a way how to get hostno
from the current kernel */
0 ,
# endif
( id [ 0 ] > > 16 ) & 0xff ,
id [ 0 ] & 0xff ,
( id [ 0 ] > > 8 ) & 0xff
) ;
pfd = fopen ( " /proc/scsi/scsi " , " r " ) ;
if ( pfd ) {
while ( fgets ( buffer2 , 2048 , pfd ) ) {
if ( ! strcmp ( buffer , buffer2 ) ) {
if ( fgets ( buffer2 , 2048 , pfd ) ) {
q = strstr ( buffer2 , " Vendor: " ) ;
if ( q ) {
q + = 8 ;
vendor = q ;
q = strstr ( q , " " ) ;
* q + + = 0 ; /* truncate vendor name */
q = strstr ( q , " Model: " ) ;
if ( q ) {
* q = 0 ;
q + = 7 ;
model = q ;
q = strstr ( q , " Rev: " ) ;
if ( q ) {
* q = 0 ;
for ( i = 0 ; i < SIZE ( sun_drives ) ; i + + ) {
if ( * sun_drives [ i ] . vendor & & strcasecmp ( sun_drives [ i ] . vendor , vendor ) )
continue ;
if ( ! strstr ( model , sun_drives [ i ] . model ) )
continue ;
printf ( _ ( " Autoconfigure found a %s%s%s \n " ) , sun_drives [ i ] . vendor , ( * sun_drives [ i ] . vendor ) ? " " : " " , sun_drives [ i ] . model ) ;
p = sun_drives + i ;
break ;
}
}
}
}
}
2002-11-26 22:00:21 +00:00
break ;
}
}
2006-02-24 16:29:00 +00:00
fclose ( pfd ) ;
2002-11-26 22:00:21 +00:00
}
}
# endif
2006-02-24 16:29:00 +00:00
return p ;
2002-11-26 22:00:21 +00:00
}
2006-02-24 16:29:00 +00:00
static void
create_sunlabel ( void )
2002-11-26 22:00:21 +00:00
{
struct hd_geometry geometry ;
unsigned int ndiv ;
int i ;
unsigned char c ;
const struct sun_predefined_drives * p = NULL ;
fprintf ( stderr ,
2006-02-24 16:29:00 +00:00
_ ( " Building a new sun disklabel. Changes will remain in memory only, \n "
" until you decide to write them. After that, of course, the previous \n "
" content won't be recoverable. \n \n " ) ) ;
2006-05-05 16:54:40 +00:00
sun_other_endian = BB_LITTLE_ENDIAN ;
2002-11-26 22:00:21 +00:00
memset ( MBRbuffer , 0 , sizeof ( MBRbuffer ) ) ;
sunlabel - > magic = SUN_SSWAP16 ( SUN_LABEL_MAGIC ) ;
if ( ! floppy ) {
2006-02-24 16:29:00 +00:00
puts ( _ ( " Drive type \n "
2002-11-26 22:00:21 +00:00
" ? auto configure \n "
" 0 custom (with hardware detected defaults) " ) ) ;
2006-02-24 16:29:00 +00:00
for ( i = 0 ; i < SIZE ( sun_drives ) ; i + + ) {
printf ( " %c %s%s%s \n " ,
i + ' a ' , sun_drives [ i ] . vendor ,
( * sun_drives [ i ] . vendor ) ? " " : " " ,
sun_drives [ i ] . model ) ;
}
while ( 1 ) {
c = read_char ( _ ( " Select type (? for auto, 0 for custom): " ) ) ;
if ( c > = ' a ' & & c < ' a ' + SIZE ( sun_drives ) ) {
p = sun_drives + c - ' a ' ;
break ;
} else if ( c > = ' A ' & & c < ' A ' + SIZE ( sun_drives ) ) {
p = sun_drives + c - ' A ' ;
break ;
} else if ( c = = ' 0 ' ) {
break ;
} else if ( c = = ' ? ' & & scsi_disk ) {
p = sun_autoconfigure_scsi ( ) ;
if ( ! p )
printf ( _ ( " Autoconfigure failed. \n " ) ) ;
else
break ;
}
2002-11-26 22:00:21 +00:00
}
}
if ( ! p | | floppy ) {
2006-02-24 16:29:00 +00:00
if ( ! ioctl ( fd , HDIO_GETGEO , & geometry ) ) {
heads = geometry . heads ;
sectors = geometry . sectors ;
cylinders = geometry . cylinders ;
} else {
heads = 0 ;
sectors = 0 ;
cylinders = 0 ;
}
if ( floppy ) {
sunlabel - > nacyl = 0 ;
sunlabel - > pcylcount = SUN_SSWAP16 ( cylinders ) ;
sunlabel - > rspeed = SUN_SSWAP16 ( 300 ) ;
sunlabel - > ilfact = SUN_SSWAP16 ( 1 ) ;
sunlabel - > sparecyl = 0 ;
} else {
heads = read_int ( 1 , heads , 1024 , 0 , _ ( " Heads " ) ) ;
sectors = read_int ( 1 , sectors , 1024 , 0 , _ ( " Sectors/track " ) ) ;
2002-11-26 22:00:21 +00:00
if ( cylinders )
2006-02-24 16:29:00 +00:00
cylinders = read_int ( 1 , cylinders - 2 , 65535 , 0 , _ ( " Cylinders " ) ) ;
2002-11-26 22:00:21 +00:00
else
2006-02-24 16:29:00 +00:00
cylinders = read_int ( 1 , 0 , 65535 , 0 , _ ( " Cylinders " ) ) ;
sunlabel - > nacyl = SUN_SSWAP16 ( read_int ( 0 , 2 , 65535 , 0 , _ ( " Alternate cylinders " ) ) ) ;
sunlabel - > pcylcount = SUN_SSWAP16 ( read_int ( 0 , cylinders + SUN_SSWAP16 ( sunlabel - > nacyl ) , 65535 , 0 , _ ( " Physical cylinders " ) ) ) ;
sunlabel - > rspeed = SUN_SSWAP16 ( read_int ( 1 , 5400 , 100000 , 0 , _ ( " Rotation speed (rpm) " ) ) ) ;
sunlabel - > ilfact = SUN_SSWAP16 ( read_int ( 1 , 1 , 32 , 0 , _ ( " Interleave factor " ) ) ) ;
sunlabel - > sparecyl = SUN_SSWAP16 ( read_int ( 0 , 0 , sectors , 0 , _ ( " Extra sectors per cylinder " ) ) ) ;
}
2002-11-26 22:00:21 +00:00
} else {
2006-02-24 16:29:00 +00:00
sunlabel - > sparecyl = SUN_SSWAP16 ( p - > sparecyl ) ;
sunlabel - > ncyl = SUN_SSWAP16 ( p - > ncyl ) ;
sunlabel - > nacyl = SUN_SSWAP16 ( p - > nacyl ) ;
sunlabel - > pcylcount = SUN_SSWAP16 ( p - > pcylcount ) ;
sunlabel - > ntrks = SUN_SSWAP16 ( p - > ntrks ) ;
sunlabel - > nsect = SUN_SSWAP16 ( p - > nsect ) ;
sunlabel - > rspeed = SUN_SSWAP16 ( p - > rspeed ) ;
sunlabel - > ilfact = SUN_SSWAP16 ( 1 ) ;
cylinders = p - > ncyl ;
heads = p - > ntrks ;
sectors = p - > nsect ;
puts ( _ ( " You may change all the disk params from the x menu " ) ) ;
2002-11-26 22:00:21 +00:00
}
2005-12-02 10:06:04 +00:00
snprintf ( ( char * ) ( sunlabel - > info ) , sizeof ( sunlabel - > info ) ,
2006-02-24 16:29:00 +00:00
" %s%s%s cyl %d alt %d hd %d sec %d " ,
p ? p - > vendor : " " , ( p & & * p - > vendor ) ? " " : " " ,
p ? p - > model : ( floppy ? _ ( " 3,5 \" floppy " ) : _ ( " Linux custom " ) ) ,
2002-11-26 22:00:21 +00:00
cylinders , SUN_SSWAP16 ( sunlabel - > nacyl ) , heads , sectors ) ;
sunlabel - > ntrks = SUN_SSWAP16 ( heads ) ;
sunlabel - > nsect = SUN_SSWAP16 ( sectors ) ;
sunlabel - > ncyl = SUN_SSWAP16 ( cylinders ) ;
if ( floppy )
2006-02-24 16:29:00 +00:00
set_sun_partition ( 0 , 0 , cylinders * heads * sectors , LINUX_NATIVE ) ;
2002-11-26 22:00:21 +00:00
else {
2006-02-24 16:29:00 +00:00
if ( cylinders * heads * sectors > = 150 * 2048 ) {
ndiv = cylinders - ( 50 * 2048 / ( heads * sectors ) ) ; /* 50M swap */
} else
ndiv = cylinders * 2 / 3 ;
set_sun_partition ( 0 , 0 , ndiv * heads * sectors , LINUX_NATIVE ) ;
set_sun_partition ( 1 , ndiv * heads * sectors , cylinders * heads * sectors , LINUX_SWAP ) ;
sunlabel - > infos [ 1 ] . flags | = 0x01 ; /* Not mountable */
2002-11-26 22:00:21 +00:00
}
set_sun_partition ( 2 , 0 , cylinders * heads * sectors , WHOLE_DISK ) ;
{
unsigned short * ush = ( unsigned short * ) sunlabel ;
unsigned short csum = 0 ;
2006-02-24 16:29:00 +00:00
while ( ush < ( unsigned short * ) ( & sunlabel - > csum ) )
2002-11-26 22:00:21 +00:00
csum ^ = * ush + + ;
sunlabel - > csum = csum ;
}
set_all_unchanged ( ) ;
set_changed ( 0 ) ;
get_boot ( create_empty_sun ) ;
}
static void
2006-02-24 16:29:00 +00:00
toggle_sunflags ( int i , unsigned char mask )
{
2002-11-26 22:00:21 +00:00
if ( sunlabel - > infos [ i ] . flags & mask )
sunlabel - > infos [ i ] . flags & = ~ mask ;
2006-02-24 16:29:00 +00:00
else
sunlabel - > infos [ i ] . flags | = mask ;
2002-11-26 22:00:21 +00:00
set_changed ( i ) ;
}
static void
2006-02-24 16:29:00 +00:00
fetch_sun ( uint * starts , uint * lens , uint * start , uint * stop )
{
2002-11-26 22:00:21 +00:00
int i , continuous = 1 ;
2006-02-24 16:29:00 +00:00
* start = 0 ;
* stop = cylinders * heads * sectors ;
2002-11-26 22:00:21 +00:00
for ( i = 0 ; i < partitions ; i + + ) {
if ( sunlabel - > partitions [ i ] . num_sectors
2006-02-24 16:29:00 +00:00
& & sunlabel - > infos [ i ] . id
& & sunlabel - > infos [ i ] . id ! = WHOLE_DISK ) {
2002-11-26 22:00:21 +00:00
starts [ i ] = SUN_SSWAP32 ( sunlabel - > partitions [ i ] . start_cylinder ) * heads * sectors ;
lens [ i ] = SUN_SSWAP32 ( sunlabel - > partitions [ i ] . num_sectors ) ;
if ( continuous ) {
if ( starts [ i ] = = * start )
* start + = lens [ i ] ;
else if ( starts [ i ] + lens [ i ] > = * stop )
* stop = starts [ i ] ;
else
continuous = 0 ;
/* There will be probably more gaps
than one , so lets check afterwards */
}
} else {
starts [ i ] = 0 ;
lens [ i ] = 0 ;
}
}
}
static uint * verify_sun_starts ;
static int
2006-02-24 16:29:00 +00:00
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 ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
verify_sun ( void )
{
uint starts [ 8 ] , lens [ 8 ] , start , stop ;
int i , j , k , starto , endo ;
int array [ 8 ] ;
verify_sun_starts = starts ;
fetch_sun ( starts , lens , & start , & stop ) ;
for ( k = 0 ; k < 7 ; k + + ) {
for ( i = 0 ; i < 8 ; i + + ) {
if ( k & & ( lens [ i ] % ( heads * sectors ) ) ) {
printf ( _ ( " Partition %d doesn't end on cylinder boundary \n " ) , i + 1 ) ;
}
if ( lens [ i ] ) {
for ( j = 0 ; j < i ; j + + )
if ( lens [ j ] ) {
if ( starts [ j ] = = starts [ i ] + lens [ i ] ) {
starts [ j ] = starts [ i ] ; lens [ j ] + = lens [ i ] ;
lens [ i ] = 0 ;
} else if ( starts [ i ] = = starts [ j ] + lens [ j ] ) {
lens [ j ] + = lens [ i ] ;
lens [ i ] = 0 ;
} else if ( ! k ) {
if ( starts [ i ] < starts [ j ] + lens [ j ]
& & starts [ j ] < starts [ i ] + lens [ i ] ) {
starto = starts [ i ] ;
if ( starts [ j ] > starto )
starto = starts [ j ] ;
endo = starts [ i ] + lens [ i ] ;
if ( starts [ j ] + lens [ j ] < endo )
endo = starts [ j ] + lens [ j ] ;
printf ( _ ( " Partition %d overlaps with others in "
" sectors %d-%d \n " ) , i + 1 , starto , endo ) ;
}
}
}
2002-11-26 22:00:21 +00:00
}
2006-02-24 16:29:00 +00:00
}
2002-11-26 22:00:21 +00:00
}
2006-02-24 16:29:00 +00:00
for ( i = 0 ; i < 8 ; i + + ) {
if ( lens [ i ] )
array [ i ] = i ;
else
array [ i ] = - 1 ;
}
qsort ( array , SIZE ( array ) , sizeof ( array [ 0 ] ) ,
( int ( * ) ( const void * , const void * ) ) verify_sun_cmp ) ;
if ( array [ 0 ] = = - 1 ) {
printf ( _ ( " No partitions defined \n " ) ) ;
return ;
}
stop = cylinders * heads * sectors ;
if ( starts [ array [ 0 ] ] )
printf ( _ ( " Unused gap - sectors 0-%d \n " ) , starts [ array [ 0 ] ] ) ;
for ( i = 0 ; i < 7 & & array [ i + 1 ] ! = - 1 ; i + + ) {
printf ( _ ( " Unused gap - sectors %d-%d \n " ) , starts [ array [ i ] ] + lens [ array [ i ] ] , starts [ array [ i + 1 ] ] ) ;
}
start = starts [ array [ i ] ] + lens [ array [ i ] ] ;
if ( start < stop )
printf ( _ ( " Unused gap - sectors %d-%d \n " ) , start , stop ) ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
add_sun_partition ( int n , int sys )
{
2002-11-26 22:00:21 +00:00
uint start , stop , stop2 ;
uint starts [ 8 ] , lens [ 8 ] ;
int whole_disk = 0 ;
char mesg [ 256 ] ;
int i , first , last ;
if ( sunlabel - > partitions [ n ] . num_sectors & & sunlabel - > infos [ n ] . id ) {
printf ( _ ( " Partition %d is already defined. Delete "
" it before re-adding it. \n " ) , n + 1 ) ;
return ;
}
fetch_sun ( starts , lens , & start , & stop ) ;
if ( stop < = start ) {
if ( n = = 2 )
whole_disk = 1 ;
else {
printf ( _ ( " Other partitions already cover the whole disk. \n Delete "
2006-02-24 16:29:00 +00:00
" some/shrink them before retry. \n " ) ) ;
2002-11-26 22:00:21 +00:00
return ;
}
}
snprintf ( mesg , sizeof ( mesg ) , _ ( " First %s " ) , str_units ( SINGULAR ) ) ;
2006-02-24 16:29:00 +00:00
while ( 1 ) {
2002-11-26 22:00:21 +00:00
if ( whole_disk )
first = read_int ( 0 , 0 , 0 , 0 , mesg ) ;
else
first = read_int ( 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 */
first = ( first + heads * sectors - 1 ) / ( heads * sectors ) ;
if ( n = = 2 & & first ! = 0 )
2006-02-24 16:29:00 +00:00
printf ( " \
2002-11-26 22:00:21 +00:00
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 + + )
2006-02-24 16:29:00 +00:00
if ( lens [ i ] & & starts [ i ] < = first & & starts [ i ] + lens [ i ] > first )
2002-11-26 22:00:21 +00:00
break ;
if ( i < partitions & & ! whole_disk ) {
if ( n = = 2 & & ! first ) {
2006-02-24 16:29:00 +00:00
whole_disk = 1 ;
break ;
2002-11-26 22:00:21 +00:00
}
printf ( _ ( " Sector %d is already allocated \n " ) , first ) ;
} else
break ;
}
stop = cylinders * heads * sectors ;
stop2 = stop ;
for ( i = 0 ; i < partitions ; i + + ) {
if ( starts [ i ] > first & & starts [ i ] < stop )
stop = starts [ i ] ;
}
snprintf ( mesg , sizeof ( mesg ) ,
2006-02-24 16:29:00 +00:00
_ ( " Last %s or +size or +sizeM or +sizeK " ) ,
str_units ( SINGULAR ) ) ;
2002-11-26 22:00:21 +00:00
if ( whole_disk )
last = read_int ( scround ( stop2 ) , scround ( stop2 ) , scround ( stop2 ) ,
0 , mesg ) ;
else if ( n = = 2 & & ! first )
last = read_int ( scround ( first ) , scround ( stop2 ) , scround ( stop2 ) ,
scround ( first ) , mesg ) ;
else
last = read_int ( 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 ) {
2006-02-24 16:29:00 +00:00
whole_disk = 1 ;
last = stop2 ;
2002-11-26 22:00:21 +00:00
} else if ( last > stop ) {
2006-02-24 16:29:00 +00:00
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 ;
2002-11-26 22:00:21 +00:00
}
} else if ( ! whole_disk & & last > stop )
last = stop ;
2006-02-24 16:29:00 +00:00
if ( whole_disk )
sys = WHOLE_DISK ;
2002-11-26 22:00:21 +00:00
set_sun_partition ( n , first , last , sys ) ;
}
static void
2006-02-24 16:29:00 +00:00
sun_delete_partition ( int i )
{
2003-07-30 08:40:37 +00:00
unsigned int nsec ;
2006-02-24 16:29:00 +00:00
if ( i = = 2
& & sunlabel - > infos [ i ] . id = = WHOLE_DISK
& & ! sunlabel - > partitions [ i ] . start_cylinder
& & ( nsec = SUN_SSWAP32 ( sunlabel - > partitions [ i ] . num_sectors ) ) = = heads * sectors * cylinders )
2002-11-26 22:00:21 +00:00
printf ( _ ( " If you want to maintain SunOS/Solaris compatibility, "
2006-02-24 16:29:00 +00:00
" consider leaving this \n "
" partition as Whole disk (5), starting at 0, with %u "
" sectors \n " ) , nsec ) ;
2002-11-26 22:00:21 +00:00
sunlabel - > infos [ i ] . id = 0 ;
sunlabel - > partitions [ i ] . num_sectors = 0 ;
}
static void
2006-02-24 16:29:00 +00:00
sun_change_sysid ( int i , int sys )
{
2002-11-26 22:00:21 +00:00
if ( sys = = LINUX_SWAP & & ! sunlabel - > partitions [ i ] . start_cylinder ) {
2006-02-24 16:29:00 +00:00
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 ;
2002-11-26 22:00:21 +00:00
}
switch ( sys ) {
case SUNOS_SWAP :
case LINUX_SWAP :
/* swaps are not mountable by default */
sunlabel - > infos [ i ] . flags | = 0x01 ;
break ;
default :
/* assume other types are mountable;
user can change it anyway */
sunlabel - > infos [ i ] . flags & = ~ 0x01 ;
break ;
}
sunlabel - > infos [ i ] . id = sys ;
}
static void
2006-02-24 16:29:00 +00:00
sun_list_table ( int xtra )
{
2002-11-26 22:00:21 +00:00
int i , w ;
w = strlen ( disk_device ) ;
if ( xtra )
printf (
_ ( " \n Disk %s (Sun disk label): %d heads, %d sectors, %d rpm \n "
" %d cylinders, %d alternate cylinders, %d physical cylinders \n "
" %d extra sects/cyl, interleave %d:1 \n "
" %s \n "
" Units = %s of %d * 512 bytes \n \n " ) ,
2006-02-24 16:29:00 +00:00
disk_device , heads , sectors , SUN_SSWAP16 ( sunlabel - > rspeed ) ,
cylinders , SUN_SSWAP16 ( sunlabel - > nacyl ) ,
SUN_SSWAP16 ( sunlabel - > pcylcount ) ,
SUN_SSWAP16 ( sunlabel - > sparecyl ) ,
SUN_SSWAP16 ( sunlabel - > ilfact ) ,
( char * ) sunlabel ,
str_units ( PLURAL ) , units_per_sector ) ;
2002-11-26 22:00:21 +00:00
else
printf (
_ ( " \n Disk %s (Sun disk label): %d heads, %d sectors, %d cylinders \n "
" Units = %s of %d * 512 bytes \n \n " ) ,
2006-02-24 16:29:00 +00:00
disk_device , heads , sectors , cylinders ,
str_units ( PLURAL ) , units_per_sector ) ;
2002-11-26 22:00:21 +00:00
printf ( _ ( " %*s Flag Start End Blocks Id System \n " ) ,
2006-02-24 16:29:00 +00:00
w + 1 , _ ( " Device " ) ) ;
2002-11-26 22:00:21 +00:00
for ( i = 0 ; i < partitions ; i + + ) {
if ( sunlabel - > partitions [ i ] . num_sectors ) {
2002-12-11 03:49:33 +00:00
uint32_t start = SUN_SSWAP32 ( sunlabel - > partitions [ i ] . start_cylinder ) * heads * sectors ;
uint32_t len = SUN_SSWAP32 ( sunlabel - > partitions [ i ] . num_sectors ) ;
2006-02-24 16:29:00 +00:00
printf ( " %s %c%c %9ld %9ld %9ld%c %2x %s \n " ,
partname ( disk_device , i + 1 , w ) , /* device */
( sunlabel - > infos [ i ] . flags & 0x01 ) ? ' u ' : ' ' , /* flags */
( sunlabel - > infos [ i ] . flags & 0x10 ) ? ' r ' : ' ' ,
( long ) scround ( start ) , /* start */
( long ) scround ( start + len ) , /* end */
( long ) len / 2 , len & 1 ? ' + ' : ' ' , /* odd flag on end */
sunlabel - > infos [ i ] . id , /* type id */
partition_type ( sunlabel - > infos [ i ] . id ) ) ; /* type name */
2002-11-26 22:00:21 +00:00
}
}
}
2003-07-30 08:40:37 +00:00
# ifdef CONFIG_FEATURE_FDISK_ADVANCED
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
sun_set_alt_cyl ( void )
{
2002-11-26 22:00:21 +00:00
sunlabel - > nacyl =
SUN_SSWAP16 ( read_int ( 0 , SUN_SSWAP16 ( sunlabel - > nacyl ) , 65535 , 0 ,
2006-02-24 16:29:00 +00:00
_ ( " Number of alternate cylinders " ) ) ) ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
sun_set_ncyl ( int cyl )
{
2002-11-26 22:00:21 +00:00
sunlabel - > ncyl = SUN_SSWAP16 ( cyl ) ;
}
static void
2006-02-24 16:29:00 +00:00
sun_set_xcyl ( void )
{
2002-11-26 22:00:21 +00:00
sunlabel - > sparecyl =
SUN_SSWAP16 ( read_int ( 0 , SUN_SSWAP16 ( sunlabel - > sparecyl ) , sectors , 0 ,
2006-02-24 16:29:00 +00:00
_ ( " Extra sectors per cylinder " ) ) ) ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
sun_set_ilfact ( void )
{
2002-11-26 22:00:21 +00:00
sunlabel - > ilfact =
SUN_SSWAP16 ( read_int ( 1 , SUN_SSWAP16 ( sunlabel - > ilfact ) , 32 , 0 ,
2006-02-24 16:29:00 +00:00
_ ( " Interleave factor " ) ) ) ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
sun_set_rspeed ( void )
{
2002-11-26 22:00:21 +00:00
sunlabel - > rspeed =
SUN_SSWAP16 ( read_int ( 1 , SUN_SSWAP16 ( sunlabel - > rspeed ) , 100000 , 0 ,
2006-02-24 16:29:00 +00:00
_ ( " Rotation speed (rpm) " ) ) ) ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
sun_set_pcylcount ( void )
{
2002-11-26 22:00:21 +00:00
sunlabel - > pcylcount =
SUN_SSWAP16 ( read_int ( 0 , SUN_SSWAP16 ( sunlabel - > pcylcount ) , 65535 , 0 ,
2006-02-24 16:29:00 +00:00
_ ( " Number of physical cylinders " ) ) ) ;
2002-11-26 22:00:21 +00:00
}
2003-07-30 08:40:37 +00:00
# endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
sun_write_table ( void )
{
2002-11-26 22:00:21 +00:00
unsigned short * ush = ( unsigned short * ) sunlabel ;
unsigned short csum = 0 ;
2006-02-24 16:29:00 +00:00
while ( ush < ( unsigned short * ) ( & sunlabel - > csum ) )
2002-11-26 22:00:21 +00:00
csum ^ = * ush + + ;
sunlabel - > csum = csum ;
if ( lseek ( fd , 0 , SEEK_SET ) < 0 )
fdisk_fatal ( unable_to_seek ) ;
if ( write ( fd , sunlabel , SECTOR_SIZE ) ! = SECTOR_SIZE )
fdisk_fatal ( unable_to_write ) ;
}
# endif /* SUN_LABEL */
/* DOS partition types */
static const struct systypes i386_sys_types [ ] = {
2006-02-24 16:29:00 +00:00
{ " \x00 " " Empty " } ,
{ " \x01 " " FAT12 " } ,
{ " \x04 " " FAT16 <32M " } ,
{ " \x05 " " Extended " } , /* DOS 3.3+ extended partition */
{ " \x06 " " FAT16 " } , /* DOS 16-bit >=32M */
{ " \x07 " " HPFS/NTFS " } , /* OS/2 IFS, eg, HPFS or NTFS or QNX */
{ " \x0a " " OS/2 Boot Manager " } , /* OS/2 Boot Manager */
{ " \x0b " " Win95 FAT32 " } ,
{ " \x0c " " Win95 FAT32 (LBA) " } , /* LBA really is `Extended Int 13h' */
{ " \x0e " " Win95 FAT16 (LBA) " } ,
{ " \x0f " " Win95 Ext'd (LBA) " } ,
{ " \x11 " " Hidden FAT12 " } ,
{ " \x12 " " Compaq diagnostics " } ,
{ " \x14 " " Hidden FAT16 <32M " } ,
{ " \x16 " " Hidden FAT16 " } ,
{ " \x17 " " Hidden HPFS/NTFS " } ,
{ " \x1b " " Hidden Win95 FAT32 " } ,
{ " \x1c " " Hidden Win95 FAT32 (LBA) " } ,
{ " \x1e " " Hidden Win95 FAT16 (LBA) " } ,
{ " \x3c " " PartitionMagic recovery " } ,
{ " \x41 " " PPC PReP Boot " } ,
{ " \x42 " " SFS " } ,
{ " \x63 " " GNU HURD or SysV " } , /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
{ " \x80 " " Old Minix " } , /* Minix 1.4a and earlier */
{ " \x81 " " Minix / old Linux " } , /* Minix 1.4b and later */
{ " \x82 " " Linux swap " } , /* also Solaris */
{ " \x83 " " Linux " } ,
{ " \x84 " " OS/2 hidden C: drive " } ,
{ " \x85 " " Linux extended " } ,
{ " \x86 " " NTFS volume set " } ,
{ " \x87 " " NTFS volume set " } ,
{ " \x8e " " Linux LVM " } ,
{ " \x9f " " BSD/OS " } , /* BSDI */
{ " \xa0 " " IBM Thinkpad hibernation " } ,
{ " \xa5 " " FreeBSD " } , /* various BSD flavours */
{ " \xa6 " " OpenBSD " } ,
{ " \xa8 " " Darwin UFS " } ,
{ " \xa9 " " NetBSD " } ,
{ " \xab " " Darwin boot " } ,
{ " \xb7 " " BSDI fs " } ,
{ " \xb8 " " BSDI swap " } ,
{ " \xbe " " Solaris boot " } ,
{ " \xeb " " BeOS fs " } ,
{ " \xee " " EFI GPT " } , /* Intel EFI GUID Partition Table */
{ " \xef " " EFI (FAT-12/16/32) " } , /* Intel EFI System Partition */
{ " \xf0 " " Linux/PA-RISC boot " } , /* Linux/PA-RISC boot loader */
{ " \xf2 " " DOS secondary " } , /* DOS 3.3+ secondary */
{ " \xfd " " Linux raid autodetect " } , /* New (2.2.x) raid partition with
autodetect using persistent
superblock */
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_WEIRD_PARTITION_TYPES
2006-02-24 16:29:00 +00:00
{ " \x02 " " XENIX root " } ,
{ " \x03 " " XENIX usr " } ,
{ " \x08 " " AIX " } , /* AIX boot (AIX -- PS/2 port) or SplitDrive */
{ " \x09 " " AIX bootable " } , /* AIX data or Coherent */
{ " \x10 " " OPUS " } ,
{ " \x18 " " AST SmartSleep " } ,
{ " \x24 " " NEC DOS " } ,
{ " \x39 " " Plan 9 " } ,
{ " \x40 " " Venix 80286 " } ,
{ " \x4d " " QNX4.x " } ,
{ " \x4e " " QNX4.x 2nd part " } ,
{ " \x4f " " QNX4.x 3rd part " } ,
{ " \x50 " " OnTrack DM " } ,
{ " \x51 " " OnTrack DM6 Aux1 " } , /* (or Novell) */
{ " \x52 " " CP/M " } , /* CP/M or Microport SysV/AT */
{ " \x53 " " OnTrack DM6 Aux3 " } ,
{ " \x54 " " OnTrackDM6 " } ,
{ " \x55 " " EZ-Drive " } ,
{ " \x56 " " Golden Bow " } ,
{ " \x5c " " Priam Edisk " } ,
{ " \x61 " " SpeedStor " } ,
{ " \x64 " " Novell Netware 286 " } ,
{ " \x65 " " Novell Netware 386 " } ,
{ " \x70 " " DiskSecure Multi-Boot " } ,
{ " \x75 " " PC/IX " } ,
{ " \x93 " " Amoeba " } ,
{ " \x94 " " Amoeba BBT " } , /* (bad block table) */
{ " \xa7 " " NeXTSTEP " } ,
{ " \xbb " " Boot Wizard hidden " } ,
{ " \xc1 " " DRDOS/sec (FAT-12) " } ,
{ " \xc4 " " DRDOS/sec (FAT-16 < 32M) " } ,
{ " \xc6 " " DRDOS/sec (FAT-16) " } ,
{ " \xc7 " " Syrinx " } ,
{ " \xda " " Non-FS data " } ,
{ " \xdb " " CP/M / CTOS / ... " } , /* CP/M or Concurrent CP/M or
2002-11-26 22:00:21 +00:00
Concurrent DOS or CTOS */
2006-02-24 16:29:00 +00:00
{ " \xde " " Dell Utility " } , /* Dell PowerEdge Server utilities */
{ " \xdf " " BootIt " } , /* BootIt EMBRM */
{ " \xe1 " " DOS access " } , /* DOS access or SpeedStor 12-bit FAT
2002-11-26 22:00:21 +00:00
extended partition */
2006-02-24 16:29:00 +00:00
{ " \xe3 " " DOS R/O " } , /* DOS R/O or SpeedStor */
{ " \xe4 " " SpeedStor " } , /* SpeedStor 16-bit FAT extended
2002-11-26 22:00:21 +00:00
partition < 1024 cyl . */
2006-02-24 16:29:00 +00:00
{ " \xf1 " " SpeedStor " } ,
{ " \xf4 " " SpeedStor " } , /* SpeedStor large partition */
{ " \xfe " " LANstep " } , /* SpeedStor >1024 cyl. or LANstep */
{ " \xff " " BBT " } , /* Xenix Bad Block Table */
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
{ 0 }
} ;
/* A valid partition table sector ends in 0x55 0xaa */
static unsigned int
2006-02-24 16:29:00 +00:00
part_table_flag ( const char * b )
{
2002-11-26 22:00:21 +00:00
return ( ( uint ) b [ 510 ] ) + ( ( ( uint ) b [ 511 ] ) < < 8 ) ;
}
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
write_part_table_flag ( char * b )
{
2002-11-26 22:00:21 +00:00
b [ 510 ] = 0x55 ;
b [ 511 ] = 0xaa ;
}
/* start_sect and nr_sects are stored little endian on all machines */
/* moreover, they are not aligned correctly */
static void
2006-02-24 16:29:00 +00:00
store4_little_endian ( unsigned char * cp , unsigned int val )
{
2002-11-26 22:00:21 +00:00
cp [ 0 ] = ( val & 0xff ) ;
cp [ 1 ] = ( ( val > > 8 ) & 0xff ) ;
cp [ 2 ] = ( ( val > > 16 ) & 0xff ) ;
cp [ 3 ] = ( ( val > > 24 ) & 0xff ) ;
}
2003-01-04 11:56:06 +00:00
# endif /* CONFIG_FEATURE_FDISK_WRITABLE */
2002-11-26 22:00:21 +00:00
static unsigned int
2006-02-24 16:29:00 +00:00
read4_little_endian ( const unsigned char * cp )
{
2002-11-26 22:00:21 +00:00
return ( uint ) ( cp [ 0 ] ) + ( ( uint ) ( cp [ 1 ] ) < < 8 )
+ ( ( uint ) ( cp [ 2 ] ) < < 16 ) + ( ( uint ) ( cp [ 3 ] ) < < 24 ) ;
}
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
set_start_sect ( struct partition * p , unsigned int start_sect )
{
2002-11-26 22:00:21 +00:00
store4_little_endian ( p - > start4 , start_sect ) ;
}
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
2004-06-28 23:50:31 +00:00
static int32_t
2006-02-24 16:29:00 +00:00
get_start_sect ( const struct partition * p )
{
2002-11-26 22:00:21 +00:00
return read4_little_endian ( p - > start4 ) ;
}
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
set_nr_sects ( struct partition * p , int32_t nr_sects )
{
2002-11-26 22:00:21 +00:00
store4_little_endian ( p - > size4 , nr_sects ) ;
}
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
2004-06-28 23:50:31 +00:00
static int32_t
2006-02-24 16:29:00 +00:00
get_nr_sects ( const struct partition * p )
{
2002-11-26 22:00:21 +00:00
return read4_little_endian ( p - > size4 ) ;
}
/* normally O_RDWR, -l option gives O_RDONLY */
static int type_open = O_RDWR ;
2006-02-24 16:29:00 +00:00
static int ext_index ; /* the prime extended partition */
static int listing ; /* no aborts for fdisk -l */
static int dos_compatible_flag = ~ 0 ;
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
static int dos_changed ;
static int nowarn ; /* no warnings for fdisk -l/-s */
# endif
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
static uint user_cylinders , user_heads , user_sectors ;
static uint pt_heads , pt_sectors ;
static uint kern_heads , kern_sectors ;
2002-11-26 22:00:21 +00:00
2004-06-28 23:50:31 +00:00
static off_t extended_offset ; /* offset of link pointers */
2002-11-26 22:00:21 +00:00
2003-07-30 08:40:37 +00:00
static unsigned long long total_number_of_sectors ;
2002-11-26 22:00:21 +00:00
static jmp_buf listingbuf ;
2006-02-24 16:29:00 +00:00
static void fdisk_fatal ( enum failure why )
{
2002-11-26 22:00:21 +00:00
const char * message ;
if ( listing ) {
close ( fd ) ;
longjmp ( listingbuf , 1 ) ;
}
switch ( why ) {
2006-02-24 16:29:00 +00:00
case unable_to_open :
message = " Unable to open %s \n " ;
break ;
case unable_to_read :
message = " Unable to read %s \n " ;
break ;
case unable_to_seek :
message = " Unable to seek on %s \n " ;
break ;
case unable_to_write :
message = " Unable to write %s \n " ;
break ;
case ioctl_error :
message = " BLKGETSIZE ioctl failed on %s \n " ;
break ;
default :
message = " Fatal error \n " ;
2002-11-26 22:00:21 +00:00
}
fputc ( ' \n ' , stderr ) ;
fprintf ( stderr , message , disk_device ) ;
exit ( 1 ) ;
}
static void
2006-02-24 16:29:00 +00:00
seek_sector ( off_t secno )
{
2004-03-30 09:21:54 +00:00
off_t offset = secno * sector_size ;
if ( lseek ( fd , offset , SEEK_SET ) = = ( off_t ) - 1 )
2002-11-26 22:00:21 +00:00
fdisk_fatal ( unable_to_seek ) ;
}
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
write_sector ( off_t secno , char * buf )
{
2002-11-26 22:00:21 +00:00
seek_sector ( secno ) ;
if ( write ( fd , buf , sector_size ) ! = sector_size )
fdisk_fatal ( unable_to_write ) ;
}
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
/* Allocate a buffer and read a partition table sector */
static void
2006-02-24 16:29:00 +00:00
read_pte ( struct pte * pe , off_t offset )
{
2002-11-26 22:00:21 +00:00
pe - > offset = offset ;
pe - > sectorbuffer = ( char * ) xmalloc ( sector_size ) ;
2003-01-04 11:56:06 +00:00
seek_sector ( offset ) ;
if ( read ( fd , pe - > sectorbuffer , sector_size ) ! = sector_size )
fdisk_fatal ( unable_to_read ) ;
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
pe - > changed = 0 ;
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
pe - > part_table = pe - > ext_pointer = NULL ;
}
static unsigned int
2006-02-24 16:29:00 +00:00
get_partition_start ( const struct pte * pe )
{
2002-11-26 22:00:21 +00:00
return pe - > offset + get_start_sect ( pe - > part_table ) ;
}
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
/*
* Avoid warning about DOS partitions when no DOS partition was changed .
* Here a heuristic " is probably dos partition " .
* We might also do the opposite and warn in all cases except
* for " is probably nondos partition " .
*/
static int
2006-02-24 16:29:00 +00:00
is_dos_partition ( int t )
{
2002-11-26 22:00:21 +00:00
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
2006-02-24 16:29:00 +00:00
menu ( void )
{
2002-11-26 22:00:21 +00:00
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type ) {
2006-02-24 16:29:00 +00:00
puts ( _ ( " Command action " ) ) ;
puts ( _ ( " \t a \t toggle a read only flag " ) ) ; /* sun */
puts ( _ ( " \t b \t edit bsd disklabel " ) ) ;
puts ( _ ( " \t c \t toggle the mountable flag " ) ) ; /* sun */
puts ( _ ( " \t d \t delete a partition " ) ) ;
puts ( _ ( " \t l \t list known partition types " ) ) ;
puts ( _ ( " \t m \t print this menu " ) ) ;
puts ( _ ( " \t n \t add a new partition " ) ) ;
puts ( _ ( " \t o \t create a new empty DOS partition table " ) ) ;
puts ( _ ( " \t p \t print the partition table " ) ) ;
puts ( _ ( " \t q \t quit without saving changes " ) ) ;
puts ( _ ( " \t s \t create a new empty Sun disklabel " ) ) ; /* sun */
puts ( _ ( " \t t \t change a partition's system id " ) ) ;
puts ( _ ( " \t u \t change display/entry units " ) ) ;
puts ( _ ( " \t v \t verify the partition table " ) ) ;
puts ( _ ( " \t w \t write table to disk and exit " ) ) ;
2002-11-26 22:00:21 +00:00
# ifdef CONFIG_FEATURE_FDISK_ADVANCED
2006-02-24 16:29:00 +00:00
puts ( _ ( " \t x \t extra functionality (experts only) " ) ) ;
2002-11-26 22:00:21 +00:00
# endif
} else
# endif
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sgi = = current_label_type ) {
2006-02-24 16:29:00 +00:00
puts ( _ ( " Command action " ) ) ;
puts ( _ ( " \t a \t select bootable partition " ) ) ; /* sgi flavour */
puts ( _ ( " \t b \t edit bootfile entry " ) ) ; /* sgi */
puts ( _ ( " \t c \t select sgi swap partition " ) ) ; /* sgi flavour */
puts ( _ ( " \t d \t delete a partition " ) ) ;
puts ( _ ( " \t l \t list known partition types " ) ) ;
puts ( _ ( " \t m \t print this menu " ) ) ;
puts ( _ ( " \t n \t add a new partition " ) ) ;
puts ( _ ( " \t o \t create a new empty DOS partition table " ) ) ;
puts ( _ ( " \t p \t print the partition table " ) ) ;
puts ( _ ( " \t q \t quit without saving changes " ) ) ;
puts ( _ ( " \t s \t create a new empty Sun disklabel " ) ) ; /* sun */
puts ( _ ( " \t t \t change a partition's system id " ) ) ;
puts ( _ ( " \t u \t change display/entry units " ) ) ;
puts ( _ ( " \t v \t verify the partition table " ) ) ;
puts ( _ ( " \t w \t write table to disk and exit " ) ) ;
2002-11-26 22:00:21 +00:00
} else
# endif
# ifdef CONFIG_FEATURE_AIX_LABEL
2006-02-25 03:46:10 +00:00
if ( label_aix = = current_label_type ) {
2006-02-24 16:29:00 +00:00
puts ( _ ( " Command action " ) ) ;
puts ( _ ( " \t m \t print this menu " ) ) ;
puts ( _ ( " \t o \t create a new empty DOS partition table " ) ) ;
puts ( _ ( " \t q \t quit without saving changes " ) ) ;
puts ( _ ( " \t s \t create a new empty Sun disklabel " ) ) ; /* sun */
2002-11-26 22:00:21 +00:00
} else
# endif
{
2006-02-24 16:29:00 +00:00
puts ( _ ( " Command action " ) ) ;
puts ( _ ( " \t a \t toggle a bootable flag " ) ) ;
puts ( _ ( " \t b \t edit bsd disklabel " ) ) ;
puts ( _ ( " \t c \t toggle the dos compatibility flag " ) ) ;
puts ( _ ( " \t d \t delete a partition " ) ) ;
puts ( _ ( " \t l \t list known partition types " ) ) ;
puts ( _ ( " \t m \t print this menu " ) ) ;
puts ( _ ( " \t n \t add a new partition " ) ) ;
puts ( _ ( " \t o \t create a new empty DOS partition table " ) ) ;
puts ( _ ( " \t p \t print the partition table " ) ) ;
puts ( _ ( " \t q \t quit without saving changes " ) ) ;
puts ( _ ( " \t s \t create a new empty Sun disklabel " ) ) ; /* sun */
puts ( _ ( " \t t \t change a partition's system id " ) ) ;
puts ( _ ( " \t u \t change display/entry units " ) ) ;
puts ( _ ( " \t v \t verify the partition table " ) ) ;
puts ( _ ( " \t w \t write table to disk and exit " ) ) ;
2002-11-26 22:00:21 +00:00
# ifdef CONFIG_FEATURE_FDISK_ADVANCED
2006-02-24 16:29:00 +00:00
puts ( _ ( " \t x \t extra functionality (experts only) " ) ) ;
2002-11-26 22:00:21 +00:00
# endif
}
}
2003-01-04 11:56:06 +00:00
# endif /* CONFIG_FEATURE_FDISK_WRITABLE */
2002-11-26 22:00:21 +00:00
# ifdef CONFIG_FEATURE_FDISK_ADVANCED
static void
2006-02-24 16:29:00 +00:00
xmenu ( void )
{
2002-11-26 22:00:21 +00:00
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type ) {
2006-02-24 16:29:00 +00:00
puts ( _ ( " Command action " ) ) ;
puts ( _ ( " \t a \t change number of alternate cylinders " ) ) ; /*sun*/
puts ( _ ( " \t c \t change number of cylinders " ) ) ;
puts ( _ ( " \t d \t print the raw data in the partition table " ) ) ;
puts ( _ ( " \t e \t change number of extra sectors per cylinder " ) ) ; /*sun*/
puts ( _ ( " \t h \t change number of heads " ) ) ;
puts ( _ ( " \t i \t change interleave factor " ) ) ; /*sun*/
puts ( _ ( " \t o \t change rotation speed (rpm) " ) ) ; /*sun*/
puts ( _ ( " \t m \t print this menu " ) ) ;
puts ( _ ( " \t p \t print the partition table " ) ) ;
puts ( _ ( " \t q \t quit without saving changes " ) ) ;
puts ( _ ( " \t r \t return to main menu " ) ) ;
puts ( _ ( " \t s \t change number of sectors/track " ) ) ;
puts ( _ ( " \t v \t verify the partition table " ) ) ;
puts ( _ ( " \t w \t write table to disk and exit " ) ) ;
puts ( _ ( " \t y \t change number of physical cylinders " ) ) ; /*sun*/
2002-11-26 22:00:21 +00:00
} else
# endif
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sgi = = current_label_type ) {
2006-02-24 16:29:00 +00:00
puts ( _ ( " Command action " ) ) ;
puts ( _ ( " \t b \t move beginning of data in a partition " ) ) ; /* !sun */
puts ( _ ( " \t c \t change number of cylinders " ) ) ;
puts ( _ ( " \t d \t print the raw data in the partition table " ) ) ;
puts ( _ ( " \t e \t list extended partitions " ) ) ; /* !sun */
puts ( _ ( " \t g \t create an IRIX (SGI) partition table " ) ) ; /* sgi */
puts ( _ ( " \t h \t change number of heads " ) ) ;
puts ( _ ( " \t m \t print this menu " ) ) ;
puts ( _ ( " \t p \t print the partition table " ) ) ;
puts ( _ ( " \t q \t quit without saving changes " ) ) ;
puts ( _ ( " \t r \t return to main menu " ) ) ;
puts ( _ ( " \t s \t change number of sectors/track " ) ) ;
puts ( _ ( " \t v \t verify the partition table " ) ) ;
puts ( _ ( " \t w \t write table to disk and exit " ) ) ;
2002-11-26 22:00:21 +00:00
} else
# endif
# ifdef CONFIG_FEATURE_AIX_LABEL
2006-02-25 03:46:10 +00:00
if ( label_aix = = current_label_type ) {
2006-02-24 16:29:00 +00:00
puts ( _ ( " Command action " ) ) ;
puts ( _ ( " \t b \t move beginning of data in a partition " ) ) ; /* !sun */
puts ( _ ( " \t c \t change number of cylinders " ) ) ;
puts ( _ ( " \t d \t print the raw data in the partition table " ) ) ;
puts ( _ ( " \t e \t list extended partitions " ) ) ; /* !sun */
puts ( _ ( " \t g \t create an IRIX (SGI) partition table " ) ) ; /* sgi */
puts ( _ ( " \t h \t change number of heads " ) ) ;
puts ( _ ( " \t m \t print this menu " ) ) ;
puts ( _ ( " \t p \t print the partition table " ) ) ;
puts ( _ ( " \t q \t quit without saving changes " ) ) ;
puts ( _ ( " \t r \t return to main menu " ) ) ;
puts ( _ ( " \t s \t change number of sectors/track " ) ) ;
puts ( _ ( " \t v \t verify the partition table " ) ) ;
puts ( _ ( " \t w \t write table to disk and exit " ) ) ;
2002-11-26 22:00:21 +00:00
} else
# endif
{
2006-02-24 16:29:00 +00:00
puts ( _ ( " Command action " ) ) ;
puts ( _ ( " \t b \t move beginning of data in a partition " ) ) ; /* !sun */
puts ( _ ( " \t c \t change number of cylinders " ) ) ;
puts ( _ ( " \t d \t print the raw data in the partition table " ) ) ;
puts ( _ ( " \t e \t list extended partitions " ) ) ; /* !sun */
puts ( _ ( " \t f \t fix partition order " ) ) ; /* !sun, !aix, !sgi */
2002-11-26 22:00:21 +00:00
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-24 16:29:00 +00:00
puts ( _ ( " \t g \t create an IRIX (SGI) partition table " ) ) ; /* sgi */
# endif
puts ( _ ( " \t h \t change number of heads " ) ) ;
puts ( _ ( " \t m \t print this menu " ) ) ;
puts ( _ ( " \t p \t print the partition table " ) ) ;
puts ( _ ( " \t q \t quit without saving changes " ) ) ;
puts ( _ ( " \t r \t return to main menu " ) ) ;
puts ( _ ( " \t s \t change number of sectors/track " ) ) ;
puts ( _ ( " \t v \t verify the partition table " ) ) ;
puts ( _ ( " \t w \t write table to disk and exit " ) ) ;
2002-11-26 22:00:21 +00:00
}
}
# endif /* ADVANCED mode */
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
static const struct systypes *
2006-02-24 16:29:00 +00:00
get_sys_types ( void )
{
2002-11-26 22:00:21 +00:00
return (
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
label_sun = = current_label_type ? sun_sys_types :
2002-11-26 22:00:21 +00:00
# endif
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
label_sgi = = current_label_type ? sgi_sys_types :
2002-11-26 22:00:21 +00:00
# endif
i386_sys_types ) ;
}
2003-01-04 11:56:06 +00:00
# else
# define get_sys_types() i386_sys_types
# endif /* CONFIG_FEATURE_FDISK_WRITABLE */
2002-11-26 22:00:21 +00:00
static const char * partition_type ( unsigned char type )
{
int i ;
const struct systypes * types = get_sys_types ( ) ;
2006-02-24 16:29:00 +00:00
for ( i = 0 ; types [ i ] . name ; i + + )
2005-12-02 10:06:04 +00:00
if ( ( unsigned char ) types [ i ] . name [ 0 ] = = type )
2002-11-26 22:00:21 +00:00
return types [ i ] . name + 1 ;
2003-01-04 11:56:06 +00:00
return _ ( " Unknown " ) ;
}
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
static int
2006-02-24 16:29:00 +00:00
get_sysid ( int i )
{
2003-01-04 11:56:06 +00:00
return (
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
label_sun = = current_label_type ? sunlabel - > infos [ i ] . id :
2003-01-04 11:56:06 +00:00
# endif
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
label_sgi = = current_label_type ? sgi_get_sysid ( i ) :
2003-01-04 11:56:06 +00:00
# endif
ptes [ i ] . part_table - > sys_ind ) ;
2002-11-26 22:00:21 +00:00
}
void list_types ( const struct systypes * sys )
{
uint last [ 4 ] , done = 0 , next = 0 , size ;
int i ;
for ( i = 0 ; sys [ i ] . name ; i + + ) ;
size = i ;
for ( i = 3 ; i > = 0 ; i - - )
last [ 3 - i ] = done + = ( size + i - done ) / ( i + 1 ) ;
i = done = 0 ;
do {
printf ( " %c%2x %-15.15s " , i ? ' ' : ' \n ' ,
2005-12-02 10:06:04 +00:00
( unsigned char ) sys [ next ] . name [ 0 ] ,
partition_type ( ( unsigned char ) sys [ next ] . name [ 0 ] ) ) ;
2002-11-26 22:00:21 +00:00
next = last [ i + + ] + done ;
if ( i > 3 | | next > = last [ i ] ) {
i = 0 ;
next = + + done ;
}
} while ( done < last [ 0 ] ) ;
putchar ( ' \n ' ) ;
}
2003-01-04 11:56:06 +00:00
# endif /* CONFIG_FEATURE_FDISK_WRITABLE */
2002-11-26 22:00:21 +00:00
static int
2006-02-24 16:29:00 +00:00
is_cleared_partition ( const struct partition * p )
{
2002-11-26 22:00:21 +00:00
return ! ( ! p | | p - > boot_ind | | p - > head | | p - > sector | | p - > cyl | |
p - > sys_ind | | p - > end_head | | p - > end_sector | | p - > end_cyl | |
get_start_sect ( p ) | | get_nr_sects ( p ) ) ;
}
static void
2006-02-24 16:29:00 +00:00
clear_partition ( struct partition * p )
{
2002-11-26 22:00:21 +00:00
if ( ! p )
return ;
2003-01-04 11:56:06 +00:00
memset ( p , 0 , sizeof ( struct partition ) ) ;
2002-11-26 22:00:21 +00:00
}
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
set_partition ( int i , int doext , off_t start , off_t stop , int sysid )
{
2002-11-26 22:00:21 +00:00
struct partition * p ;
2004-06-28 23:50:31 +00:00
off_t offset ;
2002-11-26 22:00:21 +00:00
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 ( dos_compatible_flag & & ( start / ( sectors * heads ) > 1023 ) )
start = heads * sectors * 1024 - 1 ;
set_hsc ( p - > head , p - > sector , p - > cyl , start ) ;
if ( dos_compatible_flag & & ( stop / ( sectors * heads ) > 1023 ) )
stop = heads * sectors * 1024 - 1 ;
set_hsc ( p - > end_head , p - > end_sector , p - > end_cyl , stop ) ;
ptes [ i ] . changed = 1 ;
}
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
static int
2006-02-24 16:29:00 +00:00
test_c ( const char * * m , const char * mesg )
{
2002-11-26 22:00:21 +00:00
int val = 0 ;
if ( ! * m )
fprintf ( stderr , _ ( " You must set " ) ) ;
else {
fprintf ( stderr , " %s " , * m ) ;
val = 1 ;
}
* m = mesg ;
return val ;
}
static int
2006-02-24 16:29:00 +00:00
warn_geometry ( void )
{
2002-11-26 22:00:21 +00:00
const char * m = NULL ;
int prev = 0 ;
if ( ! heads )
prev = test_c ( & m , _ ( " heads " ) ) ;
if ( ! sectors )
prev = test_c ( & m , _ ( " sectors " ) ) ;
if ( ! cylinders )
prev = test_c ( & m , _ ( " cylinders " ) ) ;
if ( ! m )
return 0 ;
2003-01-04 11:56:06 +00:00
fprintf ( stderr , " %s%s. \n "
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
" You can do this from the extra functions menu. \n "
# endif
, prev ? _ ( " and " ) : " " , m ) ;
2002-11-26 22:00:21 +00:00
return 1 ;
}
static void update_units ( void )
{
int cyl_units = heads * sectors ;
if ( display_in_cyl_units & & cyl_units )
units_per_sector = cyl_units ;
else
units_per_sector = 1 ; /* in sectors */
}
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
warn_cylinders ( void )
{
2006-02-25 03:46:10 +00:00
if ( label_dos = = current_label_type & & cylinders > 1024 & & ! nowarn )
2002-11-26 22:00:21 +00:00
fprintf ( stderr , _ ( " \n "
" The number of cylinders for this disk is set to %d. \n "
" There is nothing wrong with that, but this is larger than 1024, \n "
" and could in certain setups cause problems with: \n "
" 1) software that runs at boot time (e.g., old versions of LILO) \n "
" 2) booting and partitioning software from other OSs \n "
" (e.g., DOS FDISK, OS/2 FDISK) \n " ) ,
cylinders ) ;
}
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
read_extended ( int ext )
{
2002-11-26 22:00:21 +00:00
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 ;
}
2006-02-24 16:29:00 +00:00
while ( IS_EXTENDED ( p - > sys_ind ) ) {
2002-11-26 22:00:21 +00:00
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 ] ;
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
fprintf ( stderr ,
_ ( " Warning: deleting partitions after %d \n " ) ,
partitions ) ;
pre - > changed = 1 ;
2003-01-04 11:56:06 +00:00
# endif
clear_partition ( pre - > ext_pointer ) ;
2002-11-26 22:00:21 +00:00
return ;
}
2003-01-04 11:56:06 +00:00
read_pte ( pe , extended_offset + get_start_sect ( p ) ) ;
2002-11-26 22:00:21 +00:00
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 ) ) {
2006-02-24 16:29:00 +00:00
if ( IS_EXTENDED ( p - > sys_ind ) ) {
2002-11-26 22:00:21 +00:00
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 + + ;
}
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
/* remove empty links */
remove :
for ( i = 4 ; i < partitions ; i + + ) {
struct pte * pe = & ptes [ i ] ;
if ( ! get_nr_sects ( pe - > part_table ) & &
2006-02-24 16:29:00 +00:00
( partitions > 5 | | ptes [ 4 ] . part_table - > sys_ind ) ) {
2002-11-26 22:00:21 +00:00
printf ( " omitting empty partition (%d) \n " , i + 1 ) ;
delete_partition ( i ) ;
goto remove ; /* numbering changed */
}
}
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
}
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
create_doslabel ( void )
{
2002-11-26 22:00:21 +00:00
int i ;
fprintf ( stderr ,
_ ( " Building a new DOS disklabel. Changes will remain in memory only, \n "
" until you decide to write them. After that, of course, the previous \n "
" content won't be recoverable. \n \n " ) ) ;
2006-02-25 03:46:10 +00:00
current_label_type = label_dos ;
2002-11-26 22:00:21 +00:00
# ifdef CONFIG_FEATURE_OSF_LABEL
possibly_osf_label = 0 ;
# endif
partitions = 4 ;
for ( i = 510 - 64 ; i < 510 ; i + + )
MBRbuffer [ i ] = 0 ;
write_part_table_flag ( MBRbuffer ) ;
extended_offset = 0 ;
set_all_unchanged ( ) ;
set_changed ( 0 ) ;
get_boot ( create_empty_dos ) ;
}
2003-01-04 11:56:06 +00:00
# endif /* CONFIG_FEATURE_FDISK_WRITABLE */
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
get_sectorsize ( void )
{
2006-02-25 03:36:00 +00:00
if ( ! user_set_sector_size ) {
2002-11-26 22:00:21 +00:00
int arg ;
if ( ioctl ( fd , BLKSSZGET , & arg ) = = 0 )
sector_size = arg ;
if ( sector_size ! = DEFAULT_SECTOR_SIZE )
printf ( _ ( " Note: sector size is %d (not %d) \n " ) ,
2006-02-24 16:29:00 +00:00
sector_size , DEFAULT_SECTOR_SIZE ) ;
2002-11-26 22:00:21 +00:00
}
}
2003-01-04 11:56:06 +00:00
static inline void
2006-02-24 16:29:00 +00:00
get_kernel_geometry ( void )
{
2002-11-26 22:00:21 +00:00
struct hd_geometry geometry ;
if ( ! ioctl ( fd , HDIO_GETGEO , & geometry ) ) {
kern_heads = geometry . heads ;
kern_sectors = geometry . sectors ;
/* never use geometry.cylinders - it is truncated */
}
}
static void
2006-02-24 16:29:00 +00:00
get_partition_table_geometry ( void )
{
2005-12-02 10:06:04 +00:00
const unsigned char * bufp = ( const unsigned char * ) MBRbuffer ;
2002-11-26 22:00:21 +00:00
struct partition * p ;
int i , h , s , hh , ss ;
int first = 1 ;
int bad = 0 ;
2006-01-30 23:09:20 +00:00
if ( ! ( valid_part_table_flag ( ( char * ) bufp ) ) )
2002-11-26 22:00:21 +00:00
return ;
hh = ss = 0 ;
2006-02-24 16:29:00 +00:00
for ( i = 0 ; i < 4 ; i + + ) {
2002-11-26 22:00:21 +00:00
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 ) {
pt_heads = hh ;
pt_sectors = ss ;
}
}
2006-02-24 16:29:00 +00:00
static void
get_geometry ( void )
{
2002-11-26 22:00:21 +00:00
int sec_fac ;
2003-07-30 08:40:37 +00:00
unsigned long long bytes ; /* really u64 */
2002-11-26 22:00:21 +00:00
get_sectorsize ( ) ;
sec_fac = sector_size / 512 ;
# ifdef CONFIG_FEATURE_SUN_LABEL
guess_device_type ( ) ;
# endif
heads = cylinders = sectors = 0 ;
kern_heads = kern_sectors = 0 ;
pt_heads = pt_sectors = 0 ;
get_kernel_geometry ( ) ;
get_partition_table_geometry ( ) ;
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 ;
2003-07-30 08:40:37 +00:00
if ( ioctl ( fd , BLKGETSIZE64 , & bytes ) = = 0 ) {
/* got bytes */
} else {
unsigned long longsectors ;
2002-11-26 22:00:21 +00:00
if ( ioctl ( fd , BLKGETSIZE , & longsectors ) )
longsectors = 0 ;
2003-07-30 08:40:37 +00:00
bytes = ( ( unsigned long long ) longsectors ) < < 9 ;
}
total_number_of_sectors = ( bytes > > 9 ) ;
2002-11-26 22:00:21 +00:00
sector_offset = 1 ;
if ( dos_compatible_flag )
sector_offset = sectors ;
2003-07-30 08:40:37 +00:00
cylinders = total_number_of_sectors / ( heads * sectors * sec_fac ) ;
2002-11-26 22:00:21 +00:00
if ( ! cylinders )
cylinders = user_cylinders ;
}
/*
* Read MBR . Returns :
* - 1 : no 0xaa55 flag present ( possibly entire disk BSD )
* 0 : found or created label
* 1 : I / O error
*/
2006-02-24 16:29:00 +00:00
static int
get_boot ( enum action what )
{
2002-11-26 22:00:21 +00:00
int i ;
partitions = 4 ;
for ( i = 0 ; i < 4 ; i + + ) {
struct pte * pe = & ptes [ i ] ;
pe - > part_table = pt_offset ( MBRbuffer , i ) ;
pe - > ext_pointer = NULL ;
pe - > offset = 0 ;
pe - > sectorbuffer = MBRbuffer ;
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
pe - > changed = ( what = = create_empty_dos ) ;
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
}
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_SUN_LABEL
2002-11-26 22:00:21 +00:00
if ( what = = create_empty_sun & & check_sun_label ( ) )
return 0 ;
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
memset ( MBRbuffer , 0 , 512 ) ;
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
if ( what = = create_empty_dos )
goto got_dos_table ; /* skip reading disk */
if ( ( fd = open ( disk_device , type_open ) ) < 0 ) {
2006-02-24 16:29:00 +00:00
if ( ( fd = open ( disk_device , O_RDONLY ) ) < 0 ) {
if ( what = = try_only )
return 1 ;
fdisk_fatal ( unable_to_open ) ;
} else
printf ( _ ( " You will not be able to write "
" the partition table. \n " ) ) ;
2002-11-26 22:00:21 +00:00
}
if ( 512 ! = read ( fd , MBRbuffer , 512 ) ) {
if ( what = = try_only )
return 1 ;
fdisk_fatal ( unable_to_read ) ;
}
2003-01-04 11:56:06 +00:00
# else
if ( ( fd = open ( disk_device , O_RDONLY ) ) < 0 )
return 1 ;
if ( 512 ! = read ( fd , MBRbuffer , 512 ) )
return 1 ;
# endif
2002-11-26 22:00:21 +00:00
2003-01-04 11:56:06 +00:00
get_geometry ( ) ;
2002-11-26 22:00:21 +00:00
update_units ( ) ;
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_SUN_LABEL
2002-11-26 22:00:21 +00:00
if ( check_sun_label ( ) )
return 0 ;
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
# ifdef CONFIG_FEATURE_SGI_LABEL
if ( check_sgi_label ( ) )
return 0 ;
# endif
# ifdef CONFIG_FEATURE_AIX_LABEL
if ( check_aix_label ( ) )
return 0 ;
# endif
# ifdef CONFIG_FEATURE_OSF_LABEL
if ( check_osf_label ( ) ) {
possibly_osf_label = 1 ;
if ( ! valid_part_table_flag ( MBRbuffer ) ) {
2006-02-25 03:46:10 +00:00
current_label_type = label_osf ;
2002-11-26 22:00:21 +00:00
return 0 ;
}
printf ( _ ( " This disk has both DOS and BSD magic. \n "
" Give the 'b' command to go to BSD mode. \n " ) ) ;
}
# endif
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2006-02-24 16:29:00 +00:00
got_dos_table :
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
if ( ! valid_part_table_flag ( MBRbuffer ) ) {
2003-01-04 11:56:06 +00:00
# ifndef CONFIG_FEATURE_FDISK_WRITABLE
return - 1 ;
# else
2006-02-24 16:29:00 +00:00
switch ( what ) {
2002-11-26 22:00:21 +00:00
case fdisk :
fprintf ( stderr ,
_ ( " Device contains neither a valid DOS "
" partition table, nor Sun, SGI or OSF "
" disklabel \n " ) ) ;
# ifdef __sparc__
# ifdef CONFIG_FEATURE_SUN_LABEL
create_sunlabel ( ) ;
# endif
# else
create_doslabel ( ) ;
# endif
return 0 ;
case try_only :
return - 1 ;
case create_empty_dos :
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_SUN_LABEL
2002-11-26 22:00:21 +00:00
case create_empty_sun :
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
break ;
default :
fprintf ( stderr , _ ( " Internal error \n " ) ) ;
exit ( 1 ) ;
}
2003-01-04 11:56:06 +00:00
# endif /* CONFIG_FEATURE_FDISK_WRITABLE */
2002-11-26 22:00:21 +00:00
}
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
warn_cylinders ( ) ;
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
warn_geometry ( ) ;
for ( i = 0 ; i < 4 ; i + + ) {
struct pte * pe = & ptes [ i ] ;
2006-02-24 16:29:00 +00:00
if ( IS_EXTENDED ( pe - > part_table - > sys_ind ) ) {
2002-11-26 22:00:21 +00:00
if ( partitions ! = 4 )
fprintf ( stderr , _ ( " Ignoring extra extended "
" partition %d \n " ) , i + 1 ) ;
else
read_extended ( 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 ) ;
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
pe - > changed = 1 ;
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
}
}
return 0 ;
}
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
/*
* Print the message MESG , then read an integer between LOW and HIGH ( inclusive ) .
* If the user hits Enter , DFLT is returned .
* Answers like + 10 are interpreted as offsets from BASE .
*
* There is no default if DFLT is not between LOW and HIGH .
*/
static uint
read_int ( uint low , uint dflt , uint high , uint base , char * mesg )
{
uint i ;
int default_ok = 1 ;
static char * ms = NULL ;
static int 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 )
2003-07-30 08:40:37 +00:00
snprintf ( ms , mslen , _ ( " %s (%u-%u, default %u): " ) ,
2002-11-26 22:00:21 +00:00
mesg , low , high , dflt ) ;
else
2006-02-24 16:29:00 +00:00
snprintf ( ms , mslen , " %s (%u-%u): " , mesg , low , high ) ;
2002-11-26 22:00:21 +00:00
while ( 1 ) {
int use_default = default_ok ;
/* ask question and read answer */
while ( read_chars ( ms ) ! = ' \n ' & & ! isdigit ( * line_ptr )
2006-02-24 16:29:00 +00:00
& & * line_ptr ! = ' - ' & & * line_ptr ! = ' + ' )
2002-11-26 22:00:21 +00:00
continue ;
2004-05-19 10:49:17 +00:00
if ( * line_ptr = = ' + ' | | * line_ptr = = ' - ' ) {
2006-02-24 16:29:00 +00:00
int minus = ( * line_ptr = = ' - ' ) ;
int absolute = 0 ;
2003-07-03 10:02:32 +00:00
2006-02-24 16:29:00 +00:00
i = atoi ( line_ptr + 1 ) ;
2003-07-03 10:02:32 +00:00
2006-02-24 16:29:00 +00:00
while ( isdigit ( * + + line_ptr ) )
use_default = 0 ;
2004-05-19 10:49:17 +00:00
2006-02-24 16:29:00 +00:00
switch ( * line_ptr ) {
case ' c ' :
case ' C ' :
if ( ! display_in_cyl_units )
i * = heads * sectors ;
break ;
case ' K ' :
absolute = 1024 ;
break ;
case ' k ' :
absolute = 1000 ;
break ;
case ' m ' :
case ' M ' :
absolute = 1000000 ;
break ;
case ' g ' :
case ' G ' :
absolute = 1000000000 ;
break ;
default :
break ;
2002-11-26 22:00:21 +00:00
}
2006-02-24 16:29:00 +00:00
if ( absolute ) {
unsigned long long bytes ;
unsigned long unit ;
bytes = ( unsigned long long ) i * absolute ;
unit = sector_size * units_per_sector ;
bytes + = unit / 2 ; /* round */
bytes / = unit ;
i = bytes ;
}
if ( minus )
i = - i ;
i + = base ;
2004-05-19 10:49:17 +00:00
} else {
2002-11-26 22:00:21 +00:00
i = atoi ( line_ptr ) ;
while ( isdigit ( * line_ptr ) ) {
line_ptr + + ;
use_default = 0 ;
}
}
if ( use_default )
2003-07-30 08:40:37 +00:00
printf ( _ ( " Using default value %u \n " ) , i = dflt ) ;
2002-11-26 22:00:21 +00:00
if ( i > = low & & i < = high )
break ;
else
printf ( _ ( " Value out of range. \n " ) ) ;
}
return i ;
}
2006-02-24 16:29:00 +00:00
static int
get_partition ( int warn , int max )
{
2002-11-26 22:00:21 +00:00
struct pte * pe ;
int i ;
i = read_int ( 1 , 0 , max , 0 , _ ( " Partition number " ) ) - 1 ;
pe = & ptes [ i ] ;
if ( warn ) {
2006-02-25 03:46:10 +00:00
if (
(
label_sun ! = current_label_type & &
label_sgi ! = current_label_type & &
! pe - > part_table - > sys_ind
)
2002-11-26 22:00:21 +00:00
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
| | (
label_sun = = current_label_type & &
(
! sunlabel - > partitions [ i ] . num_sectors
| | ! sunlabel - > infos [ i ] . id
)
)
2002-11-26 22:00:21 +00:00
# endif
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
| | (
label_sgi = = current_label_type & &
! sgi_get_num_sectors ( i )
)
2002-11-26 22:00:21 +00:00
# endif
2006-02-25 03:46:10 +00:00
) {
2002-11-26 22:00:21 +00:00
fprintf ( stderr ,
_ ( " Warning: partition %d has empty type \n " ) ,
2006-02-25 03:46:10 +00:00
i + 1
) ;
}
2002-11-26 22:00:21 +00:00
}
return i ;
}
static int
2006-02-24 16:29:00 +00:00
get_existing_partition ( int warn , int max )
{
2002-11-26 22:00:21 +00:00
int pno = - 1 ;
int i ;
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_unique :
return get_partition ( warn , max ) ;
}
static int
2006-02-24 16:29:00 +00:00
get_nonexisting_partition ( int warn , int max )
{
2002-11-26 22:00:21 +00:00
int pno = - 1 ;
int i ;
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 ( _ ( " All primary partitions have been defined already! \n " ) ) ;
return - 1 ;
not_unique :
return get_partition ( warn , max ) ;
}
void change_units ( void )
{
display_in_cyl_units = ! display_in_cyl_units ;
update_units ( ) ;
printf ( _ ( " Changing display/entry units to %s \n " ) ,
str_units ( PLURAL ) ) ;
}
static void
2006-02-24 16:29:00 +00:00
toggle_active ( int i )
{
2002-11-26 22:00:21 +00:00
struct pte * pe = & ptes [ i ] ;
struct partition * p = pe - > part_table ;
2006-02-24 16:29:00 +00:00
if ( IS_EXTENDED ( p - > sys_ind ) & & ! p - > boot_ind )
2002-11-26 22:00:21 +00:00
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
2006-02-24 16:29:00 +00:00
toggle_dos_compatibility_flag ( void )
{
2002-11-26 22:00:21 +00:00
dos_compatible_flag = ~ dos_compatible_flag ;
if ( dos_compatible_flag ) {
sector_offset = sectors ;
printf ( _ ( " DOS Compatibility flag is set \n " ) ) ;
}
else {
sector_offset = 1 ;
printf ( _ ( " DOS Compatibility flag is not set \n " ) ) ;
}
}
static void
2006-02-24 16:29:00 +00:00
delete_partition ( int i )
{
2002-11-26 22:00:21 +00:00
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 ( warn_geometry ( ) )
return ; /* C/H/S not set */
pe - > changed = 1 ;
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type ) {
2002-11-26 22:00:21 +00:00
sun_delete_partition ( i ) ;
return ;
}
# endif
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sgi = = current_label_type ) {
2002-11-26 22:00:21 +00:00
sgi_delete_partition ( i ) ;
return ;
}
# endif
if ( i < 4 ) {
2006-02-24 16:29:00 +00:00
if ( IS_EXTENDED ( p - > sys_ind ) & & i = = ext_index ) {
2002-11-26 22:00:21 +00:00
partitions = 4 ;
ptes [ ext_index ] . ext_pointer = NULL ;
extended_offset = 0 ;
}
clear_partition ( p ) ;
return ;
}
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 */
pe = & ptes [ 5 ] ;
if ( pe - > part_table ) /* prevent SEGFAULT */
set_start_sect ( pe - > part_table ,
2006-02-24 16:29:00 +00:00
get_partition_start ( pe ) -
extended_offset ) ;
2002-11-26 22:00:21 +00:00
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 ) ;
}
}
static void
2006-02-24 16:29:00 +00:00
change_sysid ( void )
{
2002-11-26 22:00:21 +00:00
int i , sys , origsys ;
struct partition * p ;
2003-07-30 08:40:37 +00:00
# ifdef CONFIG_FEATURE_SGI_LABEL
/* If sgi_label then don't use get_existing_partition,
let the user select a partition , since get_existing_partition ( )
only works for Linux like partition tables . */
2006-02-25 03:46:10 +00:00
if ( label_sgi ! = current_label_type ) {
2006-02-24 16:29:00 +00:00
i = get_existing_partition ( 0 , partitions ) ;
2003-07-30 08:40:37 +00:00
} else {
i = get_partition ( 0 , partitions ) ;
}
# else
i = get_existing_partition ( 0 , partitions ) ;
# endif
2002-11-26 22:00:21 +00:00
if ( i = = - 1 )
return ;
p = ptes [ i ] . part_table ;
origsys = sys = get_sysid ( i ) ;
/* if changing types T to 0 is allowed, then
the reverse change must be allowed , too */
2006-02-25 03:46:10 +00:00
if ( ! sys & & label_sgi ! = current_label_type & &
label_sun ! = current_label_type & & ! get_nr_sects ( p ) )
{
2002-11-26 22:00:21 +00:00
printf ( _ ( " Partition %d does not exist yet! \n " ) , i + 1 ) ;
2006-02-25 03:46:10 +00:00
} else {
while ( 1 ) {
2002-11-26 22:00:21 +00:00
sys = read_hex ( get_sys_types ( ) ) ;
2006-02-25 03:46:10 +00:00
if ( ! sys & & label_sgi ! = current_label_type & &
label_sun ! = current_label_type )
{
2002-11-26 22:00:21 +00:00
printf ( _ ( " Type 0 means free space to many systems \n "
2006-02-24 16:29:00 +00:00
" (but not to Linux). Having partitions of \n "
" type 0 is probably unwise. You can delete \n "
" a partition using the `d' command. \n " ) ) ;
2002-11-26 22:00:21 +00:00
/* break; */
}
2006-02-25 03:46:10 +00:00
if ( label_sun ! = current_label_type & & label_sgi ! = current_label_type ) {
2006-02-24 16:29:00 +00:00
if ( IS_EXTENDED ( sys ) ! = IS_EXTENDED ( p - > sys_ind ) ) {
2002-11-26 22:00:21 +00:00
printf ( _ ( " You cannot change a partition into "
2006-02-24 16:29:00 +00:00
" an extended one or vice versa \n "
" Delete it first. \n " ) ) ;
2002-11-26 22:00:21 +00:00
break ;
}
}
if ( sys < 256 ) {
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type & & i = = 2 & & sys ! = WHOLE_DISK )
2002-11-26 22:00:21 +00:00
printf ( _ ( " Consider leaving partition 3 "
2006-02-24 16:29:00 +00:00
" as Whole disk (5), \n "
" as SunOS/Solaris expects it and "
" even Linux likes it. \n \n " ) ) ;
2002-11-26 22:00:21 +00:00
# endif
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sgi = = current_label_type & &
(
( i = = 10 & & sys ! = ENTIRE_DISK ) | |
( i = = 8 & & sys ! = 0 )
)
) {
2002-11-26 22:00:21 +00:00
printf ( _ ( " Consider leaving partition 9 "
2006-02-24 16:29:00 +00:00
" as volume header (0), \n and "
" partition 11 as entire volume (6) "
" as IRIX expects it. \n \n " ) ) ;
2006-02-25 03:46:10 +00:00
}
2002-11-26 22:00:21 +00:00
# endif
if ( sys = = origsys )
break ;
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type ) {
2002-11-26 22:00:21 +00:00
sun_change_sysid ( i , sys ) ;
} else
# endif
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sgi = = current_label_type ) {
2002-11-26 22:00:21 +00:00
sgi_change_sysid ( i , sys ) ;
} else
# endif
p - > sys_ind = sys ;
2006-02-25 03:46:10 +00:00
2006-02-24 16:29:00 +00:00
printf ( _ ( " Changed system type of partition %d "
2002-11-26 22:00:21 +00:00
" to %x (%s) \n " ) , i + 1 , sys ,
2003-01-04 11:56:06 +00:00
partition_type ( sys ) ) ;
2002-11-26 22:00:21 +00:00
ptes [ i ] . changed = 1 ;
if ( is_dos_partition ( origsys ) | |
2006-02-24 16:29:00 +00:00
is_dos_partition ( sys ) )
2002-11-26 22:00:21 +00:00
dos_changed = 1 ;
break ;
}
2006-02-25 03:46:10 +00:00
}
2002-11-26 22:00:21 +00:00
}
}
2003-01-04 11:56:06 +00:00
# endif /* CONFIG_FEATURE_FDISK_WRITABLE */
2002-11-26 22:00:21 +00:00
/* 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 ) . */
2006-02-24 16:29:00 +00:00
static void
long2chs ( ulong ls , uint * c , uint * h , uint * s )
{
int spc = heads * sectors ;
2002-11-26 22:00:21 +00:00
* c = ls / spc ;
ls = ls % spc ;
* h = ls / sectors ;
* s = ls % sectors + 1 ; /* sectors count from 1 */
}
2006-02-24 16:29:00 +00:00
static void
check_consistency ( const struct partition * p , int partition )
{
uint pbc , pbh , pbs ; /* physical beginning c, h, s */
uint pec , peh , pes ; /* physical ending c, h, s */
uint lbc , lbh , lbs ; /* logical beginning c, h, s */
uint lec , leh , les ; /* logical ending c, h, s */
2002-11-26 22:00:21 +00:00
if ( ! heads | | ! sectors | | ( partition > = 4 ) )
return ; /* do not check extended partitions */
/* physical beginning c, h, s */
pbc = ( p - > cyl & 0xff ) | ( ( p - > sector < < 2 ) & 0x300 ) ;
pbh = p - > head ;
pbs = p - > sector & 0x3f ;
/* physical ending c, h, s */
pec = ( p - > end_cyl & 0xff ) | ( ( p - > end_sector < < 2 ) & 0x300 ) ;
peh = p - > end_head ;
pes = p - > end_sector & 0x3f ;
/* compute logical beginning (c, h, s) */
long2chs ( get_start_sect ( p ) , & lbc , & lbh , & lbs ) ;
/* compute logical ending (c, h, s) */
long2chs ( get_start_sect ( p ) + get_nr_sects ( p ) - 1 , & lec , & leh , & les ) ;
/* Same physical / logical beginning? */
if ( cylinders < = 1024 & & ( pbc ! = lbc | | pbh ! = lbh | | pbs ! = lbs ) ) {
printf ( _ ( " Partition %d has different physical/logical "
" beginnings (non-Linux?): \n " ) , partition + 1 ) ;
printf ( _ ( " phys=(%d, %d, %d) " ) , pbc , pbh , pbs ) ;
printf ( _ ( " logical=(%d, %d, %d) \n " ) , lbc , lbh , lbs ) ;
}
/* Same physical / logical ending? */
if ( cylinders < = 1024 & & ( pec ! = lec | | peh ! = leh | | pes ! = les ) ) {
printf ( _ ( " Partition %d has different physical/logical "
" endings: \n " ) , partition + 1 ) ;
printf ( _ ( " phys=(%d, %d, %d) " ) , pec , peh , pes ) ;
printf ( _ ( " logical=(%d, %d, %d) \n " ) , lec , leh , les ) ;
}
#if 0
/* Beginning on cylinder boundary? */
if ( pbh ! = ! pbc | | pbs ! = 1 ) {
printf ( _ ( " Partition %i does not start on cylinder "
" boundary: \n " ) , partition + 1 ) ;
printf ( _ ( " phys=(%d, %d, %d) " ) , pbc , pbh , pbs ) ;
printf ( _ ( " should be (%d, %d, 1) \n " ) , pbc , ! pbc ) ;
}
# endif
/* Ending on cylinder boundary? */
if ( peh ! = ( heads - 1 ) | | pes ! = sectors ) {
2004-05-19 10:49:17 +00:00
printf ( _ ( " Partition %i does not end on cylinder boundary. \n " ) ,
2002-11-26 22:00:21 +00:00
partition + 1 ) ;
#if 0
printf ( _ ( " phys=(%d, %d, %d) " ) , pec , peh , pes ) ;
printf ( _ ( " should be (%d, %d, %d) \n " ) ,
pec , heads - 1 , sectors ) ;
# endif
}
}
static void
2006-02-24 16:29:00 +00:00
list_disk_geometry ( void )
{
2003-07-30 08:40:37 +00:00
long long bytes = ( total_number_of_sectors < < 9 ) ;
2002-11-26 22:00:21 +00:00
long megabytes = bytes / 1000000 ;
if ( megabytes < 10000 )
printf ( _ ( " \n Disk %s: %ld MB, %lld bytes \n " ) ,
2006-02-24 16:29:00 +00:00
disk_device , megabytes , bytes ) ;
2002-11-26 22:00:21 +00:00
else
printf ( _ ( " \n Disk %s: %ld.%ld GB, %lld bytes \n " ) ,
2006-02-24 16:29:00 +00:00
disk_device , megabytes / 1000 , ( megabytes / 100 ) % 10 , bytes ) ;
2002-11-26 22:00:21 +00:00
printf ( _ ( " %d heads, %d sectors/track, %d cylinders " ) ,
2006-02-24 16:29:00 +00:00
heads , sectors , cylinders ) ;
2002-11-26 22:00:21 +00:00
if ( units_per_sector = = 1 )
2003-07-30 08:40:37 +00:00
printf ( _ ( " , total %llu sectors " ) ,
2006-02-24 16:29:00 +00:00
total_number_of_sectors / ( sector_size / 512 ) ) ;
2003-01-04 11:56:06 +00:00
printf ( _ ( " \n Units = %s of %d * %d = %d bytes \n \n " ) ,
2006-02-24 16:29:00 +00:00
str_units ( PLURAL ) ,
units_per_sector , sector_size , units_per_sector * sector_size ) ;
2002-11-26 22:00:21 +00:00
}
/*
* 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
2006-02-24 16:29:00 +00:00
wrong_p_order ( int * prev )
{
2002-11-26 22:00:21 +00:00
const struct pte * pe ;
const struct partition * p ;
2004-06-28 23:50:31 +00:00
off_t last_p_start_pos = 0 , p_start_pos ;
2002-11-26 22:00:21 +00:00
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 ;
}
# ifdef CONFIG_FEATURE_FDISK_ADVANCED
/*
* 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 doesnt 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
2006-02-24 16:29:00 +00:00
fix_chain_of_logicals ( void )
{
2002-11-26 22:00:21 +00:00
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 ,
2006-02-24 16:29:00 +00:00
ojj - extended_offset ) ;
2002-11-26 22:00:21 +00:00
set_start_sect ( ptes [ j ] . ext_pointer ,
2006-02-24 16:29:00 +00:00
oj - extended_offset ) ;
2002-11-26 22:00:21 +00:00
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
2006-02-24 16:29:00 +00:00
fix_partition_table_order ( void )
{
2002-11-26 22:00:21 +00:00
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 " ) ;
}
# endif
static void
2006-02-24 16:29:00 +00:00
list_table ( int xtra )
{
2002-11-26 22:00:21 +00:00
const struct partition * p ;
int i , w ;
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type ) {
2002-11-26 22:00:21 +00:00
sun_list_table ( xtra ) ;
return ;
}
# endif
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sgi = = current_label_type ) {
2002-11-26 22:00:21 +00:00
sgi_list_table ( xtra ) ;
return ;
}
# endif
list_disk_geometry ( ) ;
# ifdef CONFIG_FEATURE_OSF_LABEL
2006-02-25 03:46:10 +00:00
if ( label_osf = = current_label_type ) {
2002-11-26 22:00:21 +00:00
xbsd_print_disklabel ( xtra ) ;
return ;
}
# endif
/* 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 ( disk_device ) ;
if ( w & & isdigit ( disk_device [ w - 1 ] ) )
w + + ;
if ( w < 5 )
w = 5 ;
printf ( _ ( " %*s Boot Start End Blocks Id System \n " ) ,
2006-02-24 16:29:00 +00:00
w + 1 , _ ( " Device " ) ) ;
2002-11-26 22:00:21 +00:00
for ( i = 0 ; i < partitions ; i + + ) {
const struct pte * pe = & ptes [ i ] ;
p = pe - > part_table ;
if ( p & & ! is_cleared_partition ( p ) ) {
2004-06-28 23:50:31 +00:00
off_t psects = get_nr_sects ( p ) ;
off_t pblocks = psects ;
2002-11-26 22:00:21 +00:00
unsigned int podd = 0 ;
if ( sector_size < 1024 ) {
pblocks / = ( 1024 / sector_size ) ;
podd = psects % ( 1024 / sector_size ) ;
}
if ( sector_size > 1024 )
pblocks * = ( sector_size / 1024 ) ;
printf (
2006-02-24 16:29:00 +00:00
" %s %c %11llu %11llu %11llu%c %2x %s \n " ,
2002-11-26 22:00:21 +00:00
partname ( disk_device , i + 1 , w + 2 ) ,
/* boot flag */ ! p - > boot_ind ? ' ' : p - > boot_ind = = ACTIVE_FLAG
? ' * ' : ' ? ' ,
2004-06-28 23:50:31 +00:00
/* start */ ( unsigned long long ) cround ( get_partition_start ( pe ) ) ,
/* end */ ( unsigned long long ) cround ( get_partition_start ( pe ) + psects
2002-11-26 22:00:21 +00:00
- ( psects ? 1 : 0 ) ) ,
2004-06-28 23:50:31 +00:00
/* odd flag on end */ ( unsigned long long ) pblocks , podd ? ' + ' : ' ' ,
2002-11-26 22:00:21 +00:00
/* type id */ p - > sys_ind ,
2003-01-04 11:56:06 +00:00
/* type name */ partition_type ( p - > sys_ind ) ) ;
2002-11-26 22:00:21 +00:00
check_consistency ( p , 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 . . . */
2006-02-25 03:46:10 +00:00
if ( label_dos = = current_label_type & & wrong_p_order ( NULL ) ) {
/* FIXME */
2002-11-26 22:00:21 +00:00
printf ( _ ( " \n Partition table entries are not in disk order \n " ) ) ;
}
}
# ifdef CONFIG_FEATURE_FDISK_ADVANCED
static void
2006-02-24 16:29:00 +00:00
x_list_table ( int extend )
{
2002-11-26 22:00:21 +00:00
const struct pte * pe ;
const struct partition * p ;
int i ;
printf ( _ ( " \n Disk %s: %d heads, %d sectors, %d cylinders \n \n " ) ,
disk_device , heads , sectors , cylinders ) ;
printf ( _ ( " Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID \n " ) ) ;
for ( i = 0 ; i < partitions ; i + + ) {
pe = & ptes [ i ] ;
p = ( extend ? pe - > ext_pointer : pe - > part_table ) ;
if ( p ! = NULL ) {
2003-07-30 08:40:37 +00:00
printf ( " %2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x \n " ,
2002-11-26 22:00:21 +00:00
i + 1 , p - > boot_ind , p - > head ,
sector ( p - > sector ) ,
cylinder ( p - > sector , p - > cyl ) , p - > end_head ,
sector ( p - > end_sector ) ,
cylinder ( p - > end_sector , p - > end_cyl ) ,
get_start_sect ( p ) , get_nr_sects ( p ) , p - > sys_ind ) ;
if ( p - > sys_ind )
check_consistency ( p , i ) ;
}
}
}
# endif
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
fill_bounds ( off_t * first , off_t * last )
{
2002-11-26 22:00:21 +00:00
int i ;
const struct pte * pe = & ptes [ 0 ] ;
const struct partition * p ;
for ( i = 0 ; i < partitions ; pe + + , i + + ) {
p = pe - > part_table ;
2006-02-24 16:29:00 +00:00
if ( ! p - > sys_ind | | IS_EXTENDED ( p - > sys_ind ) ) {
2002-11-26 22:00:21 +00:00
first [ i ] = 0xffffffff ;
last [ i ] = 0 ;
} else {
first [ i ] = get_partition_start ( pe ) ;
last [ i ] = first [ i ] + get_nr_sects ( p ) - 1 ;
}
}
}
static void
2006-02-24 16:29:00 +00:00
check ( int n , uint h , uint s , uint c , off_t start )
{
2004-06-28 23:50:31 +00:00
off_t total , real_s , real_c ;
2002-11-26 22:00:21 +00:00
real_s = sector ( s ) - 1 ;
real_c = cylinder ( s , c ) ;
total = ( real_c * sectors + real_s ) * heads + h ;
if ( ! total )
fprintf ( stderr , _ ( " Warning: partition %d contains sector 0 \n " ) , n ) ;
if ( h > = heads )
fprintf ( stderr ,
_ ( " Partition %d: head %d greater than maximum %d \n " ) ,
n , h + 1 , heads ) ;
if ( real_s > = sectors )
fprintf ( stderr , _ ( " Partition %d: sector %d greater than "
" maximum %d \n " ) , n , s , sectors ) ;
if ( real_c > = cylinders )
2004-06-28 23:50:31 +00:00
fprintf ( stderr , _ ( " Partitions %d: cylinder %llu greater than "
" maximum %d \n " ) , n , ( unsigned long long ) real_c + 1 , cylinders ) ;
2002-11-26 22:00:21 +00:00
if ( cylinders < = 1024 & & start ! = total )
fprintf ( stderr ,
2004-06-28 23:50:31 +00:00
_ ( " Partition %d: previous sectors %llu disagrees with "
" total %llu \n " ) , n , ( unsigned long long ) start , ( unsigned long long ) total ) ;
2002-11-26 22:00:21 +00:00
}
static void
2006-02-24 16:29:00 +00:00
verify ( void )
{
2002-11-26 22:00:21 +00:00
int i , j ;
uint total = 1 ;
2004-06-28 23:50:31 +00:00
off_t first [ partitions ] , last [ partitions ] ;
2002-11-26 22:00:21 +00:00
struct partition * p ;
if ( warn_geometry ( ) )
return ;
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type ) {
2002-11-26 22:00:21 +00:00
verify_sun ( ) ;
return ;
}
# endif
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sgi = = current_label_type ) {
2002-11-26 22:00:21 +00:00
verify_sgi ( 1 ) ;
return ;
}
# endif
fill_bounds ( first , last ) ;
for ( i = 0 ; i < partitions ; i + + ) {
struct pte * pe = & ptes [ i ] ;
p = pe - > part_table ;
2006-02-24 16:29:00 +00:00
if ( p - > sys_ind & & ! IS_EXTENDED ( p - > sys_ind ) ) {
2002-11-26 22:00:21 +00:00
check_consistency ( p , i ) ;
if ( get_partition_start ( pe ) < first [ i ] )
printf ( _ ( " Warning: bad start-of-data in "
" partition %d \n " ) , i + 1 ) ;
check ( i + 1 , p - > end_head , p - > end_sector , p - > end_cyl ,
last [ i ] ) ;
total + = last [ i ] + 1 - first [ i ] ;
for ( j = 0 ; j < i ; j + + )
if ( ( first [ i ] > = first [ j ] & & first [ i ] < = last [ j ] )
| | ( ( last [ i ] < = last [ j ] & & last [ i ] > = first [ j ] ) ) ) {
printf ( _ ( " Warning: partition %d overlaps "
" partition %d. \n " ) , j + 1 , i + 1 ) ;
total + = first [ i ] > = first [ j ] ?
first [ i ] : first [ j ] ;
total - = last [ i ] < = last [ j ] ?
last [ i ] : last [ j ] ;
}
}
}
if ( extended_offset ) {
struct pte * pex = & ptes [ ext_index ] ;
2004-06-28 23:50:31 +00:00
off_t e_last = get_start_sect ( pex - > part_table ) +
2002-11-26 22:00:21 +00:00
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 > heads * sectors * cylinders )
printf ( _ ( " Total allocated sectors %d greater than the maximum "
" %d \n " ) , total , heads * sectors * cylinders ) ;
else if ( ( total = heads * sectors * cylinders - total ) ! = 0 )
printf ( _ ( " %d unallocated sectors \n " ) , total ) ;
}
static void
2006-02-24 16:29:00 +00:00
add_partition ( int n , int sys )
{
2002-11-26 22:00:21 +00:00
char mesg [ 256 ] ; /* 48 does not suffice in Japanese */
2006-05-26 01:48:17 +00:00
int i , num_read = 0 ;
2002-11-26 22:00:21 +00:00
struct partition * p = ptes [ n ] . part_table ;
struct partition * q = ptes [ ext_index ] . part_table ;
2003-07-30 08:40:37 +00:00
long long llimit ;
2004-06-28 23:50:31 +00:00
off_t start , stop = 0 , limit , temp ,
2002-11-26 22:00:21 +00:00
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 ;
2003-07-30 08:40:37 +00:00
if ( display_in_cyl_units | | ! total_number_of_sectors )
llimit = heads * sectors * cylinders - 1 ;
2002-11-26 22:00:21 +00:00
else
2003-07-30 08:40:37 +00:00
llimit = total_number_of_sectors - 1 ;
limit = llimit ;
if ( limit ! = llimit )
limit = 0x7fffffff ;
2002-11-26 22:00:21 +00:00
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 {
temp = start ;
for ( i = 0 ; i < partitions ; i + + ) {
int lastplusoff ;
if ( start = = ptes [ i ] . offset )
start + = sector_offset ;
2006-02-24 16:29:00 +00:00
lastplusoff = last [ i ] + ( ( n < 4 ) ? 0 : sector_offset ) ;
2002-11-26 22:00:21 +00:00
if ( start > = first [ i ] & & start < = lastplusoff )
start = lastplusoff + 1 ;
}
if ( start > limit )
break ;
2006-05-26 01:48:17 +00:00
if ( start > = temp + units_per_sector & & num_read ) {
2004-06-28 23:50:31 +00:00
printf ( _ ( " Sector %llu is already allocated \n " ) , ( unsigned long long ) temp ) ;
2002-11-26 22:00:21 +00:00
temp = start ;
2006-05-26 01:48:17 +00:00
num_read = 0 ;
2002-11-26 22:00:21 +00:00
}
2006-05-26 01:48:17 +00:00
if ( ! num_read & & start = = temp ) {
2004-06-28 23:50:31 +00:00
off_t saved_start ;
2002-11-26 22:00:21 +00:00
saved_start = start ;
start = read_int ( cround ( saved_start ) , cround ( saved_start ) , cround ( limit ) ,
0 , mesg ) ;
if ( display_in_cyl_units ) {
start = ( start - 1 ) * units_per_sector ;
if ( start < saved_start ) start = saved_start ;
}
2006-05-26 01:48:17 +00:00
num_read = 1 ;
2002-11-26 22:00:21 +00:00
}
2006-05-26 01:48:17 +00:00
} while ( start ! = temp | | ! num_read ) ;
2002-11-26 22:00:21 +00:00
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 {
snprintf ( mesg , sizeof ( mesg ) ,
_ ( " Last %s or +size or +sizeM or +sizeK " ) ,
str_units ( SINGULAR ) ) ;
stop = read_int ( cround ( start ) , cround ( limit ) , cround ( limit ) ,
cround ( start ) , mesg ) ;
if ( display_in_cyl_units ) {
stop = stop * units_per_sector - 1 ;
if ( stop > limit )
stop = limit ;
}
}
set_partition ( n , 0 , start , stop , sys ) ;
if ( n > 4 )
set_partition ( n - 1 , 1 , ptes [ n ] . offset , stop , EXTENDED ) ;
2006-02-24 16:29:00 +00:00
if ( IS_EXTENDED ( sys ) ) {
2002-11-26 22:00:21 +00:00
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 , sector_size ) ;
pe4 - > part_table = pt_offset ( pe4 - > sectorbuffer , 0 ) ;
pe4 - > ext_pointer = pe4 - > part_table + 1 ;
pe4 - > changed = 1 ;
partitions = 5 ;
}
}
static void
2006-02-24 16:29:00 +00:00
add_logical ( void )
{
2002-11-26 22:00:21 +00:00
if ( partitions > 5 | | ptes [ 4 ] . part_table - > sys_ind ) {
struct pte * pe = & ptes [ partitions ] ;
pe - > sectorbuffer = xcalloc ( 1 , sector_size ) ;
pe - > part_table = pt_offset ( pe - > sectorbuffer , 0 ) ;
pe - > ext_pointer = pe - > part_table + 1 ;
pe - > offset = 0 ;
pe - > changed = 1 ;
partitions + + ;
}
add_partition ( partitions - 1 , LINUX_NATIVE ) ;
}
static void
2006-02-24 16:29:00 +00:00
new_partition ( void )
{
2002-11-26 22:00:21 +00:00
int i , free_primary = 0 ;
if ( warn_geometry ( ) )
return ;
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type ) {
2002-11-26 22:00:21 +00:00
add_sun_partition ( get_partition ( 0 , partitions ) , LINUX_NATIVE ) ;
return ;
}
# endif
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sgi = = current_label_type ) {
2002-11-26 22:00:21 +00:00
sgi_add_partition ( get_partition ( 0 , partitions ) , LINUX_NATIVE ) ;
return ;
}
# endif
# ifdef CONFIG_FEATURE_AIX_LABEL
2006-02-25 03:46:10 +00:00
if ( label_aix = = current_label_type ) {
2002-11-26 22:00:21 +00:00
printf ( _ ( " \t Sorry - this fdisk cannot handle AIX disk labels. "
" \n \t If you want to add DOS-type partitions, create "
" \n \t a new empty DOS partition table first. (Use o.) "
" \n \t WARNING: "
" This will destroy the present disk contents. \n " ) ) ;
return ;
}
# endif
for ( i = 0 ; i < 4 ; i + + )
free_primary + = ! ptes [ i ] . part_table - > sys_ind ;
2003-07-03 10:02:32 +00:00
2006-02-24 16:29:00 +00:00
if ( ! free_primary & & partitions > = MAXIMUM_PARTS ) {
2004-05-19 10:49:17 +00:00
printf ( _ ( " The maximum number of partitions has been created \n " ) ) ;
return ;
2006-02-24 16:29:00 +00:00
}
2003-07-03 10:02:32 +00:00
2002-11-26 22:00:21 +00:00
if ( ! free_primary ) {
if ( extended_offset )
add_logical ( ) ;
else
printf ( _ ( " You must delete some partition and add "
" an extended partition first \n " ) ) ;
} else {
char c , line [ LINE_LENGTH ] ;
snprintf ( line , sizeof ( line ) , " %s \n %s \n p primary "
" partition (1-4) \n " ,
" Command action " , ( extended_offset ?
" l logical (5 or over) " : " e extended " ) ) ;
while ( 1 ) {
if ( ( c = read_char ( line ) ) = = ' p ' | | c = = ' P ' ) {
i = get_nonexisting_partition ( 0 , 4 ) ;
if ( i > = 0 )
add_partition ( i , LINUX_NATIVE ) ;
return ;
}
else if ( c = = ' l ' & & extended_offset ) {
add_logical ( ) ;
return ;
}
else if ( c = = ' e ' & & ! extended_offset ) {
i = get_nonexisting_partition ( 0 , 4 ) ;
if ( i > = 0 )
add_partition ( i , EXTENDED ) ;
return ;
}
else
printf ( _ ( " Invalid partition number "
" for type `%c' \n " ) , c ) ;
}
}
}
static void
2006-02-24 16:29:00 +00:00
write_table ( void )
{
2002-11-26 22:00:21 +00:00
int i ;
2006-02-25 03:46:10 +00:00
if ( label_dos = = current_label_type ) {
2006-02-24 16:29:00 +00:00
for ( i = 0 ; i < 3 ; i + + )
2002-11-26 22:00:21 +00:00
if ( ptes [ i ] . changed )
ptes [ 3 ] . changed = 1 ;
for ( i = 3 ; i < partitions ; i + + ) {
struct pte * pe = & ptes [ i ] ;
if ( pe - > changed ) {
write_part_table_flag ( pe - > sectorbuffer ) ;
write_sector ( pe - > offset , pe - > sectorbuffer ) ;
}
}
}
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
else if ( label_sgi = = current_label_type ) {
2002-11-26 22:00:21 +00:00
/* no test on change? the printf below might be mistaken */
sgi_write_table ( ) ;
}
# endif
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
else if ( label_sun = = current_label_type ) {
2002-11-26 22:00:21 +00:00
int needw = 0 ;
2006-02-24 16:29:00 +00:00
for ( i = 0 ; i < 8 ; i + + )
2002-11-26 22:00:21 +00:00
if ( ptes [ i ] . changed )
needw = 1 ;
if ( needw )
sun_write_table ( ) ;
}
# endif
printf ( _ ( " The partition table has been altered! \n \n " ) ) ;
reread_partition_table ( 1 ) ;
}
2006-02-24 16:29:00 +00:00
static void
reread_partition_table ( int leave )
{
2002-11-26 22:00:21 +00:00
int error = 0 ;
int i ;
printf ( _ ( " Calling ioctl() to re-read partition table. \n " ) ) ;
sync ( ) ;
sleep ( 2 ) ;
if ( ( i = ioctl ( fd , BLKRRPART ) ) ! = 0 ) {
error = errno ;
} else {
/* some kernel versions (1.2.x) seem to have trouble
rereading the partition table , but if asked to do it
twice , the second time works . - biro @ yggdrasil . com */
sync ( ) ;
sleep ( 2 ) ;
if ( ( i = ioctl ( fd , BLKRRPART ) ) ! = 0 )
error = errno ;
}
if ( i ) {
printf ( _ ( " \n WARNING: Re-reading the partition table "
" failed with error %d: %s. \n "
" The kernel still uses the old table. \n "
" The new table will be used "
" at the next reboot. \n " ) ,
error , strerror ( error ) ) ;
}
if ( dos_changed )
2006-02-24 16:29:00 +00:00
printf (
2002-11-26 22:00:21 +00:00
_ ( " \n WARNING: 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 ) {
close ( fd ) ;
printf ( _ ( " Syncing disks. \n " ) ) ;
sync ( ) ;
sleep ( 4 ) ; /* for sync() */
exit ( ! ! i ) ;
}
}
2003-01-04 11:56:06 +00:00
# endif /* CONFIG_FEATURE_FDISK_WRITABLE */
2002-11-26 22:00:21 +00:00
# ifdef CONFIG_FEATURE_FDISK_ADVANCED
# define MAX_PER_LINE 16
static void
2006-02-24 16:29:00 +00:00
print_buffer ( char * pbuffer )
{
int i , l ;
2002-11-26 22:00:21 +00:00
for ( i = 0 , l = 0 ; i < sector_size ; i + + , l + + ) {
if ( l = = 0 )
printf ( " 0x%03X: " , i ) ;
printf ( " %02X " , ( unsigned char ) pbuffer [ i ] ) ;
if ( l = = MAX_PER_LINE - 1 ) {
printf ( " \n " ) ;
l = - 1 ;
}
}
if ( l > 0 )
printf ( " \n " ) ;
printf ( " \n " ) ;
}
static void
2006-02-24 16:29:00 +00:00
print_raw ( void )
{
2002-11-26 22:00:21 +00:00
int i ;
printf ( _ ( " Device: %s \n " ) , disk_device ) ;
# if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type | | label_sgi = = current_label_type )
2002-11-26 22:00:21 +00:00
print_buffer ( MBRbuffer ) ;
else
# endif
for ( i = 3 ; i < partitions ; i + + )
print_buffer ( ptes [ i ] . sectorbuffer ) ;
}
static void
2006-02-24 16:29:00 +00:00
move_begin ( int i )
{
2002-11-26 22:00:21 +00:00
struct pte * pe = & ptes [ i ] ;
struct partition * p = pe - > part_table ;
2004-06-28 23:50:31 +00:00
off_t new , first ;
2002-11-26 22:00:21 +00:00
if ( warn_geometry ( ) )
return ;
2006-02-24 16:29:00 +00:00
if ( ! p - > sys_ind | | ! get_nr_sects ( p ) | | IS_EXTENDED ( p - > sys_ind ) ) {
2002-11-26 22:00:21 +00:00
printf ( _ ( " Partition %d has no data area \n " ) , i + 1 ) ;
return ;
}
first = get_partition_start ( pe ) ;
new = read_int ( first , first , first + get_nr_sects ( p ) - 1 , first ,
2006-02-24 16:29:00 +00:00
_ ( " New beginning of data " ) ) - pe - > offset ;
2002-11-26 22:00:21 +00:00
if ( new ! = get_nr_sects ( p ) ) {
first = get_nr_sects ( p ) + get_start_sect ( p ) - new ;
set_nr_sects ( p , first ) ;
set_start_sect ( p , new ) ;
pe - > changed = 1 ;
}
}
static void
2006-02-24 16:29:00 +00:00
xselect ( void )
{
2002-11-26 22:00:21 +00:00
char c ;
2006-02-24 16:29:00 +00:00
while ( 1 ) {
2002-11-26 22:00:21 +00:00
putchar ( ' \n ' ) ;
c = tolower ( read_char ( _ ( " Expert command (m for help): " ) ) ) ;
switch ( c ) {
case ' a ' :
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type )
2002-11-26 22:00:21 +00:00
sun_set_alt_cyl ( ) ;
# endif
break ;
case ' b ' :
2006-02-25 03:46:10 +00:00
if ( label_dos = = current_label_type )
2002-11-26 22:00:21 +00:00
move_begin ( get_partition ( 0 , partitions ) ) ;
break ;
case ' c ' :
user_cylinders = cylinders =
read_int ( 1 , cylinders , 1048576 , 0 ,
2006-02-24 16:29:00 +00:00
_ ( " Number of cylinders " ) ) ;
2002-11-26 22:00:21 +00:00
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type )
2002-11-26 22:00:21 +00:00
sun_set_ncyl ( cylinders ) ;
# endif
2006-02-25 03:46:10 +00:00
if ( label_dos = = current_label_type )
2002-11-26 22:00:21 +00:00
warn_cylinders ( ) ;
break ;
case ' d ' :
print_raw ( ) ;
break ;
case ' e ' :
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sgi = = current_label_type )
2002-11-26 22:00:21 +00:00
sgi_set_xcyl ( ) ;
2006-02-25 03:46:10 +00:00
else
2002-11-26 22:00:21 +00:00
# endif
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type )
2002-11-26 22:00:21 +00:00
sun_set_xcyl ( ) ;
else
# endif
2006-02-25 03:46:10 +00:00
if ( label_dos = = current_label_type )
2002-11-26 22:00:21 +00:00
x_list_table ( 1 ) ;
break ;
case ' f ' :
2006-02-25 03:46:10 +00:00
if ( label_dos = = current_label_type )
2002-11-26 22:00:21 +00:00
fix_partition_table_order ( ) ;
break ;
case ' g ' :
# ifdef CONFIG_FEATURE_SGI_LABEL
create_sgilabel ( ) ;
# endif
break ;
case ' h ' :
user_heads = heads = read_int ( 1 , heads , 256 , 0 ,
2006-02-24 16:29:00 +00:00
_ ( " Number of heads " ) ) ;
2002-11-26 22:00:21 +00:00
update_units ( ) ;
break ;
case ' i ' :
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type )
2002-11-26 22:00:21 +00:00
sun_set_ilfact ( ) ;
# endif
break ;
case ' o ' :
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type )
2002-11-26 22:00:21 +00:00
sun_set_rspeed ( ) ;
# endif
break ;
case ' p ' :
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type )
2002-11-26 22:00:21 +00:00
list_table ( 1 ) ;
else
# endif
x_list_table ( 0 ) ;
break ;
case ' q ' :
close ( fd ) ;
printf ( " \n " ) ;
exit ( 0 ) ;
case ' r ' :
return ;
case ' s ' :
user_sectors = sectors = read_int ( 1 , sectors , 63 , 0 ,
_ ( " Number of sectors " ) ) ;
if ( dos_compatible_flag ) {
sector_offset = sectors ;
fprintf ( stderr , _ ( " Warning: setting "
" sector offset for DOS "
" compatiblity \n " ) ) ;
}
update_units ( ) ;
break ;
case ' v ' :
verify ( ) ;
break ;
case ' w ' :
write_table ( ) ; /* does not return */
break ;
case ' y ' :
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sun = = current_label_type )
2002-11-26 22:00:21 +00:00
sun_set_pcylcount ( ) ;
# endif
break ;
default :
xmenu ( ) ;
}
}
}
# endif /* ADVANCED mode */
static int
2006-02-24 16:29:00 +00:00
is_ide_cdrom_or_tape ( const char * device )
{
2002-11-26 22:00:21 +00:00
FILE * procf ;
char buf [ 100 ] ;
struct stat statbuf ;
int is_ide = 0 ;
/* No device was given explicitly, and we are trying some
likely things . But opening / dev / hdc may produce errors like
" hdc: tray open or drive not ready "
if it happens to be a CD - ROM drive . It even happens that
the process hangs on the attempt to read a music CD .
So try to be careful . This only works since 2.1 .73 . */
if ( strncmp ( " /dev/hd " , device , 7 ) )
return 0 ;
snprintf ( buf , sizeof ( buf ) , " /proc/ide/%s/media " , device + 5 ) ;
procf = fopen ( buf , " r " ) ;
if ( procf ! = NULL & & fgets ( buf , sizeof ( buf ) , procf ) )
is_ide = ( ! strncmp ( buf , " cdrom " , 5 ) | |
! strncmp ( buf , " tape " , 4 ) ) ;
else
/* Now when this proc file does not exist, skip the
device when it is read - only . */
if ( stat ( device , & statbuf ) = = 0 )
is_ide = ( ( statbuf . st_mode & 0222 ) = = 0 ) ;
if ( procf )
fclose ( procf ) ;
return is_ide ;
}
2006-02-25 03:46:10 +00:00
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
try ( const char * device , int user_specified )
{
2002-11-26 22:00:21 +00:00
int gb ;
disk_device = device ;
if ( setjmp ( listingbuf ) )
return ;
if ( ! user_specified )
if ( is_ide_cdrom_or_tape ( device ) )
return ;
if ( ( fd = open ( disk_device , type_open ) ) > = 0 ) {
gb = get_boot ( try_only ) ;
if ( gb > 0 ) { /* I/O error */
close ( fd ) ;
} else if ( gb < 0 ) { /* no DOS signature */
list_disk_geometry ( ) ;
2006-02-25 03:46:10 +00:00
if ( label_aix = = current_label_type ) {
2002-11-26 22:00:21 +00:00
return ;
2006-02-25 03:46:10 +00:00
}
2002-11-26 22:00:21 +00:00
# ifdef CONFIG_FEATURE_OSF_LABEL
if ( btrydev ( device ) < 0 )
# endif
fprintf ( stderr ,
_ ( " Disk %s doesn't contain a valid "
2006-02-24 16:29:00 +00:00
" partition table \n " ) , device ) ;
2002-11-26 22:00:21 +00:00
close ( fd ) ;
} else {
close ( fd ) ;
list_table ( 0 ) ;
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2006-02-25 03:46:10 +00:00
if ( label_sun ! = current_label_type & & partitions > 4 ) {
2002-11-26 22:00:21 +00:00
delete_partition ( ext_index ) ;
2006-02-25 03:46:10 +00:00
}
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
}
} else {
/* Ignore other errors, since we try IDE
and SCSI hard disks which may not be
installed on the system . */
if ( errno = = EACCES ) {
fprintf ( stderr , _ ( " Cannot open %s \n " ) , device ) ;
return ;
}
}
}
/* for fdisk -l: try all things in /proc/partitions
that look like a partition name ( do not end in a digit ) */
static void
2006-02-24 16:29:00 +00:00
tryprocpt ( void )
{
2002-11-26 22:00:21 +00:00
FILE * procpt ;
char line [ 100 ] , ptname [ 100 ] , devname [ 120 ] , * s ;
int ma , mi , sz ;
2003-03-19 09:13:01 +00:00
procpt = bb_wfopen ( PROC_PARTITIONS , " r " ) ;
2002-11-26 22:00:21 +00:00
while ( fgets ( line , sizeof ( line ) , procpt ) ) {
2006-02-24 16:29:00 +00:00
if ( sscanf ( line , " %d %d %d %[^ \n ] " ,
& ma , & mi , & sz , ptname ) ! = 4 )
2002-11-26 22:00:21 +00:00
continue ;
for ( s = ptname ; * s ; s + + ) ;
if ( isdigit ( s [ - 1 ] ) )
continue ;
2003-01-04 11:56:06 +00:00
sprintf ( devname , " /dev/%s " , ptname ) ;
2002-11-26 22:00:21 +00:00
try ( devname , 0 ) ;
}
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_CLEAN_UP
2002-11-26 22:00:21 +00:00
fclose ( procpt ) ;
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
}
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
static void
2006-02-24 16:29:00 +00:00
unknown_command ( int c )
{
2002-11-26 22:00:21 +00:00
printf ( _ ( " %c: unknown command \n " ) , c ) ;
}
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
2006-02-24 16:29:00 +00:00
int fdisk_main ( int argc , char * * argv )
{
2003-01-04 11:56:06 +00:00
int c ;
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
int optl = 0 ;
# endif
# ifdef CONFIG_FEATURE_FDISK_BLKSIZE
int opts = 0 ;
# endif
2002-11-26 22:00:21 +00:00
/*
* Calls :
* fdisk - v
* fdisk - l [ - b sectorsize ] [ - u ] device . . .
* fdisk - s [ partition ] . . .
* fdisk [ - b sectorsize ] [ - u ] device
*
* Options - C , - H , - S set the geometry .
*
*/
2003-01-04 11:56:06 +00:00
while ( ( c = getopt ( argc , argv , " b:C:H:lS:uvV "
# ifdef CONFIG_FEATURE_FDISK_BLKSIZE
" s "
# endif
) ) ! = - 1 ) {
2002-11-26 22:00:21 +00:00
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 = atoi ( optarg ) ;
if ( sector_size ! = 512 & & sector_size ! = 1024 & &
2006-02-24 16:29:00 +00:00
sector_size ! = 2048 )
2003-03-19 09:13:01 +00:00
bb_show_usage ( ) ;
2002-11-26 22:00:21 +00:00
sector_offset = 2 ;
user_set_sector_size = 1 ;
break ;
case ' C ' :
user_cylinders = atoi ( optarg ) ;
break ;
case ' H ' :
user_heads = atoi ( optarg ) ;
if ( user_heads < = 0 | | user_heads > = 256 )
user_heads = 0 ;
break ;
case ' S ' :
user_sectors = atoi ( optarg ) ;
if ( user_sectors < = 0 | | user_sectors > = 64 )
user_sectors = 0 ;
break ;
case ' l ' :
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
optl = 1 ;
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
break ;
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_BLKSIZE
2002-11-26 22:00:21 +00:00
case ' s ' :
opts = 1 ;
break ;
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
case ' u ' :
display_in_cyl_units = 0 ;
break ;
case ' V ' :
case ' v ' :
printf ( " fdisk v " UTIL_LINUX_VERSION " \n " ) ;
return 0 ;
default :
2003-03-19 09:13:01 +00:00
bb_show_usage ( ) ;
2002-11-26 22:00:21 +00:00
}
}
#if 0
printf ( _ ( " This kernel finds the sector size itself - "
" -b option ignored \n " ) ) ;
# else
if ( user_set_sector_size & & argc - optind ! = 1 )
printf ( _ ( " Warning: the -b (set sector size) option should "
" be used with one specified device \n " ) ) ;
# endif
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
if ( optl ) {
nowarn = 1 ;
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
type_open = O_RDONLY ;
if ( argc > optind ) {
int k ;
# if __GNUC__
/* avoid gcc warning:
variable ` k ' might be clobbered by ` longjmp ' */
( void ) & k ;
# endif
listing = 1 ;
2006-02-24 16:29:00 +00:00
for ( k = optind ; k < argc ; k + + )
2002-11-26 22:00:21 +00:00
try ( argv [ k ] , 1 ) ;
} else {
/* we no longer have default device names */
/* but, we can use /proc/partitions instead */
tryprocpt ( ) ;
}
return 0 ;
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
}
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_BLKSIZE
2002-11-26 22:00:21 +00:00
if ( opts ) {
long size ;
2003-01-04 11:56:06 +00:00
int j ;
2002-11-26 22:00:21 +00:00
nowarn = 1 ;
type_open = O_RDONLY ;
opts = argc - optind ;
if ( opts < = 0 )
2003-03-19 09:13:01 +00:00
bb_show_usage ( ) ;
2002-11-26 22:00:21 +00:00
for ( j = optind ; j < argc ; j + + ) {
disk_device = argv [ j ] ;
if ( ( fd = open ( disk_device , type_open ) ) < 0 )
fdisk_fatal ( unable_to_open ) ;
if ( ioctl ( fd , BLKGETSIZE , & size ) )
fdisk_fatal ( ioctl_error ) ;
close ( fd ) ;
if ( opts = = 1 )
printf ( " %ld \n " , size / 2 ) ;
else
printf ( " %s: %ld \n " , argv [ j ] , size / 2 ) ;
}
return 0 ;
}
2003-01-04 11:56:06 +00:00
# endif
2002-11-26 22:00:21 +00:00
2003-01-04 11:56:06 +00:00
# ifdef CONFIG_FEATURE_FDISK_WRITABLE
2002-11-26 22:00:21 +00:00
if ( argc - optind = = 1 )
disk_device = argv [ optind ] ;
else
2003-03-19 09:13:01 +00:00
bb_show_usage ( ) ;
2002-11-26 22:00:21 +00:00
get_boot ( fdisk ) ;
# ifdef CONFIG_FEATURE_OSF_LABEL
2006-02-25 03:46:10 +00:00
if ( label_osf = = current_label_type ) {
2002-11-26 22:00:21 +00:00
/* OSF label, and no DOS label */
printf ( _ ( " Detected an OSF/1 disklabel on %s, entering "
" disklabel mode. \n " ) ,
2006-02-24 16:29:00 +00:00
disk_device ) ;
2002-11-26 22:00:21 +00:00
bselect ( ) ;
2006-02-25 03:46:10 +00:00
/*Why do we do this? It seems to be counter-intuitive*/
current_label_type = label_dos ;
2002-11-26 22:00:21 +00:00
/* If we return we may want to make an empty DOS label? */
}
# endif
while ( 1 ) {
putchar ( ' \n ' ) ;
c = tolower ( read_char ( _ ( " Command (m for help): " ) ) ) ;
switch ( c ) {
case ' a ' :
2006-02-25 03:46:10 +00:00
if ( label_dos = = current_label_type )
2002-11-26 22:00:21 +00:00
toggle_active ( get_partition ( 1 , partitions ) ) ;
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
else if ( label_sun = = current_label_type )
2002-11-26 22:00:21 +00:00
toggle_sunflags ( get_partition ( 1 , partitions ) ,
0x01 ) ;
# endif
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
else if ( label_sgi = = current_label_type )
2002-11-26 22:00:21 +00:00
sgi_set_bootpartition (
get_partition ( 1 , partitions ) ) ;
# endif
else
unknown_command ( c ) ;
break ;
case ' b ' :
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sgi = = current_label_type ) {
2002-11-26 22:00:21 +00:00
printf ( _ ( " \n The current boot file is: %s \n " ) ,
2006-02-24 16:29:00 +00:00
sgi_get_bootfile ( ) ) ;
2002-11-26 22:00:21 +00:00
if ( read_chars ( _ ( " Please enter the name of the "
2006-02-24 16:29:00 +00:00
" new boot file: " ) ) = = ' \n ' )
2002-11-26 22:00:21 +00:00
printf ( _ ( " Boot file unchanged \n " ) ) ;
else
sgi_set_bootfile ( line_ptr ) ;
} else
# endif
# ifdef CONFIG_FEATURE_OSF_LABEL
bselect ( ) ;
# endif
break ;
case ' c ' :
2006-02-25 03:46:10 +00:00
if ( label_dos = = current_label_type )
2002-11-26 22:00:21 +00:00
toggle_dos_compatibility_flag ( ) ;
# ifdef CONFIG_FEATURE_SUN_LABEL
2006-02-25 03:46:10 +00:00
else if ( label_sun = = current_label_type )
2002-11-26 22:00:21 +00:00
toggle_sunflags ( get_partition ( 1 , partitions ) ,
0x10 ) ;
# endif
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
else if ( label_sgi = = current_label_type )
2002-11-26 22:00:21 +00:00
sgi_set_swappartition (
get_partition ( 1 , partitions ) ) ;
# endif
else
unknown_command ( c ) ;
break ;
case ' d ' :
2003-01-04 11:56:06 +00:00
{
2003-07-30 08:40:37 +00:00
int j ;
# ifdef CONFIG_FEATURE_SGI_LABEL
/* If sgi_label then don't use get_existing_partition,
let the user select a partition , since
get_existing_partition ( ) only works for Linux - like
partition tables */
2006-02-25 03:46:10 +00:00
if ( label_sgi ! = current_label_type ) {
2003-07-30 08:40:37 +00:00
j = get_existing_partition ( 1 , partitions ) ;
} else {
j = get_partition ( 1 , partitions ) ;
}
# else
j = get_existing_partition ( 1 , partitions ) ;
# endif
2003-01-04 11:56:06 +00:00
if ( j > = 0 )
delete_partition ( j ) ;
}
2002-11-26 22:00:21 +00:00
break ;
case ' i ' :
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sgi = = current_label_type )
2002-11-26 22:00:21 +00:00
create_sgiinfo ( ) ;
else
# endif
unknown_command ( c ) ;
case ' l ' :
list_types ( get_sys_types ( ) ) ;
break ;
case ' m ' :
menu ( ) ;
break ;
case ' n ' :
new_partition ( ) ;
break ;
case ' o ' :
create_doslabel ( ) ;
break ;
case ' p ' :
list_table ( 0 ) ;
break ;
case ' q ' :
close ( fd ) ;
printf ( " \n " ) ;
return 0 ;
case ' s ' :
# ifdef CONFIG_FEATURE_SUN_LABEL
create_sunlabel ( ) ;
# endif
break ;
case ' t ' :
change_sysid ( ) ;
break ;
case ' u ' :
change_units ( ) ;
break ;
case ' v ' :
verify ( ) ;
break ;
case ' w ' :
write_table ( ) ; /* does not return */
break ;
# ifdef CONFIG_FEATURE_FDISK_ADVANCED
case ' x ' :
# ifdef CONFIG_FEATURE_SGI_LABEL
2006-02-25 03:46:10 +00:00
if ( label_sgi = = current_label_type ) {
2002-11-26 22:00:21 +00:00
fprintf ( stderr ,
_ ( " \n \t Sorry, no experts menu for SGI "
" partition tables available. \n \n " ) ) ;
} else
# endif
xselect ( ) ;
break ;
# endif
default :
unknown_command ( c ) ;
menu ( ) ;
}
}
return 0 ;
2003-01-04 11:56:06 +00:00
# endif /* CONFIG_FEATURE_FDISK_WRITABLE */
2002-11-26 22:00:21 +00:00
}