fdisk: separate sun/aix/etc code into #included files
This commit is contained in:
3414
util-linux/fdisk.c
3414
util-linux/fdisk.c
File diff suppressed because it is too large
Load Diff
76
util-linux/fdisk_aix.c
Normal file
76
util-linux/fdisk_aix.c
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#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:
|
||||||
|
* 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
|
||||||
|
* Internationalization
|
||||||
|
*
|
||||||
|
* 2003-03-20 Phillip Kesling <pkesling@sgi.com>
|
||||||
|
* Some fixes
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int aix_other_endian;
|
||||||
|
static short aix_volumes = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* only dealing with free blocks here
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
aix_info(void)
|
||||||
|
{
|
||||||
|
puts(
|
||||||
|
_("\n\tThere is a valid AIX label on this disk.\n"
|
||||||
|
"\tUnfortunately Linux cannot handle these\n"
|
||||||
|
"\tdisks at the moment. Nevertheless some\n"
|
||||||
|
"\tadvice:\n"
|
||||||
|
"\t1. fdisk will destroy its contents on write.\n"
|
||||||
|
"\t2. Be sure that this disk is NOT a still vital\n"
|
||||||
|
"\t part of a volume group. (Otherwise you may\n"
|
||||||
|
"\t erase the other disks as well, if unmirrored.)\n"
|
||||||
|
"\t3. Before deleting this physical volume be sure\n"
|
||||||
|
"\t to remove the disk logically from your AIX\n"
|
||||||
|
"\t machine. (Otherwise you become an AIXpert).")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_aix_label(void)
|
||||||
|
{
|
||||||
|
if (aixlabel->magic != AIX_LABEL_MAGIC &&
|
||||||
|
aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
|
||||||
|
current_label_type = 0;
|
||||||
|
aix_other_endian = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
|
||||||
|
update_units();
|
||||||
|
current_label_type = label_aix;
|
||||||
|
partitions = 1016;
|
||||||
|
aix_volumes = 15;
|
||||||
|
aix_info();
|
||||||
|
/*aix_nolabel();*/ /* %% */
|
||||||
|
/*aix_label = 1;*/ /* %% */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif /* AIX_LABEL */
|
1046
util-linux/fdisk_osf.c
Normal file
1046
util-linux/fdisk_osf.c
Normal file
File diff suppressed because it is too large
Load Diff
887
util-linux/fdisk_sgi.c
Normal file
887
util-linux/fdisk_sgi.c
Normal file
@ -0,0 +1,887 @@
|
|||||||
|
#ifdef CONFIG_FEATURE_SGI_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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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_partinfo { /* 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) \
|
||||||
|
: (uint16_t)(x))
|
||||||
|
#define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
|
||||||
|
: (uint32_t)(x))
|
||||||
|
|
||||||
|
#define sgilabel ((sgi_partition *)MBRbuffer)
|
||||||
|
#define sgiparam (sgilabel->devparam)
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static int sgi_other_endian;
|
||||||
|
static int debug;
|
||||||
|
static short sgi_volumes = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* only dealing with free blocks here
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int first;
|
||||||
|
unsigned int last;
|
||||||
|
} freeblocks;
|
||||||
|
static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
|
||||||
|
|
||||||
|
static void
|
||||||
|
setfreelist(int i, unsigned int f, unsigned int l)
|
||||||
|
{
|
||||||
|
freelist[i].first = f;
|
||||||
|
freelist[i].last = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add2freelist(unsigned int f, unsigned int l)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 17 ; i++)
|
||||||
|
if (freelist[i].last == 0)
|
||||||
|
break;
|
||||||
|
setfreelist(i, f, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clearfreelist(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 17 ; i++)
|
||||||
|
setfreelist(i, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
isinfreelist(unsigned int b)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 17 ; i++)
|
||||||
|
if (freelist[i].first <= b && freelist[i].last >= b)
|
||||||
|
return freelist[i].last;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* return last vacant block of this stride (never 0). */
|
||||||
|
/* the '>=' is not quite correct, but simplifies the code */
|
||||||
|
/*
|
||||||
|
* end of free blocks section
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const struct systypes sgi_sys_types[] = {
|
||||||
|
/* 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" },
|
||||||
|
/* SGI_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 }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
sgi_get_nsect(void)
|
||||||
|
{
|
||||||
|
return SGI_SSWAP16(sgilabel->devparam.nsect);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sgi_get_ntrks(void)
|
||||||
|
{
|
||||||
|
return SGI_SSWAP16(sgilabel->devparam.ntrks);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
unsigned int sum = 0;
|
||||||
|
|
||||||
|
size /= sizeof(unsigned int);
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
sum -= SGI_SSWAP32(base[i]);
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
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) {
|
||||||
|
current_label_type = label_dos;
|
||||||
|
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))) {
|
||||||
|
fprintf(stderr,
|
||||||
|
_("Detected sgi disklabel with wrong checksum.\n"));
|
||||||
|
}
|
||||||
|
update_units();
|
||||||
|
current_label_type = label_sgi;
|
||||||
|
partitions = 16;
|
||||||
|
sgi_volumes = 15;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
sgi_get_start_sector(int i)
|
||||||
|
{
|
||||||
|
return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
sgi_get_num_sectors(int i)
|
||||||
|
{
|
||||||
|
return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sgi_get_sysid(int i)
|
||||||
|
{
|
||||||
|
return SGI_SSWAP32(sgilabel->partitions[i].id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sgi_get_bootpartition(void)
|
||||||
|
{
|
||||||
|
return SGI_SSWAP16(sgilabel->boot_part);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sgi_get_swappartition(void)
|
||||||
|
{
|
||||||
|
return SGI_SSWAP16(sgilabel->swap_part);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sgi_list_table(int xtra)
|
||||||
|
{
|
||||||
|
int i, w, wd;
|
||||||
|
int kpi = 0; /* kernel partition ID */
|
||||||
|
|
||||||
|
if(xtra) {
|
||||||
|
printf(_("\nDisk %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( _("\nDisk %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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
w = strlen(disk_device);
|
||||||
|
wd = strlen(_("Device"));
|
||||||
|
if (w < wd)
|
||||||
|
w = wd;
|
||||||
|
|
||||||
|
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 -----\nBootfile: %s\n"
|
||||||
|
"----- Directory Entries -----\n"),
|
||||||
|
sgilabel->boot_file);
|
||||||
|
for (i = 0 ; i < sgi_volumes; i++) {
|
||||||
|
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;
|
||||||
|
|
||||||
|
printf(_("%2d: %-10s sector%5u size%8u\n"),
|
||||||
|
i, (char*)name, (unsigned int) start, (unsigned int) len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sgi_set_bootpartition(int i)
|
||||||
|
{
|
||||||
|
sgilabel->boot_part = SGI_SSWAP16(((short)i));
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
sgi_get_lastblock(void)
|
||||||
|
{
|
||||||
|
return heads * sectors * cylinders;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sgi_set_swappartition(int i)
|
||||||
|
{
|
||||||
|
sgilabel->swap_part = SGI_SSWAP16(((short)i));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sgi_check_bootfile(const char* aFile)
|
||||||
|
{
|
||||||
|
if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
|
||||||
|
printf(_("\nInvalid Bootfile!\n"
|
||||||
|
"\tThe bootfile must be an absolute non-zero pathname,\n"
|
||||||
|
"\te.g. \"/unix\" or \"/unix.save\".\n"));
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
if (strlen(aFile) > 16) {
|
||||||
|
printf(_("\n\tName of Bootfile too long: "
|
||||||
|
"16 bytes maximum.\n"));
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
if (aFile[0] != '/') {
|
||||||
|
printf(_("\n\tBootfile must have a "
|
||||||
|
"fully qualified pathname.\n"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
|
||||||
|
printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
|
||||||
|
"SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
|
||||||
|
/* filename is correct and did change */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0; /* filename did not change */
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
sgi_get_bootfile(void)
|
||||||
|
{
|
||||||
|
return (char*)sgilabel->boot_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sgi_set_bootfile(const char* aFile)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
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\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
create_sgiinfo(void)
|
||||||
|
{
|
||||||
|
/* 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));
|
||||||
|
strncpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static sgiinfo *fill_sgiinfo(void);
|
||||||
|
|
||||||
|
static void
|
||||||
|
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(
|
||||||
|
(unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (a == b)
|
||||||
|
return (d > c) ? 1 : (d == c) ? 0 : -1;
|
||||||
|
return (a > b) ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
verify_sgi(int verbose)
|
||||||
|
{
|
||||||
|
int Index[16]; /* list of valid partitions */
|
||||||
|
int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
|
||||||
|
int entire = 0, i = 0;
|
||||||
|
unsigned int start = 0;
|
||||||
|
long long gap = 0; /* count unused blocks */
|
||||||
|
unsigned int lastblock = sgi_get_lastblock();
|
||||||
|
|
||||||
|
clearfreelist();
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
if (sgi_get_num_sectors(i) != 0) {
|
||||||
|
Index[sortcount++] = i;
|
||||||
|
if (sgi_get_sysid(i) == SGI_ENTIRE_DISK) {
|
||||||
|
if (entire++ == 1) {
|
||||||
|
if (verbose)
|
||||||
|
printf(_("More than one entire disk entry present.\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sortcount == 0) {
|
||||||
|
if (verbose)
|
||||||
|
printf(_("No partitions defined\n"));
|
||||||
|
return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
|
||||||
|
}
|
||||||
|
qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
|
||||||
|
if (sgi_get_sysid(Index[0]) == SGI_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 "
|
||||||
|
"at block 0,\n"
|
||||||
|
"not at diskblock %d.\n"),
|
||||||
|
sgi_get_start_sector(Index[0]));
|
||||||
|
if (debug) /* I do not understand how some disks fulfil it */
|
||||||
|
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);
|
||||||
|
lastblock = sgi_get_num_sectors(Index[0]);
|
||||||
|
} else {
|
||||||
|
if (verbose)
|
||||||
|
printf(_("One Partition (#11) should cover the entire disk.\n"));
|
||||||
|
if (debug > 2)
|
||||||
|
printf("sysid=%d\tpartition=%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]) == SGI_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) {
|
||||||
|
if (verbose)
|
||||||
|
printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
|
||||||
|
lastblock - start, start, lastblock-1);
|
||||||
|
gap += lastblock - start;
|
||||||
|
add2freelist(start, lastblock);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Done with arithmetics
|
||||||
|
* Go for details now
|
||||||
|
*/
|
||||||
|
if (verbose) {
|
||||||
|
if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
|
||||||
|
printf(_("\nThe boot partition does not exist.\n"));
|
||||||
|
}
|
||||||
|
if (!sgi_get_num_sectors(sgi_get_swappartition())) {
|
||||||
|
printf(_("\nThe 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(_("\nThe swap partition has no swap type.\n"));
|
||||||
|
}
|
||||||
|
if (sgi_check_bootfile("/unix"))
|
||||||
|
printf(_("\tYou have chosen an unusual boot file name.\n"));
|
||||||
|
}
|
||||||
|
return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sgi_change_sysid(int i, int sys)
|
||||||
|
{
|
||||||
|
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 != SGI_ENTIRE_DISK) && (sys != SGI_VOLHDR))
|
||||||
|
&& (sgi_get_start_sector(i) < 1) ) {
|
||||||
|
read_maybe_empty(
|
||||||
|
_("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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns partition index of first entry marked as entire disk */
|
||||||
|
static int
|
||||||
|
sgi_entire(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
if (sgi_get_sysid(i) == SGI_VOLUME)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sgi_set_entire(void)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
for (n = 10; n < partitions; n++) {
|
||||||
|
if(!sgi_get_num_sectors(n) ) {
|
||||||
|
sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sgi_set_volhdr(void)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sgi_delete_partition(int i)
|
||||||
|
{
|
||||||
|
sgi_set_partition(i, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
if (display_in_cyl_units)
|
||||||
|
last *= units_per_sector;
|
||||||
|
else
|
||||||
|
last = last; /* align to cylinder if You know how ... */
|
||||||
|
if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_FEATURE_FDISK_ADVANCED
|
||||||
|
static void
|
||||||
|
create_sgilabel(void)
|
||||||
|
{
|
||||||
|
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"));
|
||||||
|
|
||||||
|
sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
|
||||||
|
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\tSTART=%d\tLENGTH=%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);
|
||||||
|
/* tracks/cylinder (heads) */
|
||||||
|
sgilabel->devparam.cmd_tag_queue_depth = (0);
|
||||||
|
sgilabel->devparam.unused0 = (0);
|
||||||
|
sgilabel->devparam.unused1 = SGI_SSWAP16(0);
|
||||||
|
sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
|
||||||
|
/* sectors/track */
|
||||||
|
sgilabel->devparam.bytes = SGI_SSWAP16(512);
|
||||||
|
sgilabel->devparam.ilfact = SGI_SSWAP16(1);
|
||||||
|
sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
|
||||||
|
IGNORE_ERRORS|RESEEK);
|
||||||
|
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_partinfo)*16 );
|
||||||
|
current_label_type = label_sgi;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sgi_set_xcyl(void)
|
||||||
|
{
|
||||||
|
/* do nothing in the beginning */
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_FEATURE_FDISK_ADVANCED */
|
||||||
|
|
||||||
|
/* _____________________________________________________________
|
||||||
|
*/
|
||||||
|
|
||||||
|
static sgiinfo *
|
||||||
|
fill_sgiinfo(void)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
#endif /* SGI_LABEL */
|
731
util-linux/fdisk_sun.c
Normal file
731
util-linux/fdisk_sun.c
Normal file
@ -0,0 +1,731 @@
|
|||||||
|
#ifdef CONFIG_FEATURE_SUN_LABEL
|
||||||
|
|
||||||
|
#define SUN_LABEL_MAGIC 0xDABE
|
||||||
|
#define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
|
||||||
|
#define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
|
||||||
|
: (uint16_t)(x))
|
||||||
|
#define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
|
||||||
|
: (uint32_t)(x))
|
||||||
|
|
||||||
|
/* Copied from linux/major.h */
|
||||||
|
#define FLOPPY_MAJOR 2
|
||||||
|
|
||||||
|
#define SCSI_IOCTL_GET_IDLUN 0x5382
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static int sun_other_endian;
|
||||||
|
static int scsi_disk;
|
||||||
|
static int floppy;
|
||||||
|
|
||||||
|
#ifndef IDE0_MAJOR
|
||||||
|
#define IDE0_MAJOR 3
|
||||||
|
#endif
|
||||||
|
#ifndef IDE1_MAJOR
|
||||||
|
#define IDE1_MAJOR 22
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
guess_device_type(void)
|
||||||
|
{
|
||||||
|
struct stat bootstat;
|
||||||
|
|
||||||
|
if (fstat(fd, &bootstat) < 0) {
|
||||||
|
scsi_disk = 0;
|
||||||
|
floppy = 0;
|
||||||
|
} else if (S_ISBLK(bootstat.st_mode)
|
||||||
|
&& (major(bootstat.st_rdev) == IDE0_MAJOR ||
|
||||||
|
major(bootstat.st_rdev) == IDE1_MAJOR)) {
|
||||||
|
scsi_disk = 0;
|
||||||
|
floppy = 0;
|
||||||
|
} else if (S_ISBLK(bootstat.st_mode)
|
||||||
|
&& major(bootstat.st_rdev) == FLOPPY_MAJOR) {
|
||||||
|
scsi_disk = 0;
|
||||||
|
floppy = 1;
|
||||||
|
} else {
|
||||||
|
scsi_disk = 1;
|
||||||
|
floppy = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct systypes sun_sys_types[] = {
|
||||||
|
{ "\x00" "Empty" }, /* 0 */
|
||||||
|
{ "\x01" "Boot" }, /* 1 */
|
||||||
|
{ "\x02" "SunOS root" }, /* 2 */
|
||||||
|
{ "\x03" "SunOS swap" }, /* SUNOS_SWAP */
|
||||||
|
{ "\x04" "SunOS usr" }, /* 4 */
|
||||||
|
{ "\x05" "Whole disk" }, /* SUN_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 */
|
||||||
|
/* New (2.2.x) raid partition with autodetect using persistent superblock */
|
||||||
|
{ "\xfd" "Linux raid autodetect" }, /* 0xfd */
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_sun_partition(int i, uint start, uint stop, int sysid)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
check_sun_label(void)
|
||||||
|
{
|
||||||
|
unsigned short *ush;
|
||||||
|
int csum;
|
||||||
|
|
||||||
|
if (sunlabel->magic != SUN_LABEL_MAGIC
|
||||||
|
&& sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
|
||||||
|
current_label_type = label_dos;
|
||||||
|
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();
|
||||||
|
current_label_type = label_sun;
|
||||||
|
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[] = {
|
||||||
|
{ "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},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct sun_predefined_drives *
|
||||||
|
sun_autoconfigure_scsi(void)
|
||||||
|
{
|
||||||
|
const struct sun_predefined_drives *p = NULL;
|
||||||
|
|
||||||
|
#ifdef SCSI_IOCTL_GET_IDLUN
|
||||||
|
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))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sprintf(buffer,
|
||||||
|
"Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
|
||||||
|
/* 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,
|
||||||
|
(id[0]>>16) & 0xff,
|
||||||
|
id[0] & 0xff,
|
||||||
|
(id[0]>>8) & 0xff
|
||||||
|
);
|
||||||
|
pfd = fopen("/proc/scsi/scsi", "r");
|
||||||
|
if (!pfd) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
while (fgets(buffer2, 2048, pfd)) {
|
||||||
|
if (strcmp(buffer, buffer2))
|
||||||
|
continue;
|
||||||
|
if (!fgets(buffer2, 2048, pfd))
|
||||||
|
break;
|
||||||
|
q = strstr(buffer2, "Vendor: ");
|
||||||
|
if (!q)
|
||||||
|
break;
|
||||||
|
q += 8;
|
||||||
|
vendor = q;
|
||||||
|
q = strstr(q, " ");
|
||||||
|
*q++ = '\0'; /* truncate vendor name */
|
||||||
|
q = strstr(q, "Model: ");
|
||||||
|
if (!q)
|
||||||
|
break;
|
||||||
|
*q = '\0';
|
||||||
|
q += 7;
|
||||||
|
model = q;
|
||||||
|
q = strstr(q, " Rev: ");
|
||||||
|
if (!q)
|
||||||
|
break;
|
||||||
|
*q = '\0';
|
||||||
|
for (i = 0; i < SIZE(sun_drives); i++) {
|
||||||
|
if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
|
||||||
|
continue;
|
||||||
|
if (!strstr(model, sun_drives[i].model))
|
||||||
|
continue;
|
||||||
|
printf(_("Autoconfigure found a %s%s%s\n"),
|
||||||
|
sun_drives[i].vendor,
|
||||||
|
(*sun_drives[i].vendor) ? " " : "",
|
||||||
|
sun_drives[i].model);
|
||||||
|
p = sun_drives + i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fclose(pfd);
|
||||||
|
#endif
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
create_sunlabel(void)
|
||||||
|
{
|
||||||
|
struct hd_geometry geometry;
|
||||||
|
unsigned int ndiv;
|
||||||
|
int i;
|
||||||
|
unsigned char c;
|
||||||
|
const struct sun_predefined_drives *p = NULL;
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
_("Building a new sun disklabel. Changes will remain in memory only,\n"
|
||||||
|
"until you decide to write them. After that, of course, the previous\n"
|
||||||
|
"content won't be recoverable.\n\n"));
|
||||||
|
sun_other_endian = BB_LITTLE_ENDIAN;
|
||||||
|
memset(MBRbuffer, 0, sizeof(MBRbuffer));
|
||||||
|
sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
|
||||||
|
if (!floppy) {
|
||||||
|
puts(_("Drive type\n"
|
||||||
|
" ? auto configure\n"
|
||||||
|
" 0 custom (with hardware detected defaults)"));
|
||||||
|
for (i = 0; i < SIZE(sun_drives); i++) {
|
||||||
|
printf(" %c %s%s%s\n",
|
||||||
|
i + 'a', sun_drives[i].vendor,
|
||||||
|
(*sun_drives[i].vendor) ? " " : "",
|
||||||
|
sun_drives[i].model);
|
||||||
|
}
|
||||||
|
while (1) {
|
||||||
|
c = read_nonempty(_("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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!p || floppy) {
|
||||||
|
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"));
|
||||||
|
if (cylinders)
|
||||||
|
cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
|
||||||
|
else
|
||||||
|
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")));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
|
||||||
|
"%s%s%s cyl %d alt %d hd %d sec %d",
|
||||||
|
p ? p->vendor : "", (p && *p->vendor) ? " " : "",
|
||||||
|
p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")),
|
||||||
|
cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
|
||||||
|
|
||||||
|
sunlabel->ntrks = SUN_SSWAP16(heads);
|
||||||
|
sunlabel->nsect = SUN_SSWAP16(sectors);
|
||||||
|
sunlabel->ncyl = SUN_SSWAP16(cylinders);
|
||||||
|
if (floppy)
|
||||||
|
set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
|
||||||
|
else {
|
||||||
|
if (cylinders * heads * sectors >= 150 * 2048) {
|
||||||
|
ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
|
||||||
|
} else
|
||||||
|
ndiv = cylinders * 2 / 3;
|
||||||
|
set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
|
||||||
|
set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
|
||||||
|
sunlabel->infos[1].flags |= 0x01; /* Not mountable */
|
||||||
|
}
|
||||||
|
set_sun_partition(2, 0, cylinders * heads * sectors, SUN_WHOLE_DISK);
|
||||||
|
{
|
||||||
|
unsigned short *ush = (unsigned short *)sunlabel;
|
||||||
|
unsigned short csum = 0;
|
||||||
|
while (ush < (unsigned short *)(&sunlabel->csum))
|
||||||
|
csum ^= *ush++;
|
||||||
|
sunlabel->csum = csum;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_all_unchanged();
|
||||||
|
set_changed(0);
|
||||||
|
get_boot(create_empty_sun);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
toggle_sunflags(int i, unsigned char mask)
|
||||||
|
{
|
||||||
|
if (sunlabel->infos[i].flags & mask)
|
||||||
|
sunlabel->infos[i].flags &= ~mask;
|
||||||
|
else
|
||||||
|
sunlabel->infos[i].flags |= mask;
|
||||||
|
set_changed(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
|
||||||
|
{
|
||||||
|
int i, continuous = 1;
|
||||||
|
|
||||||
|
*start = 0;
|
||||||
|
*stop = cylinders * heads * sectors;
|
||||||
|
for (i = 0; i < partitions; i++) {
|
||||||
|
if (sunlabel->partitions[i].num_sectors
|
||||||
|
&& sunlabel->infos[i].id
|
||||||
|
&& sunlabel->infos[i].id != SUN_WHOLE_DISK) {
|
||||||
|
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
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
verify_sun(void)
|
||||||
|
{
|
||||||
|
uint starts[8], lens[8], start, stop;
|
||||||
|
int i,j,k,starto,endo;
|
||||||
|
int array[8];
|
||||||
|
|
||||||
|
verify_sun_starts = starts;
|
||||||
|
fetch_sun(starts,lens,&start,&stop);
|
||||||
|
for (k = 0; k < 7; k++) {
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (k && (lens[i] % (heads * sectors))) {
|
||||||
|
printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
|
||||||
|
}
|
||||||
|
if (lens[i]) {
|
||||||
|
for (j = 0; j < i; j++)
|
||||||
|
if (lens[j]) {
|
||||||
|
if (starts[j] == starts[i]+lens[i]) {
|
||||||
|
starts[j] = starts[i]; lens[j] += lens[i];
|
||||||
|
lens[i] = 0;
|
||||||
|
} else if (starts[i] == starts[j]+lens[j]){
|
||||||
|
lens[j] += lens[i];
|
||||||
|
lens[i] = 0;
|
||||||
|
} else if (!k) {
|
||||||
|
if (starts[i] < starts[j]+lens[j]
|
||||||
|
&& starts[j] < starts[i]+lens[i]) {
|
||||||
|
starto = starts[i];
|
||||||
|
if (starts[j] > starto)
|
||||||
|
starto = starts[j];
|
||||||
|
endo = starts[i]+lens[i];
|
||||||
|
if (starts[j]+lens[j] < endo)
|
||||||
|
endo = starts[j]+lens[j];
|
||||||
|
printf(_("Partition %d overlaps with others in "
|
||||||
|
"sectors %d-%d\n"), i+1, starto, endo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (lens[i])
|
||||||
|
array[i] = i;
|
||||||
|
else
|
||||||
|
array[i] = -1;
|
||||||
|
}
|
||||||
|
qsort(array,SIZE(array),sizeof(array[0]),
|
||||||
|
(int (*)(const void *,const void *)) verify_sun_cmp);
|
||||||
|
if (array[0] == -1) {
|
||||||
|
printf(_("No partitions defined\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stop = cylinders * heads * sectors;
|
||||||
|
if (starts[array[0]])
|
||||||
|
printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
|
||||||
|
for (i = 0; i < 7 && array[i+1] != -1; i++) {
|
||||||
|
printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
|
||||||
|
}
|
||||||
|
start = starts[array[i]] + lens[array[i]];
|
||||||
|
if (start < stop)
|
||||||
|
printf(_("Unused gap - sectors %d-%d\n"),start,stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_sun_partition(int n, int sys)
|
||||||
|
{
|
||||||
|
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.\nDelete "
|
||||||
|
"some/shrink them before retry.\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
|
||||||
|
while (1) {
|
||||||
|
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)
|
||||||
|
printf("\
|
||||||
|
It is highly recommended that the third partition covers the whole disk\n\
|
||||||
|
and is of type `Whole disk'\n");
|
||||||
|
/* ewt asks to add: "don't start a partition at cyl 0"
|
||||||
|
However, edmundo@rano.demon.co.uk writes:
|
||||||
|
"In addition to having a Sun partition table, to be able to
|
||||||
|
boot from the disc, the first partition, /dev/sdX1, must
|
||||||
|
start at cylinder 0. This means that /dev/sdX1 contains
|
||||||
|
the partition table and the boot block, as these are the
|
||||||
|
first two sectors of the disc. Therefore you must be
|
||||||
|
careful what you use /dev/sdX1 for. In particular, you must
|
||||||
|
not use a partition starting at cylinder 0 for Linux swap,
|
||||||
|
as that would overwrite the partition table and the boot
|
||||||
|
block. You may, however, use such a partition for a UFS
|
||||||
|
or EXT2 file system, as these file systems leave the first
|
||||||
|
1024 bytes undisturbed. */
|
||||||
|
/* On the other hand, one should not use partitions
|
||||||
|
starting at block 0 in an md, or the label will
|
||||||
|
be trashed. */
|
||||||
|
for (i = 0; i < partitions; i++)
|
||||||
|
if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
|
||||||
|
break;
|
||||||
|
if (i < partitions && !whole_disk) {
|
||||||
|
if (n == 2 && !first) {
|
||||||
|
whole_disk = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf(_("Sector %d is already allocated\n"), first);
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stop = 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),
|
||||||
|
_("Last %s or +size or +sizeM or +sizeK"),
|
||||||
|
str_units(SINGULAR));
|
||||||
|
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) {
|
||||||
|
whole_disk = 1;
|
||||||
|
last = stop2;
|
||||||
|
} else if (last > stop) {
|
||||||
|
printf(_("You haven't covered the whole disk with "
|
||||||
|
"the 3rd partition, but your value\n"
|
||||||
|
"%d %s covers some other partition. "
|
||||||
|
"Your entry has been changed\n"
|
||||||
|
"to %d %s\n"),
|
||||||
|
scround(last), str_units(SINGULAR),
|
||||||
|
scround(stop), str_units(SINGULAR));
|
||||||
|
last = stop;
|
||||||
|
}
|
||||||
|
} else if (!whole_disk && last > stop)
|
||||||
|
last = stop;
|
||||||
|
|
||||||
|
if (whole_disk)
|
||||||
|
sys = SUN_WHOLE_DISK;
|
||||||
|
set_sun_partition(n, first, last, sys);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sun_delete_partition(int i)
|
||||||
|
{
|
||||||
|
unsigned int nsec;
|
||||||
|
|
||||||
|
if (i == 2
|
||||||
|
&& sunlabel->infos[i].id == SUN_WHOLE_DISK
|
||||||
|
&& !sunlabel->partitions[i].start_cylinder
|
||||||
|
&& (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
|
||||||
|
printf(_("If you want to maintain SunOS/Solaris compatibility, "
|
||||||
|
"consider leaving this\n"
|
||||||
|
"partition as Whole disk (5), starting at 0, with %u "
|
||||||
|
"sectors\n"), nsec);
|
||||||
|
sunlabel->infos[i].id = 0;
|
||||||
|
sunlabel->partitions[i].num_sectors = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sun_change_sysid(int i, int sys)
|
||||||
|
{
|
||||||
|
if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
|
||||||
|
read_maybe_empty(
|
||||||
|
_("It is highly recommended that the partition at offset 0\n"
|
||||||
|
"is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
|
||||||
|
"there may destroy your partition table and bootblock.\n"
|
||||||
|
"Type YES if you're very sure you would like that partition\n"
|
||||||
|
"tagged with 82 (Linux swap): "));
|
||||||
|
if (strcmp (line_ptr, _("YES\n")))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (sys) {
|
||||||
|
case SUNOS_SWAP:
|
||||||
|
case LINUX_SWAP:
|
||||||
|
/* swaps are not mountable by default */
|
||||||
|
sunlabel->infos[i].flags |= 0x01;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* assume other types are mountable;
|
||||||
|
user can change it anyway */
|
||||||
|
sunlabel->infos[i].flags &= ~0x01;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sunlabel->infos[i].id = sys;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sun_list_table(int xtra)
|
||||||
|
{
|
||||||
|
int i, w;
|
||||||
|
|
||||||
|
w = strlen(disk_device);
|
||||||
|
if (xtra)
|
||||||
|
printf(
|
||||||
|
_("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
|
||||||
|
"%d cylinders, %d alternate cylinders, %d physical cylinders\n"
|
||||||
|
"%d extra sects/cyl, interleave %d:1\n"
|
||||||
|
"%s\n"
|
||||||
|
"Units = %s of %d * 512 bytes\n\n"),
|
||||||
|
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);
|
||||||
|
else
|
||||||
|
printf(
|
||||||
|
_("\nDisk %s (Sun 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);
|
||||||
|
|
||||||
|
printf(_("%*s Flag Start End Blocks Id System\n"),
|
||||||
|
w + 1, _("Device"));
|
||||||
|
for (i = 0 ; i < partitions; i++) {
|
||||||
|
if (sunlabel->partitions[i].num_sectors) {
|
||||||
|
uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
|
||||||
|
uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
|
||||||
|
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 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_FEATURE_FDISK_ADVANCED
|
||||||
|
|
||||||
|
static void
|
||||||
|
sun_set_alt_cyl(void)
|
||||||
|
{
|
||||||
|
sunlabel->nacyl =
|
||||||
|
SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
|
||||||
|
_("Number of alternate cylinders")));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sun_set_ncyl(int cyl)
|
||||||
|
{
|
||||||
|
sunlabel->ncyl = SUN_SSWAP16(cyl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sun_set_xcyl(void)
|
||||||
|
{
|
||||||
|
sunlabel->sparecyl =
|
||||||
|
SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
|
||||||
|
_("Extra sectors per cylinder")));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sun_set_ilfact(void)
|
||||||
|
{
|
||||||
|
sunlabel->ilfact =
|
||||||
|
SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
|
||||||
|
_("Interleave factor")));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sun_set_rspeed(void)
|
||||||
|
{
|
||||||
|
sunlabel->rspeed =
|
||||||
|
SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
|
||||||
|
_("Rotation speed (rpm)")));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sun_set_pcylcount(void)
|
||||||
|
{
|
||||||
|
sunlabel->pcylcount =
|
||||||
|
SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
|
||||||
|
_("Number of physical cylinders")));
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_FEATURE_FDISK_ADVANCED */
|
||||||
|
|
||||||
|
static void
|
||||||
|
sun_write_table(void)
|
||||||
|
{
|
||||||
|
unsigned short *ush = (unsigned short *)sunlabel;
|
||||||
|
unsigned short csum = 0;
|
||||||
|
|
||||||
|
while (ush < (unsigned short *)(&sunlabel->csum))
|
||||||
|
csum ^= *ush++;
|
||||||
|
sunlabel->csum = csum;
|
||||||
|
if (lseek(fd, 0, SEEK_SET) < 0)
|
||||||
|
fdisk_fatal(unable_to_seek);
|
||||||
|
if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
|
||||||
|
fdisk_fatal(unable_to_write);
|
||||||
|
}
|
||||||
|
#endif /* SUN_LABEL */
|
Reference in New Issue
Block a user