2006-12-06 17:25:32 -06:00
|
|
|
/* fdisk.c -- Partition table manipulator for Linux.
|
|
|
|
*
|
|
|
|
* Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
|
|
|
|
*
|
|
|
|
* This program is free software. You can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation: either version 1 or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <setjmp.h>
|
|
|
|
#include <errno.h>
|
2006-12-06 17:25:35 -06:00
|
|
|
#include <getopt.h>
|
|
|
|
#include <sys/stat.h>
|
2008-01-16 12:53:56 -06:00
|
|
|
#include <sys/time.h>
|
2007-07-06 20:32:31 -05:00
|
|
|
#include <time.h>
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
#include "nls.h"
|
2007-11-07 12:05:31 -06:00
|
|
|
#include "blkdev.h"
|
2006-12-06 17:25:39 -06:00
|
|
|
#include "common.h"
|
2006-12-06 17:25:33 -06:00
|
|
|
#include "fdisk.h"
|
2006-12-06 17:25:37 -06:00
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
#include "fdisksunlabel.h"
|
2006-12-06 17:25:37 -06:00
|
|
|
#include "fdisksgilabel.h"
|
|
|
|
#include "fdiskaixlabel.h"
|
2007-06-27 16:49:56 -05:00
|
|
|
#include "fdiskmaclabel.h"
|
2006-12-06 17:25:37 -06:00
|
|
|
|
2006-12-06 17:26:54 -06:00
|
|
|
#ifdef HAVE_LINUX_COMPILER_H
|
|
|
|
#include <linux/compiler.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_LINUX_BLKPG_H
|
2006-12-06 17:25:39 -06:00
|
|
|
#include <linux/blkpg.h>
|
|
|
|
#endif
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2007-05-31 07:31:51 -05:00
|
|
|
#include "gpt.h"
|
|
|
|
|
2006-12-06 17:25:44 -06:00
|
|
|
static void delete_partition(int i);
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
#define hex_val(c) ({ \
|
|
|
|
char _c = (c); \
|
|
|
|
isdigit(_c) ? _c - '0' : \
|
|
|
|
tolower(_c) + 10 - 'a'; \
|
|
|
|
})
|
|
|
|
|
|
|
|
|
2006-12-06 17:25:46 -06:00
|
|
|
#define LINE_LENGTH 800
|
2006-12-06 17:25:43 -06:00
|
|
|
#define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
|
2006-12-06 17:25:32 -06:00
|
|
|
(n) * sizeof(struct partition)))
|
|
|
|
#define sector(s) ((s) & 0x3f)
|
|
|
|
#define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
|
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
#define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
|
2006-12-06 17:25:32 -06:00
|
|
|
((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; \
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
/* A valid partition table sector ends in 0x55 0xaa */
|
2006-12-06 17:25:43 -06:00
|
|
|
static unsigned int
|
2007-05-30 10:10:43 -05:00
|
|
|
part_table_flag(unsigned char *b) {
|
2006-12-06 17:26:12 -06:00
|
|
|
return ((unsigned int) b[510]) + (((unsigned int) b[511]) << 8);
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
valid_part_table_flag(unsigned char *b) {
|
|
|
|
return (b[510] == 0x55 && b[511] == 0xaa);
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
2007-05-30 10:10:43 -05:00
|
|
|
write_part_table_flag(unsigned char *b) {
|
2006-12-06 17:25:35 -06: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 */
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
2006-12-06 17:25:35 -06:00
|
|
|
store4_little_endian(unsigned char *cp, unsigned int val) {
|
|
|
|
cp[0] = (val & 0xff);
|
|
|
|
cp[1] = ((val >> 8) & 0xff);
|
|
|
|
cp[2] = ((val >> 16) & 0xff);
|
|
|
|
cp[3] = ((val >> 24) & 0xff);
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static unsigned int
|
2007-07-06 20:32:31 -05:00
|
|
|
read4_little_endian(const unsigned char *cp) {
|
2006-12-06 17:26:12 -06:00
|
|
|
return (unsigned int)(cp[0]) + ((unsigned int)(cp[1]) << 8)
|
|
|
|
+ ((unsigned int)(cp[2]) << 16)
|
|
|
|
+ ((unsigned int)(cp[3]) << 24);
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
2006-12-06 17:25:35 -06:00
|
|
|
set_start_sect(struct partition *p, unsigned int start_sect) {
|
|
|
|
store4_little_endian(p->start4, start_sect);
|
|
|
|
}
|
|
|
|
|
2007-05-30 10:10:43 -05:00
|
|
|
unsigned long long
|
2006-12-06 17:25:35 -06:00
|
|
|
get_start_sect(struct partition *p) {
|
|
|
|
return read4_little_endian(p->start4);
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
2007-05-30 10:10:43 -05:00
|
|
|
set_nr_sects(struct partition *p, unsigned long long nr_sects) {
|
2006-12-06 17:25:35 -06:00
|
|
|
store4_little_endian(p->size4, nr_sects);
|
|
|
|
}
|
|
|
|
|
2007-05-30 10:10:43 -05:00
|
|
|
unsigned long long
|
2006-12-06 17:25:35 -06:00
|
|
|
get_nr_sects(struct partition *p) {
|
|
|
|
return read4_little_endian(p->size4);
|
|
|
|
}
|
|
|
|
|
2007-07-06 20:32:31 -05:00
|
|
|
static ssize_t
|
|
|
|
xread(int fd, void *buf, size_t count) {
|
|
|
|
char *p = buf;
|
|
|
|
ssize_t out = 0;
|
|
|
|
ssize_t rv;
|
|
|
|
|
|
|
|
while (count) {
|
|
|
|
rv = read(fd, p, count);
|
|
|
|
if (rv == -1) {
|
|
|
|
if (errno == EINTR || errno == EAGAIN)
|
|
|
|
continue;
|
|
|
|
return out ? out : -1; /* Error */
|
|
|
|
} else if (rv == 0) {
|
|
|
|
return out; /* EOF */
|
|
|
|
}
|
|
|
|
|
|
|
|
p += rv;
|
|
|
|
out += rv;
|
|
|
|
count -= rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int
|
|
|
|
get_random_id(void) {
|
|
|
|
int fd;
|
|
|
|
unsigned int v;
|
|
|
|
ssize_t rv = -1;
|
2008-01-16 12:53:56 -06:00
|
|
|
struct timeval tv;
|
2007-07-06 20:32:31 -05:00
|
|
|
|
|
|
|
fd = open("/dev/urandom", O_RDONLY);
|
|
|
|
if (fd >= 0) {
|
|
|
|
rv = xread(fd, &v, sizeof v);
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rv == sizeof v)
|
|
|
|
return v;
|
|
|
|
|
|
|
|
/* Fallback: sucks, but better than nothing */
|
2008-01-16 12:53:56 -06:00
|
|
|
gettimeofday(&tv, NULL);
|
|
|
|
return (unsigned int)(tv.tv_sec + (tv.tv_usec << 12) + getpid());
|
2007-07-06 20:32:31 -05:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:33 -06:00
|
|
|
/* normally O_RDWR, -l option gives O_RDONLY */
|
|
|
|
static int type_open = O_RDWR;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
/*
|
|
|
|
* Raw disk label. For DOS-type partition tables the MBR,
|
|
|
|
* with descriptions of the primary partitions.
|
|
|
|
*/
|
2007-05-30 10:10:43 -05:00
|
|
|
unsigned char MBRbuffer[MAX_SECTOR_SIZE];
|
2006-12-06 17:25:43 -06: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.
|
|
|
|
*/
|
|
|
|
struct pte {
|
|
|
|
struct partition *part_table; /* points into sectorbuffer */
|
|
|
|
struct partition *ext_pointer; /* points into sectorbuffer */
|
2006-12-06 17:26:12 -06:00
|
|
|
char changed; /* boolean */
|
2007-05-30 10:10:43 -05:00
|
|
|
unsigned long long offset; /* disk sector number */
|
|
|
|
unsigned char *sectorbuffer; /* disk sector contents */
|
2006-12-06 17:25:43 -06:00
|
|
|
} ptes[MAXIMUM_PARTS];
|
|
|
|
|
2006-12-06 17:25:39 -06:00
|
|
|
char *disk_device, /* must be specified */
|
2006-12-06 17:25:32 -06:00
|
|
|
*line_ptr, /* interactive input */
|
2006-12-06 17:25:43 -06:00
|
|
|
line_buffer[LINE_LENGTH];
|
2006-12-06 17:25:32 -06:00
|
|
|
|
|
|
|
int fd, /* the disk */
|
|
|
|
ext_index, /* the prime extended partition */
|
|
|
|
listing = 0, /* no aborts for fdisk -l */
|
2006-12-06 17:25:35 -06:00
|
|
|
nowarn = 0, /* no warnings for fdisk -l/-s */
|
2006-12-06 17:25:32 -06:00
|
|
|
dos_compatible_flag = ~0,
|
2006-12-06 17:25:49 -06:00
|
|
|
dos_changed = 0,
|
2006-12-06 17:25:32 -06:00
|
|
|
partitions = 4; /* maximum partition + 1 */
|
|
|
|
|
2006-12-06 17:26:12 -06:00
|
|
|
unsigned int user_cylinders, user_heads, user_sectors;
|
|
|
|
unsigned int pt_heads, pt_sectors;
|
|
|
|
unsigned int kern_heads, kern_sectors;
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2007-05-30 10:10:43 -05:00
|
|
|
unsigned long long sector_offset = 1, extended_offset = 0, sectors;
|
|
|
|
|
2006-12-06 17:26:12 -06:00
|
|
|
unsigned int heads,
|
2006-12-06 17:25:32 -06:00
|
|
|
cylinders,
|
2006-12-06 17:25:37 -06:00
|
|
|
sector_size = DEFAULT_SECTOR_SIZE,
|
2006-12-06 17:25:44 -06:00
|
|
|
user_set_sector_size = 0,
|
2006-12-06 17:25:39 -06:00
|
|
|
units_per_sector = 1,
|
2007-05-30 10:10:43 -05:00
|
|
|
display_in_cyl_units = 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:26:12 -06:00
|
|
|
unsigned long long total_number_of_sectors;
|
2006-12-06 17:26:03 -06:00
|
|
|
|
2007-06-27 16:49:56 -05:00
|
|
|
#define dos_label (!sun_label && !sgi_label && !aix_label && !mac_label && !osf_label)
|
|
|
|
int sun_label = 0; /* looking at sun disklabel */
|
2006-12-06 17:25:37 -06:00
|
|
|
int sgi_label = 0; /* looking at sgi disklabel */
|
|
|
|
int aix_label = 0; /* looking at aix disklabel */
|
2006-12-06 17:25:58 -06:00
|
|
|
int osf_label = 0; /* looking at OSF/1 disklabel */
|
2007-06-27 16:49:56 -05:00
|
|
|
int mac_label = 0; /* looking at mac disklabel */
|
2006-12-06 17:25:58 -06:00
|
|
|
int possibly_osf_label = 0;
|
2006-12-06 17:25:56 -06:00
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
jmp_buf listingbuf;
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
void fatal(enum failure why) {
|
2006-12-06 17:25:32 -06:00
|
|
|
char error[LINE_LENGTH],
|
|
|
|
*message = error;
|
|
|
|
|
|
|
|
if (listing) {
|
|
|
|
close(fd);
|
|
|
|
longjmp(listingbuf, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (why) {
|
2006-12-06 17:25:39 -06:00
|
|
|
case usage: message = _(
|
|
|
|
"Usage: fdisk [-b SSZ] [-u] DISK Change partition table\n"
|
|
|
|
" fdisk -l [-b SSZ] [-u] DISK List partition table(s)\n"
|
|
|
|
" fdisk -s PARTITION Give partition size(s) in blocks\n"
|
|
|
|
" fdisk -v Give fdisk version\n"
|
2006-12-06 17:25:37 -06:00
|
|
|
"Here DISK is something like /dev/hdb or /dev/sda\n"
|
|
|
|
"and PARTITION is something like /dev/hda7\n"
|
|
|
|
"-u: give Start and End in sector (instead of cylinder) units\n"
|
2006-12-06 17:25:49 -06:00
|
|
|
"-b 2048: (for certain MO disks) use 2048-byte sectors\n");
|
2006-12-06 17:25:39 -06:00
|
|
|
break;
|
|
|
|
case usage2:
|
|
|
|
/* msg in cases where fdisk used to probe */
|
|
|
|
message = _(
|
|
|
|
"Usage: fdisk [-l] [-b SSZ] [-u] device\n"
|
|
|
|
"E.g.: fdisk /dev/hda (for the first IDE disk)\n"
|
|
|
|
" or: fdisk /dev/sdc (for the third SCSI disk)\n"
|
|
|
|
" or: fdisk /dev/eda (for the first PS/2 ESDI drive)\n"
|
|
|
|
" or: fdisk /dev/rd/c0d0 or: fdisk /dev/ida/c0d0 (for RAID devices)\n"
|
|
|
|
" ...\n");
|
2006-12-06 17:25:37 -06:00
|
|
|
break;
|
2006-12-06 17:25:32 -06:00
|
|
|
case unable_to_open:
|
2006-12-06 17:25:46 -06:00
|
|
|
snprintf(error, sizeof(error),
|
|
|
|
_("Unable to open %s\n"), disk_device);
|
2006-12-06 17:25:32 -06:00
|
|
|
break;
|
|
|
|
case unable_to_read:
|
2006-12-06 17:25:46 -06:00
|
|
|
snprintf(error, sizeof(error),
|
|
|
|
_("Unable to read %s\n"), disk_device);
|
2006-12-06 17:25:32 -06:00
|
|
|
break;
|
|
|
|
case unable_to_seek:
|
2006-12-06 17:25:46 -06:00
|
|
|
snprintf(error, sizeof(error),
|
|
|
|
_("Unable to seek on %s\n"),disk_device);
|
2006-12-06 17:25:32 -06:00
|
|
|
break;
|
|
|
|
case unable_to_write:
|
2006-12-06 17:25:46 -06:00
|
|
|
snprintf(error, sizeof(error),
|
|
|
|
_("Unable to write %s\n"), disk_device);
|
2006-12-06 17:25:39 -06:00
|
|
|
break;
|
|
|
|
case ioctl_error:
|
2006-12-06 17:25:46 -06:00
|
|
|
snprintf(error, sizeof(error),
|
|
|
|
_("BLKGETSIZE ioctl failed on %s\n"),
|
2006-12-06 17:25:39 -06:00
|
|
|
disk_device);
|
2006-12-06 17:25:32 -06:00
|
|
|
break;
|
|
|
|
case out_of_memory:
|
2006-12-06 17:25:39 -06:00
|
|
|
message = _("Unable to allocate any more memory\n");
|
2006-12-06 17:25:32 -06:00
|
|
|
break;
|
2006-12-06 17:25:46 -06:00
|
|
|
default:
|
|
|
|
message = _("Fatal error\n");
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fputc('\n', stderr);
|
|
|
|
fputs(message, stderr);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
2007-05-30 10:10:43 -05:00
|
|
|
seek_sector(int fd, unsigned long long secno) {
|
2006-12-06 17:27:13 -06:00
|
|
|
off_t offset = (off_t) secno * sector_size;
|
|
|
|
if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
|
2006-12-06 17:25:43 -06:00
|
|
|
fatal(unable_to_seek);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-05-30 10:10:43 -05:00
|
|
|
read_sector(int fd, unsigned long long secno, unsigned char *buf) {
|
2006-12-06 17:25:43 -06:00
|
|
|
seek_sector(fd, secno);
|
|
|
|
if (read(fd, buf, sector_size) != sector_size)
|
|
|
|
fatal(unable_to_read);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-05-30 10:10:43 -05:00
|
|
|
write_sector(int fd, unsigned long long secno, unsigned char *buf) {
|
2006-12-06 17:25:43 -06:00
|
|
|
seek_sector(fd, secno);
|
|
|
|
if (write(fd, buf, sector_size) != sector_size)
|
|
|
|
fatal(unable_to_write);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate a buffer and read a partition table sector */
|
|
|
|
static void
|
2007-05-30 10:10:43 -05:00
|
|
|
read_pte(int fd, int pno, unsigned long long offset) {
|
2006-12-06 17:25:43 -06:00
|
|
|
struct pte *pe = &ptes[pno];
|
|
|
|
|
|
|
|
pe->offset = offset;
|
2007-05-30 10:10:43 -05:00
|
|
|
pe->sectorbuffer = malloc(sector_size);
|
2006-12-06 17:25:43 -06:00
|
|
|
if (!pe->sectorbuffer)
|
|
|
|
fatal(out_of_memory);
|
|
|
|
read_sector(fd, offset, pe->sectorbuffer);
|
|
|
|
pe->changed = 0;
|
|
|
|
pe->part_table = pe->ext_pointer = NULL;
|
|
|
|
}
|
2006-12-06 17:25:46 -06:00
|
|
|
|
2007-05-30 10:10:43 -05:00
|
|
|
static unsigned long long
|
2006-12-06 17:25:43 -06:00
|
|
|
get_partition_start(struct pte *pe) {
|
|
|
|
return pe->offset + get_start_sect(pe->part_table);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct partition *
|
|
|
|
get_part_table(int i) {
|
|
|
|
return ptes[i].part_table;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
set_all_unchanged(void) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < MAXIMUM_PARTS; i++)
|
|
|
|
ptes[i].changed = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
set_changed(int i) {
|
|
|
|
ptes[i].changed = 1;
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:26:24 -06:00
|
|
|
static int
|
|
|
|
is_garbage_table(void) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
struct pte *pe = &ptes[i];
|
|
|
|
struct partition *p = pe->part_table;
|
|
|
|
|
|
|
|
if (p->boot_ind != 0 && p->boot_ind != 0x80)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:49 -06: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
|
|
|
|
is_dos_partition(int t) {
|
|
|
|
return (t == 1 || t == 4 || t == 6 ||
|
|
|
|
t == 0x0b || t == 0x0c || t == 0x0e ||
|
|
|
|
t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
|
|
|
|
t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
|
|
|
|
t == 0xc1 || t == 0xc4 || t == 0xc6);
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
menu(void) {
|
2006-12-06 17:25:39 -06:00
|
|
|
if (sun_label) {
|
|
|
|
puts(_("Command action"));
|
|
|
|
puts(_(" a toggle a read only flag")); /* sun */
|
|
|
|
puts(_(" b edit bsd disklabel"));
|
|
|
|
puts(_(" c toggle the mountable flag")); /* sun */
|
|
|
|
puts(_(" d delete a partition"));
|
|
|
|
puts(_(" l list known partition types"));
|
|
|
|
puts(_(" m print this menu"));
|
|
|
|
puts(_(" n add a new partition"));
|
|
|
|
puts(_(" o create a new empty DOS partition table"));
|
|
|
|
puts(_(" p print the partition table"));
|
|
|
|
puts(_(" q quit without saving changes"));
|
|
|
|
puts(_(" s create a new empty Sun disklabel")); /* sun */
|
|
|
|
puts(_(" t change a partition's system id"));
|
|
|
|
puts(_(" u change display/entry units"));
|
|
|
|
puts(_(" v verify the partition table"));
|
|
|
|
puts(_(" w write table to disk and exit"));
|
|
|
|
puts(_(" x extra functionality (experts only)"));
|
|
|
|
}
|
2006-12-06 17:25:58 -06:00
|
|
|
else if (sgi_label) {
|
2006-12-06 17:25:39 -06:00
|
|
|
puts(_("Command action"));
|
|
|
|
puts(_(" a select bootable partition")); /* sgi flavour */
|
|
|
|
puts(_(" b edit bootfile entry")); /* sgi */
|
|
|
|
puts(_(" c select sgi swap partition")); /* sgi flavour */
|
|
|
|
puts(_(" d delete a partition"));
|
|
|
|
puts(_(" l list known partition types"));
|
|
|
|
puts(_(" m print this menu"));
|
|
|
|
puts(_(" n add a new partition"));
|
|
|
|
puts(_(" o create a new empty DOS partition table"));
|
|
|
|
puts(_(" p print the partition table"));
|
|
|
|
puts(_(" q quit without saving changes"));
|
|
|
|
puts(_(" s create a new empty Sun disklabel")); /* sun */
|
|
|
|
puts(_(" t change a partition's system id"));
|
|
|
|
puts(_(" u change display/entry units"));
|
|
|
|
puts(_(" v verify the partition table"));
|
|
|
|
puts(_(" w write table to disk and exit"));
|
|
|
|
}
|
2007-06-27 16:49:56 -05:00
|
|
|
else if (aix_label || mac_label) {
|
2006-12-06 17:25:39 -06:00
|
|
|
puts(_("Command action"));
|
|
|
|
puts(_(" m print this menu"));
|
|
|
|
puts(_(" o create a new empty DOS partition table"));
|
|
|
|
puts(_(" q quit without saving changes"));
|
|
|
|
puts(_(" s create a new empty Sun disklabel")); /* sun */
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
puts(_("Command action"));
|
|
|
|
puts(_(" a toggle a bootable flag"));
|
|
|
|
puts(_(" b edit bsd disklabel"));
|
|
|
|
puts(_(" c toggle the dos compatibility flag"));
|
|
|
|
puts(_(" d delete a partition"));
|
|
|
|
puts(_(" l list known partition types"));
|
|
|
|
puts(_(" m print this menu"));
|
|
|
|
puts(_(" n add a new partition"));
|
|
|
|
puts(_(" o create a new empty DOS partition table"));
|
|
|
|
puts(_(" p print the partition table"));
|
|
|
|
puts(_(" q quit without saving changes"));
|
|
|
|
puts(_(" s create a new empty Sun disklabel")); /* sun */
|
|
|
|
puts(_(" t change a partition's system id"));
|
|
|
|
puts(_(" u change display/entry units"));
|
|
|
|
puts(_(" v verify the partition table"));
|
|
|
|
puts(_(" w write table to disk and exit"));
|
|
|
|
puts(_(" x extra functionality (experts only)"));
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
xmenu(void) {
|
2006-12-06 17:25:39 -06:00
|
|
|
if (sun_label) {
|
|
|
|
puts(_("Command action"));
|
2006-12-06 17:25:43 -06:00
|
|
|
puts(_(" a change number of alternate cylinders")); /*sun*/
|
2006-12-06 17:25:39 -06:00
|
|
|
puts(_(" c change number of cylinders"));
|
|
|
|
puts(_(" d print the raw data in the partition table"));
|
|
|
|
puts(_(" e change number of extra sectors per cylinder"));/*sun*/
|
|
|
|
puts(_(" h change number of heads"));
|
|
|
|
puts(_(" i change interleave factor")); /*sun*/
|
|
|
|
puts(_(" o change rotation speed (rpm)")); /*sun*/
|
|
|
|
puts(_(" m print this menu"));
|
|
|
|
puts(_(" p print the partition table"));
|
|
|
|
puts(_(" q quit without saving changes"));
|
|
|
|
puts(_(" r return to main menu"));
|
|
|
|
puts(_(" s change number of sectors/track"));
|
|
|
|
puts(_(" v verify the partition table"));
|
|
|
|
puts(_(" w write table to disk and exit"));
|
|
|
|
puts(_(" y change number of physical cylinders")); /*sun*/
|
|
|
|
}
|
2006-12-06 17:25:58 -06:00
|
|
|
else if (sgi_label) {
|
2006-12-06 17:25:43 -06:00
|
|
|
puts(_("Command action"));
|
|
|
|
puts(_(" b move beginning of data in a partition")); /* !sun */
|
|
|
|
puts(_(" c change number of cylinders"));
|
|
|
|
puts(_(" d print the raw data in the partition table"));
|
|
|
|
puts(_(" e list extended partitions")); /* !sun */
|
2006-12-06 17:25:49 -06:00
|
|
|
puts(_(" g create an IRIX (SGI) partition table"));/* sgi */
|
2006-12-06 17:25:43 -06:00
|
|
|
puts(_(" h change number of heads"));
|
|
|
|
puts(_(" m print this menu"));
|
|
|
|
puts(_(" p print the partition table"));
|
|
|
|
puts(_(" q quit without saving changes"));
|
|
|
|
puts(_(" r return to main menu"));
|
|
|
|
puts(_(" s change number of sectors/track"));
|
|
|
|
puts(_(" v verify the partition table"));
|
|
|
|
puts(_(" w write table to disk and exit"));
|
|
|
|
}
|
2007-06-27 16:49:56 -05:00
|
|
|
else if (aix_label || mac_label) {
|
2006-12-06 17:25:43 -06:00
|
|
|
puts(_("Command action"));
|
|
|
|
puts(_(" b move beginning of data in a partition")); /* !sun */
|
|
|
|
puts(_(" c change number of cylinders"));
|
|
|
|
puts(_(" d print the raw data in the partition table"));
|
|
|
|
puts(_(" e list extended partitions")); /* !sun */
|
2006-12-06 17:25:49 -06:00
|
|
|
puts(_(" g create an IRIX (SGI) partition table"));/* sgi */
|
2006-12-06 17:25:43 -06:00
|
|
|
puts(_(" h change number of heads"));
|
|
|
|
puts(_(" m print this menu"));
|
|
|
|
puts(_(" p print the partition table"));
|
|
|
|
puts(_(" q quit without saving changes"));
|
|
|
|
puts(_(" r return to main menu"));
|
|
|
|
puts(_(" s change number of sectors/track"));
|
|
|
|
puts(_(" v verify the partition table"));
|
|
|
|
puts(_(" w write table to disk and exit"));
|
|
|
|
}
|
2006-12-06 17:25:39 -06:00
|
|
|
else {
|
|
|
|
puts(_("Command action"));
|
|
|
|
puts(_(" b move beginning of data in a partition")); /* !sun */
|
|
|
|
puts(_(" c change number of cylinders"));
|
|
|
|
puts(_(" d print the raw data in the partition table"));
|
|
|
|
puts(_(" e list extended partitions")); /* !sun */
|
2006-12-06 17:25:43 -06:00
|
|
|
puts(_(" f fix partition order")); /* !sun, !aix, !sgi */
|
2006-12-06 17:25:49 -06:00
|
|
|
puts(_(" g create an IRIX (SGI) partition table"));/* sgi */
|
2006-12-06 17:25:39 -06:00
|
|
|
puts(_(" h change number of heads"));
|
2007-07-06 20:32:31 -05:00
|
|
|
puts(_(" i change the disk identifier")); /* dos only */
|
2006-12-06 17:25:39 -06:00
|
|
|
puts(_(" m print this menu"));
|
|
|
|
puts(_(" p print the partition table"));
|
|
|
|
puts(_(" q quit without saving changes"));
|
|
|
|
puts(_(" r return to main menu"));
|
|
|
|
puts(_(" s change number of sectors/track"));
|
|
|
|
puts(_(" v verify the partition table"));
|
|
|
|
puts(_(" w write table to disk and exit"));
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static int
|
2006-12-06 17:25:37 -06:00
|
|
|
get_sysid(int i) {
|
|
|
|
return (
|
fdisk: many significant improvements and fixes to Sun label handling
1) Properly describe the exact layout and fields of the sun disk
label. Several fields were incorrectly mentioned and others
wrongly sized.
2) Properly set the version, sane, and num_partitions fields.
Because we weren't doing this, programs such as Solaris's format
and the Solaris kernel itself refused to recognize our disk labels
as valid.
3) Move SSWAP*() macros into fdisksunlabel.c as there is no reason
for them to be exposed to the rest of fdisk.
4) Kill the sun_predefined_drives array hack and assosciated code.
Instead size the disk and figure out the geometry properly just
like the SGI and MSDOS partition handling do, by means of the
HD_GETGEO ioctl() and disksize().
5) If the disk label read is found to not have the proper values
set in version, sane, or num_partitions, fix them, recompute the
label checksum, dirty the disk label, and let the user know what
we did and that the fixed values will be written out if they 'w'.
This gives users an easy way to fix up disk labels created by
disk labelling programs which had this bug.
6) Create a sun_sys_getid() function so that fdisk.c does not need
to reference the sun disk label details directly, just like the
SGI code does.
Signed-off-by: David S. Miller <davem@davemloft.net>
2007-06-29 17:50:21 -05:00
|
|
|
sun_label ? sun_get_sysid(i) :
|
2006-12-06 17:25:56 -06:00
|
|
|
sgi_label ? sgi_get_sysid(i) :
|
|
|
|
ptes[i].part_table->sys_ind);
|
2006-12-06 17:25:37 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static struct systypes *
|
2006-12-06 17:25:37 -06:00
|
|
|
get_sys_types(void) {
|
|
|
|
return (
|
|
|
|
sun_label ? sun_sys_types :
|
2006-12-06 17:25:56 -06:00
|
|
|
sgi_label ? sgi_sys_types :
|
|
|
|
i386_sys_types);
|
2006-12-06 17:25:37 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
char *partition_type(unsigned char type)
|
|
|
|
{
|
2006-12-06 17:25:35 -06:00
|
|
|
int i;
|
2006-12-06 17:25:37 -06:00
|
|
|
struct systypes *types = get_sys_types();
|
2006-12-06 17:25:35 -06:00
|
|
|
|
|
|
|
for (i=0; types[i].name; i++)
|
2006-12-06 17:25:39 -06:00
|
|
|
if (types[i].type == type)
|
|
|
|
return _(types[i].name);
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
void list_types(struct systypes *sys)
|
2006-12-06 17:25:32 -06:00
|
|
|
{
|
2006-12-06 17:26:12 -06:00
|
|
|
unsigned int last[4], done = 0, next = 0, size;
|
2006-12-06 17:25:32 -06:00
|
|
|
int i;
|
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
for (i = 0; sys[i].name; i++);
|
|
|
|
size = i;
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
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',
|
2006-12-06 17:25:39 -06:00
|
|
|
sys[next].type, _(sys[next].name));
|
2006-12-06 17:25:33 -06:00
|
|
|
next = last[i++] + done;
|
2006-12-06 17:25:32 -06:00
|
|
|
if (i > 3 || next >= last[i]) {
|
|
|
|
i = 0;
|
|
|
|
next = ++done;
|
|
|
|
}
|
|
|
|
} while (done < last[0]);
|
|
|
|
putchar('\n');
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:49 -06:00
|
|
|
static int
|
|
|
|
is_cleared_partition(struct partition *p) {
|
|
|
|
return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
|
|
|
|
p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
|
|
|
|
get_start_sect(p) || get_nr_sects(p));
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
clear_partition(struct partition *p) {
|
|
|
|
if (!p)
|
|
|
|
return;
|
2006-12-06 17:25:32 -06:00
|
|
|
p->boot_ind = 0;
|
|
|
|
p->head = 0;
|
|
|
|
p->sector = 0;
|
|
|
|
p->cyl = 0;
|
|
|
|
p->sys_ind = 0;
|
|
|
|
p->end_head = 0;
|
|
|
|
p->end_sector = 0;
|
|
|
|
p->end_cyl = 0;
|
2006-12-06 17:25:35 -06:00
|
|
|
set_start_sect(p,0);
|
|
|
|
set_nr_sects(p,0);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
2007-05-30 10:10:43 -05:00
|
|
|
set_partition(int i, int doext, unsigned long long start,
|
|
|
|
unsigned long long stop, int sysid) {
|
2006-12-06 17:25:48 -06:00
|
|
|
struct partition *p;
|
2007-05-30 10:10:43 -05:00
|
|
|
unsigned long long offset;
|
2006-12-06 17:25:48 -06:00
|
|
|
|
|
|
|
if (doext) {
|
|
|
|
p = ptes[i].ext_pointer;
|
|
|
|
offset = extended_offset;
|
|
|
|
} else {
|
|
|
|
p = ptes[i].part_table;
|
|
|
|
offset = ptes[i].offset;
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
p->boot_ind = 0;
|
2006-12-06 17:25:35 -06:00
|
|
|
p->sys_ind = sysid;
|
|
|
|
set_start_sect(p, start - offset);
|
|
|
|
set_nr_sects(p, stop - start + 1);
|
2006-12-06 17:25:32 -06:00
|
|
|
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);
|
2006-12-06 17:25:43 -06:00
|
|
|
ptes[i].changed = 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static int
|
|
|
|
test_c(char **m, char *mesg) {
|
2006-12-06 17:25:32 -06:00
|
|
|
int val = 0;
|
|
|
|
if (!*m)
|
2006-12-06 17:25:39 -06:00
|
|
|
fprintf(stderr, _("You must set"));
|
2006-12-06 17:25:32 -06:00
|
|
|
else {
|
|
|
|
fprintf(stderr, " %s", *m);
|
|
|
|
val = 1;
|
|
|
|
}
|
|
|
|
*m = mesg;
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static int
|
|
|
|
warn_geometry(void) {
|
2006-12-06 17:25:32 -06:00
|
|
|
char *m = NULL;
|
|
|
|
int prev = 0;
|
2006-12-06 17:26:30 -06:00
|
|
|
|
|
|
|
if (sgi_label) /* cannot set cylinders etc anyway */
|
|
|
|
return 0;
|
2006-12-06 17:25:32 -06:00
|
|
|
if (!heads)
|
2006-12-06 17:25:39 -06:00
|
|
|
prev = test_c(&m, _("heads"));
|
2006-12-06 17:25:32 -06:00
|
|
|
if (!sectors)
|
2006-12-06 17:25:39 -06:00
|
|
|
prev = test_c(&m, _("sectors"));
|
2006-12-06 17:25:32 -06:00
|
|
|
if (!cylinders)
|
2006-12-06 17:25:39 -06:00
|
|
|
prev = test_c(&m, _("cylinders"));
|
2006-12-06 17:25:32 -06:00
|
|
|
if (!m)
|
|
|
|
return 0;
|
|
|
|
fprintf(stderr,
|
2006-12-06 17:25:39 -06:00
|
|
|
_("%s%s.\nYou can do this from the extra functions menu.\n"),
|
|
|
|
prev ? _(" and ") : " ", m);
|
2006-12-06 17:25:32 -06:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void update_units(void)
|
|
|
|
{
|
2006-12-06 17:25:37 -06:00
|
|
|
int cyl_units = heads * sectors;
|
|
|
|
|
2006-12-06 17:25:39 -06:00
|
|
|
if (display_in_cyl_units && cyl_units)
|
|
|
|
units_per_sector = cyl_units;
|
2006-12-06 17:25:37 -06:00
|
|
|
else
|
2006-12-06 17:25:39 -06:00
|
|
|
units_per_sector = 1; /* in sectors */
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
warn_cylinders(void) {
|
|
|
|
if (dos_label && cylinders > 1024 && !nowarn)
|
2006-12-06 17:25:44 -06: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"),
|
2006-12-06 17:25:32 -06:00
|
|
|
cylinders);
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
read_extended(int ext) {
|
2006-12-06 17:25:32 -06:00
|
|
|
int i;
|
2006-12-06 17:25:43 -06:00
|
|
|
struct pte *pex;
|
|
|
|
struct partition *p, *q;
|
|
|
|
|
|
|
|
ext_index = ext;
|
|
|
|
pex = &ptes[ext];
|
|
|
|
pex->ext_pointer = pex->part_table;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
p = pex->part_table;
|
2006-12-06 17:25:44 -06:00
|
|
|
if (!get_start_sect(p)) {
|
|
|
|
fprintf(stderr,
|
|
|
|
_("Bad offset in primary extended partition\n"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (IS_EXTENDED (p->sys_ind)) {
|
2006-12-06 17:25:43 -06:00
|
|
|
struct pte *pe = &ptes[partitions];
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
if (partitions >= MAXIMUM_PARTS) {
|
2006-12-06 17:25:39 -06:00
|
|
|
/* This is not a Linux restriction, but
|
|
|
|
this program uses arrays of size MAXIMUM_PARTS.
|
|
|
|
Do not try to `improve' this test. */
|
2006-12-06 17:25:43 -06:00
|
|
|
struct pte *pre = &ptes[partitions-1];
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
fprintf(stderr,
|
2006-12-06 17:26:26 -06:00
|
|
|
_("Warning: omitting partitions after #%d.\n"
|
|
|
|
"They will be deleted "
|
|
|
|
"if you save this partition table.\n"),
|
2006-12-06 17:25:32 -06:00
|
|
|
partitions);
|
2006-12-06 17:25:43 -06:00
|
|
|
clear_partition(pre->ext_pointer);
|
|
|
|
pre->changed = 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
return;
|
|
|
|
}
|
2006-12-06 17:25:43 -06:00
|
|
|
|
|
|
|
read_pte(fd, partitions, extended_offset + get_start_sect(p));
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
if (!extended_offset)
|
2006-12-06 17:25:35 -06:00
|
|
|
extended_offset = get_start_sect(p);
|
2006-12-06 17:25:43 -06:00
|
|
|
|
|
|
|
q = p = pt_offset(pe->sectorbuffer, 0);
|
2006-12-06 17:25:44 -06:00
|
|
|
for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
|
2006-12-06 17:25:37 -06:00
|
|
|
if (IS_EXTENDED (p->sys_ind)) {
|
2006-12-06 17:25:43 -06:00
|
|
|
if (pe->ext_pointer)
|
2006-12-06 17:25:46 -06:00
|
|
|
fprintf(stderr,
|
|
|
|
_("Warning: extra link "
|
|
|
|
"pointer in partition table"
|
|
|
|
" %d\n"), partitions + 1);
|
2006-12-06 17:25:32 -06:00
|
|
|
else
|
2006-12-06 17:25:43 -06:00
|
|
|
pe->ext_pointer = p;
|
2006-12-06 17:25:37 -06:00
|
|
|
} else if (p->sys_ind) {
|
2006-12-06 17:25:43 -06:00
|
|
|
if (pe->part_table)
|
2006-12-06 17:25:32 -06:00
|
|
|
fprintf(stderr,
|
2006-12-06 17:25:46 -06:00
|
|
|
_("Warning: ignoring extra "
|
|
|
|
"data in partition table"
|
|
|
|
" %d\n"), partitions + 1);
|
2006-12-06 17:25:32 -06:00
|
|
|
else
|
2006-12-06 17:25:43 -06:00
|
|
|
pe->part_table = p;
|
2006-12-06 17:25:37 -06:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2006-12-06 17:25:43 -06:00
|
|
|
|
|
|
|
/* very strange code here... */
|
|
|
|
if (!pe->part_table) {
|
|
|
|
if (q != pe->ext_pointer)
|
|
|
|
pe->part_table = q;
|
|
|
|
else
|
|
|
|
pe->part_table = q + 1;
|
2006-12-06 17:25:37 -06:00
|
|
|
}
|
2006-12-06 17:25:43 -06:00
|
|
|
if (!pe->ext_pointer) {
|
|
|
|
if (q != pe->part_table)
|
|
|
|
pe->ext_pointer = q;
|
|
|
|
else
|
|
|
|
pe->ext_pointer = q + 1;
|
2006-12-06 17:25:37 -06:00
|
|
|
}
|
2006-12-06 17:25:43 -06:00
|
|
|
|
|
|
|
p = pe->ext_pointer;
|
|
|
|
partitions++;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2006-12-06 17:25:44 -06:00
|
|
|
|
|
|
|
/* remove empty links */
|
|
|
|
remove:
|
|
|
|
for (i = 4; i < partitions; i++) {
|
|
|
|
struct pte *pe = &ptes[i];
|
|
|
|
|
2006-12-06 17:25:46 -06:00
|
|
|
if (!get_nr_sects(pe->part_table) &&
|
|
|
|
(partitions > 5 || ptes[4].part_table->sys_ind)) {
|
2006-12-06 17:25:44 -06:00
|
|
|
printf("omitting empty partition (%d)\n", i+1);
|
|
|
|
delete_partition(i);
|
|
|
|
goto remove; /* numbering changed */
|
|
|
|
}
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2007-07-06 20:32:31 -05:00
|
|
|
static void
|
|
|
|
dos_write_mbr_id(unsigned char *b, unsigned int id) {
|
|
|
|
store4_little_endian(&b[440], id);
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int
|
|
|
|
dos_read_mbr_id(const unsigned char *b) {
|
|
|
|
return read4_little_endian(&b[440]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
dos_print_mbr_id(void) {
|
|
|
|
printf(_("Disk identifier: 0x%08x\n"), dos_read_mbr_id(MBRbuffer));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
dos_set_mbr_id(void) {
|
|
|
|
unsigned long new_id;
|
|
|
|
char *ep;
|
|
|
|
char ps[64];
|
|
|
|
|
|
|
|
snprintf(ps, sizeof ps, _("New disk identifier (current 0x%08x): "),
|
|
|
|
dos_read_mbr_id(MBRbuffer));
|
|
|
|
|
|
|
|
if (read_chars(ps) == '\n')
|
|
|
|
return;
|
|
|
|
|
|
|
|
new_id = strtoul(line_ptr, &ep, 0);
|
|
|
|
if (*ep != '\n')
|
|
|
|
return;
|
|
|
|
|
|
|
|
dos_write_mbr_id(MBRbuffer, new_id);
|
|
|
|
dos_print_mbr_id();
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
create_doslabel(void) {
|
2007-07-06 20:32:31 -05:00
|
|
|
unsigned int id = get_random_id();
|
2006-12-06 17:25:35 -06:00
|
|
|
|
|
|
|
fprintf(stderr,
|
2007-07-06 20:32:31 -05:00
|
|
|
_("Building a new DOS disklabel with disk identifier 0x%08x.\n"
|
|
|
|
"Changes will remain in memory only, until you decide to write them.\n"
|
|
|
|
"After that, of course, the previous content won't be recoverable.\n\n"),
|
|
|
|
id);
|
2006-12-06 17:25:37 -06:00
|
|
|
sun_nolabel(); /* otherwise always recognised as sun */
|
|
|
|
sgi_nolabel(); /* otherwise always recognised as sgi */
|
2007-06-27 16:49:56 -05:00
|
|
|
mac_label = aix_label = osf_label = possibly_osf_label = 0;
|
2006-12-06 17:25:49 -06:00
|
|
|
partitions = 4;
|
2006-12-06 17:25:37 -06:00
|
|
|
|
2007-07-06 20:32:31 -05:00
|
|
|
/* Zero out the MBR buffer */
|
2006-12-06 17:25:46 -06:00
|
|
|
extended_offset = 0;
|
2006-12-06 17:25:43 -06:00
|
|
|
set_all_unchanged();
|
|
|
|
set_changed(0);
|
2006-12-06 17:25:49 -06:00
|
|
|
get_boot(create_empty_dos);
|
2007-07-06 20:32:31 -05:00
|
|
|
|
|
|
|
/* Generate an MBR ID for this disk */
|
|
|
|
dos_write_mbr_id(MBRbuffer, id);
|
|
|
|
|
|
|
|
/* Mark it bootable (unfortunately required) */
|
|
|
|
write_part_table_flag(MBRbuffer);
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
get_sectorsize(int fd) {
|
2007-11-07 12:05:31 -06:00
|
|
|
int arg;
|
|
|
|
|
|
|
|
if (user_set_sector_size)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (blkdev_get_sector_size(fd, &arg) == 0)
|
|
|
|
sector_size = arg;
|
|
|
|
if (sector_size != DEFAULT_SECTOR_SIZE)
|
|
|
|
printf(_("Note: sector size is %d (not %d)\n"),
|
|
|
|
sector_size, DEFAULT_SECTOR_SIZE);
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
2006-12-06 17:25:39 -06:00
|
|
|
|
2006-12-06 17:25:54 -06:00
|
|
|
static void
|
|
|
|
get_kernel_geometry(int fd) {
|
|
|
|
#ifdef HDIO_GETGEO
|
|
|
|
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 */
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
get_partition_table_geometry(void) {
|
|
|
|
unsigned char *bufp = MBRbuffer;
|
|
|
|
struct partition *p;
|
|
|
|
int i, h, s, hh, ss;
|
|
|
|
int first = 1;
|
|
|
|
int bad = 0;
|
|
|
|
|
|
|
|
if (!(valid_part_table_flag(bufp)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
hh = ss = 0;
|
|
|
|
for (i=0; i<4; i++) {
|
|
|
|
p = pt_offset(bufp, i);
|
|
|
|
if (p->sys_ind != 0) {
|
|
|
|
h = p->end_head + 1;
|
|
|
|
s = (p->end_sector & 077);
|
|
|
|
if (first) {
|
|
|
|
hh = h;
|
|
|
|
ss = s;
|
|
|
|
first = 0;
|
|
|
|
} else if (hh != h || ss != s)
|
|
|
|
bad = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!first && !bad) {
|
|
|
|
pt_heads = hh;
|
|
|
|
pt_sectors = ss;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
void
|
|
|
|
get_geometry(int fd, struct geom *g) {
|
|
|
|
int sec_fac;
|
2006-12-06 17:26:18 -06:00
|
|
|
unsigned long long llsectors, llcyls;
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
get_sectorsize(fd);
|
|
|
|
sec_fac = sector_size / 512;
|
|
|
|
guess_device_type(fd);
|
|
|
|
heads = cylinders = sectors = 0;
|
2006-12-06 17:25:54 -06:00
|
|
|
kern_heads = kern_sectors = 0;
|
|
|
|
pt_heads = pt_sectors = 0;
|
|
|
|
|
|
|
|
get_kernel_geometry(fd);
|
|
|
|
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;
|
|
|
|
|
2007-11-07 12:05:31 -06:00
|
|
|
if (blkdev_get_sectors(fd, &llsectors) == -1)
|
2006-12-06 17:26:18 -06:00
|
|
|
llsectors = 0;
|
2006-12-06 17:26:12 -06:00
|
|
|
|
2006-12-06 17:26:18 -06:00
|
|
|
total_number_of_sectors = llsectors;
|
2006-12-06 17:25:54 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
sector_offset = 1;
|
2006-12-06 17:25:54 -06:00
|
|
|
if (dos_compatible_flag)
|
|
|
|
sector_offset = sectors;
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2006-12-06 17:26:18 -06:00
|
|
|
llcyls = total_number_of_sectors / (heads * sectors * sec_fac);
|
|
|
|
cylinders = llcyls;
|
|
|
|
if (cylinders != llcyls) /* truncated? */
|
|
|
|
cylinders = ~0;
|
2006-12-06 17:25:43 -06:00
|
|
|
if (!cylinders)
|
|
|
|
cylinders = user_cylinders;
|
|
|
|
|
|
|
|
if (g) {
|
|
|
|
g->heads = heads;
|
|
|
|
g->sectors = sectors;
|
|
|
|
g->cylinders = cylinders;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read MBR. Returns:
|
|
|
|
* -1: no 0xaa55 flag present (possibly entire disk BSD)
|
|
|
|
* 0: found or created label
|
2006-12-06 17:25:49 -06:00
|
|
|
* 1: I/O error
|
2006-12-06 17:25:43 -06:00
|
|
|
*/
|
|
|
|
int
|
|
|
|
get_boot(enum action what) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
partitions = 4;
|
2006-12-06 17:26:16 -06:00
|
|
|
ext_index = 0;
|
|
|
|
extended_offset = 0;
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2006-12-06 17:25:58 -06:00
|
|
|
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;
|
|
|
|
pe->changed = (what == create_empty_dos);
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:26:03 -06:00
|
|
|
if (what == create_empty_sun && check_sun_label())
|
|
|
|
return 0;
|
|
|
|
|
2006-12-06 17:25:58 -06:00
|
|
|
memset(MBRbuffer, 0, 512);
|
|
|
|
|
2006-12-06 17:25:49 -06:00
|
|
|
if (what == create_empty_dos)
|
|
|
|
goto got_dos_table; /* skip reading disk */
|
2006-12-06 17:25:43 -06:00
|
|
|
|
|
|
|
if ((fd = open(disk_device, type_open)) < 0) {
|
2006-12-06 17:25:49 -06:00
|
|
|
if ((fd = open(disk_device, O_RDONLY)) < 0) {
|
|
|
|
if (what == try_only)
|
|
|
|
return 1;
|
2006-12-06 17:25:43 -06:00
|
|
|
fatal(unable_to_open);
|
2006-12-06 17:25:49 -06:00
|
|
|
} else
|
2006-12-06 17:25:58 -06:00
|
|
|
printf(_("You will not be able to write "
|
|
|
|
"the partition table.\n"));
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:54 -06:00
|
|
|
if (512 != read(fd, MBRbuffer, 512)) {
|
2006-12-06 17:25:49 -06:00
|
|
|
if (what == try_only)
|
|
|
|
return 1;
|
2006-12-06 17:25:43 -06:00
|
|
|
fatal(unable_to_read);
|
2006-12-06 17:25:49 -06:00
|
|
|
}
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2006-12-06 17:25:54 -06:00
|
|
|
get_geometry(fd, NULL);
|
|
|
|
|
|
|
|
update_units();
|
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
if (check_sun_label())
|
|
|
|
return 0;
|
2006-12-06 17:25:37 -06:00
|
|
|
|
|
|
|
if (check_sgi_label())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (check_aix_label())
|
|
|
|
return 0;
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2007-06-27 16:49:56 -05:00
|
|
|
if (check_mac_label())
|
|
|
|
return 0;
|
|
|
|
|
2006-12-06 17:25:58 -06:00
|
|
|
if (check_osf_label()) {
|
|
|
|
possibly_osf_label = 1;
|
|
|
|
if (!valid_part_table_flag(MBRbuffer)) {
|
|
|
|
osf_label = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
printf(_("This disk has both DOS and BSD magic.\n"
|
|
|
|
"Give the 'b' command to go to BSD mode.\n"));
|
|
|
|
}
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2006-12-06 17:25:49 -06:00
|
|
|
got_dos_table:
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
if (!valid_part_table_flag(MBRbuffer)) {
|
2006-12-06 17:25:35 -06:00
|
|
|
switch(what) {
|
|
|
|
case fdisk:
|
|
|
|
fprintf(stderr,
|
2006-12-06 17:25:58 -06:00
|
|
|
_("Device contains neither a valid DOS "
|
|
|
|
"partition table, nor Sun, SGI or OSF "
|
|
|
|
"disklabel\n"));
|
2006-12-06 17:25:35 -06:00
|
|
|
#ifdef __sparc__
|
|
|
|
create_sunlabel();
|
|
|
|
#else
|
|
|
|
create_doslabel();
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
case require:
|
|
|
|
return -1;
|
|
|
|
case try_only:
|
|
|
|
return -1;
|
2006-12-06 17:25:49 -06:00
|
|
|
case create_empty_dos:
|
|
|
|
case create_empty_sun:
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
2006-12-06 17:26:00 -06:00
|
|
|
default:
|
|
|
|
fprintf(stderr, _("Internal error\n"));
|
|
|
|
exit(1);
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
2006-12-06 17:25:34 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
warn_cylinders();
|
|
|
|
warn_geometry();
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
struct pte *pe = &ptes[i];
|
|
|
|
|
|
|
|
if (IS_EXTENDED (pe->part_table->sys_ind)) {
|
2006-12-06 17:25:32 -06:00
|
|
|
if (partitions != 4)
|
2006-12-06 17:25:39 -06:00
|
|
|
fprintf(stderr, _("Ignoring extra extended "
|
|
|
|
"partition %d\n"), i + 1);
|
2006-12-06 17:25:43 -06:00
|
|
|
else
|
|
|
|
read_extended(i);
|
2006-12-06 17:25:37 -06:00
|
|
|
}
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 3; i < partitions; i++) {
|
|
|
|
struct pte *pe = &ptes[i];
|
|
|
|
|
|
|
|
if (!valid_part_table_flag(pe->sectorbuffer)) {
|
2006-12-06 17:25:35 -06:00
|
|
|
fprintf(stderr,
|
2006-12-06 17:25:39 -06:00
|
|
|
_("Warning: invalid flag 0x%04x of partition "
|
|
|
|
"table %d will be corrected by w(rite)\n"),
|
2006-12-06 17:25:43 -06:00
|
|
|
part_table_flag(pe->sectorbuffer), i + 1);
|
|
|
|
pe->changed = 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
2006-12-06 17:25:34 -06:00
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
return 0;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
/* read line; return 0 or first char */
|
|
|
|
int
|
|
|
|
read_line(void)
|
2006-12-06 17:25:32 -06:00
|
|
|
{
|
2006-12-06 17:25:39 -06:00
|
|
|
static int got_eof = 0;
|
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
line_ptr = line_buffer;
|
2006-12-06 17:25:39 -06:00
|
|
|
if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
|
|
|
|
if (feof(stdin))
|
|
|
|
got_eof++; /* user typed ^D ? */
|
|
|
|
if (got_eof >= 3) {
|
|
|
|
fflush(stdout);
|
|
|
|
fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
|
|
|
|
exit(1);
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
return 0;
|
2006-12-06 17:25:39 -06:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
while (*line_ptr && !isgraph(*line_ptr))
|
|
|
|
line_ptr++;
|
|
|
|
return *line_ptr;
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
char
|
|
|
|
read_char(char *mesg)
|
2006-12-06 17:25:32 -06:00
|
|
|
{
|
2006-12-06 17:25:35 -06:00
|
|
|
do {
|
2006-12-06 17:25:32 -06:00
|
|
|
fputs(mesg, stdout);
|
2006-12-06 17:25:44 -06:00
|
|
|
fflush (stdout); /* requested by niles@scyld.com */
|
2006-12-06 17:25:35 -06:00
|
|
|
} while (!read_line());
|
2006-12-06 17:25:32 -06:00
|
|
|
return *line_ptr;
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
char
|
|
|
|
read_chars(char *mesg)
|
2006-12-06 17:25:35 -06:00
|
|
|
{
|
|
|
|
fputs(mesg, stdout);
|
2006-12-06 17:25:44 -06:00
|
|
|
fflush (stdout); /* niles@scyld.com */
|
2006-12-06 17:25:35 -06:00
|
|
|
if (!read_line()) {
|
|
|
|
*line_ptr = '\n';
|
2006-12-06 17:25:37 -06:00
|
|
|
line_ptr[1] = 0;
|
|
|
|
}
|
|
|
|
return *line_ptr;
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
int
|
|
|
|
read_hex(struct systypes *sys)
|
2006-12-06 17:25:32 -06:00
|
|
|
{
|
2006-12-06 17:25:33 -06:00
|
|
|
int hex;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
2006-12-06 17:25:39 -06:00
|
|
|
read_char(_("Hex code (type L to list codes): "));
|
2006-12-06 17:25:33 -06:00
|
|
|
if (tolower(*line_ptr) == 'l')
|
2006-12-06 17:25:35 -06:00
|
|
|
list_types(sys);
|
2006-12-06 17:25:33 -06:00
|
|
|
else if (isxdigit (*line_ptr))
|
|
|
|
{
|
|
|
|
hex = 0;
|
|
|
|
do
|
|
|
|
hex = hex << 4 | hex_val(*line_ptr++);
|
|
|
|
while (isxdigit(*line_ptr));
|
|
|
|
return hex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
/*
|
2006-12-06 17:26:16 -06:00
|
|
|
* Print the message MESG, then read an integer in LOW..HIGH.
|
|
|
|
* If the user hits Enter, DFLT is returned, provided that is in LOW..HIGH.
|
2006-12-06 17:25:37 -06:00
|
|
|
* Answers like +10 are interpreted as offsets from BASE.
|
|
|
|
*
|
|
|
|
* There is no default if DFLT is not between LOW and HIGH.
|
|
|
|
*/
|
2006-12-06 17:26:12 -06:00
|
|
|
unsigned int
|
|
|
|
read_int(unsigned int low, unsigned int dflt, unsigned int high,
|
|
|
|
unsigned int base, char *mesg)
|
2006-12-06 17:25:33 -06:00
|
|
|
{
|
2006-12-06 17:26:12 -06:00
|
|
|
unsigned int i;
|
2006-12-06 17:25:37 -06:00
|
|
|
int default_ok = 1;
|
|
|
|
static char *ms = NULL;
|
|
|
|
static int mslen = 0;
|
|
|
|
|
2006-12-06 17:25:46 -06:00
|
|
|
if (!ms || strlen(mesg)+100 > mslen) {
|
|
|
|
mslen = strlen(mesg)+200;
|
2006-12-06 17:25:37 -06:00
|
|
|
if (!(ms = realloc(ms,mslen)))
|
|
|
|
fatal(out_of_memory);
|
2006-12-06 17:25:33 -06:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
if (dflt < low || dflt > high)
|
|
|
|
default_ok = 0;
|
|
|
|
|
|
|
|
if (default_ok)
|
2006-12-06 17:26:12 -06:00
|
|
|
snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
|
2006-12-06 17:25:46 -06:00
|
|
|
mesg, low, high, dflt);
|
2006-12-06 17:25:37 -06:00
|
|
|
else
|
2006-12-06 17:26:12 -06:00
|
|
|
snprintf(ms, mslen, "%s (%u-%u): ",
|
2006-12-06 17:25:46 -06:00
|
|
|
mesg, low, high);
|
2006-12-06 17:25:37 -06:00
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
while (1) {
|
2006-12-06 17:25:37 -06:00
|
|
|
int use_default = default_ok;
|
|
|
|
|
|
|
|
/* ask question and read answer */
|
|
|
|
while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
|
|
|
|
&& *line_ptr != '-' && *line_ptr != '+')
|
|
|
|
continue;
|
|
|
|
|
2006-12-06 17:25:33 -06:00
|
|
|
if (*line_ptr == '+' || *line_ptr == '-') {
|
2006-12-06 17:26:08 -06:00
|
|
|
int minus = (*line_ptr == '-');
|
|
|
|
int absolute = 0;
|
2007-12-12 18:06:44 -06:00
|
|
|
int suflen;
|
2006-12-06 17:26:08 -06:00
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
i = atoi(line_ptr+1);
|
2006-12-06 17:26:08 -06:00
|
|
|
|
2007-12-12 18:06:44 -06:00
|
|
|
while (isdigit(*++line_ptr))
|
2006-12-06 17:25:33 -06:00
|
|
|
use_default = 0;
|
2006-12-06 17:26:08 -06:00
|
|
|
|
2007-12-12 18:06:44 -06:00
|
|
|
suflen = strlen(line_ptr) - 1;
|
|
|
|
|
|
|
|
while(isspace(*(line_ptr + suflen)))
|
|
|
|
*(line_ptr + suflen--) = '\0';
|
|
|
|
|
|
|
|
if ((*line_ptr == 'C' || *line_ptr == 'c') &&
|
|
|
|
*(line_ptr + 1) == '\0') {
|
|
|
|
/*
|
|
|
|
* Cylinders
|
|
|
|
*/
|
|
|
|
if (!display_in_cyl_units)
|
|
|
|
i *= heads * sectors;
|
|
|
|
} else if (*(line_ptr + 1) == 'B' &&
|
|
|
|
*(line_ptr + 2) == '\0') {
|
|
|
|
/*
|
|
|
|
* 10^N
|
|
|
|
*/
|
|
|
|
if (*line_ptr == 'K')
|
2006-12-06 17:26:08 -06:00
|
|
|
absolute = 1000;
|
2007-12-12 18:06:44 -06:00
|
|
|
else if (*line_ptr == 'M')
|
2006-12-06 17:26:08 -06:00
|
|
|
absolute = 1000000;
|
2007-12-12 18:06:44 -06:00
|
|
|
else if (*line_ptr == 'G')
|
2006-12-06 17:26:08 -06:00
|
|
|
absolute = 1000000000;
|
2007-12-12 18:06:44 -06:00
|
|
|
else
|
|
|
|
absolute = -1;
|
|
|
|
} else if (*(line_ptr + 1) == '\0') {
|
|
|
|
/*
|
|
|
|
* 2^N
|
|
|
|
*/
|
|
|
|
if (*line_ptr == 'K')
|
|
|
|
absolute = 1 << 10;
|
|
|
|
else if (*line_ptr == 'M')
|
|
|
|
absolute = 1 << 20;
|
|
|
|
else if (*line_ptr == 'G')
|
|
|
|
absolute = 1 << 30;
|
|
|
|
else
|
|
|
|
absolute = -1;
|
|
|
|
} else if (*line_ptr != '\0')
|
|
|
|
absolute = -1;
|
|
|
|
|
|
|
|
if (absolute == -1) {
|
|
|
|
printf(_("Unsupported suffix: '%s'.\n"), line_ptr);
|
|
|
|
printf(_("Supported: 10^N: KB (KiloByte), MB (MegaByte), GB (GigaByte)\n"
|
|
|
|
" 2^N: K (KibiByte), M (MebiByte), G (GibiByte)\n"));
|
|
|
|
continue;
|
2006-12-06 17:25:33 -06:00
|
|
|
}
|
2007-12-12 18:06:44 -06:00
|
|
|
|
|
|
|
if (absolute && i) {
|
2006-12-06 17:26:08 -06:00
|
|
|
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;
|
2006-12-06 17:25:37 -06:00
|
|
|
i += base;
|
|
|
|
} else {
|
2006-12-06 17:25:33 -06:00
|
|
|
i = atoi(line_ptr);
|
2006-12-06 17:25:37 -06:00
|
|
|
while (isdigit(*line_ptr)) {
|
2006-12-06 17:25:33 -06:00
|
|
|
line_ptr++;
|
|
|
|
use_default = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (use_default)
|
2006-12-06 17:26:12 -06:00
|
|
|
printf(_("Using default value %u\n"), i = dflt);
|
2006-12-06 17:25:32 -06:00
|
|
|
if (i >= low && i <= high)
|
|
|
|
break;
|
2006-12-06 17:25:33 -06:00
|
|
|
else
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Value out of range.\n"));
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
int
|
|
|
|
get_partition(int warn, int max) {
|
|
|
|
struct pte *pe;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
i = read_int(1, 0, max, 0, _("Partition number")) - 1;
|
|
|
|
pe = &ptes[i];
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:26:03 -06:00
|
|
|
if (warn) {
|
|
|
|
if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
|
|
|
|
|| (sun_label &&
|
|
|
|
(!sunlabel->partitions[i].num_sectors ||
|
fdisk: many significant improvements and fixes to Sun label handling
1) Properly describe the exact layout and fields of the sun disk
label. Several fields were incorrectly mentioned and others
wrongly sized.
2) Properly set the version, sane, and num_partitions fields.
Because we weren't doing this, programs such as Solaris's format
and the Solaris kernel itself refused to recognize our disk labels
as valid.
3) Move SSWAP*() macros into fdisksunlabel.c as there is no reason
for them to be exposed to the rest of fdisk.
4) Kill the sun_predefined_drives array hack and assosciated code.
Instead size the disk and figure out the geometry properly just
like the SGI and MSDOS partition handling do, by means of the
HD_GETGEO ioctl() and disksize().
5) If the disk label read is found to not have the proper values
set in version, sane, or num_partitions, fix them, recompute the
label checksum, dirty the disk label, and let the user know what
we did and that the fixed values will be written out if they 'w'.
This gives users an easy way to fix up disk labels created by
disk labelling programs which had this bug.
6) Create a sun_sys_getid() function so that fdisk.c does not need
to reference the sun disk label details directly, just like the
SGI code does.
Signed-off-by: David S. Miller <davem@davemloft.net>
2007-06-29 17:50:21 -05:00
|
|
|
!sunlabel->part_tags[i].tag))
|
2006-12-06 17:26:03 -06:00
|
|
|
|| (sgi_label && (!sgi_get_num_sectors(i)))
|
|
|
|
)
|
|
|
|
fprintf(stderr,
|
|
|
|
_("Warning: partition %d has empty type\n"),
|
|
|
|
i+1);
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:26:03 -06:00
|
|
|
static int
|
|
|
|
get_existing_partition(int warn, int max) {
|
|
|
|
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
|
|
|
|
get_nonexisting_partition(int warn, int max) {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2007-05-30 10:41:14 -05:00
|
|
|
const char *
|
2006-12-06 17:25:43 -06:00
|
|
|
str_units(int n) { /* n==1: use singular */
|
2006-12-06 17:25:39 -06:00
|
|
|
if (n == 1)
|
|
|
|
return display_in_cyl_units ? _("cylinder") : _("sector");
|
|
|
|
else
|
|
|
|
return display_in_cyl_units ? _("cylinders") : _("sectors");
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void change_units(void)
|
|
|
|
{
|
2006-12-06 17:25:39 -06:00
|
|
|
display_in_cyl_units = !display_in_cyl_units;
|
2006-12-06 17:25:32 -06:00
|
|
|
update_units();
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Changing display/entry units to %s\n"),
|
|
|
|
str_units(PLURAL));
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
toggle_active(int i) {
|
|
|
|
struct pte *pe = &ptes[i];
|
|
|
|
struct partition *p = pe->part_table;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
|
2006-12-06 17:25:32 -06:00
|
|
|
fprintf(stderr,
|
2006-12-06 17:25:39 -06:00
|
|
|
_("WARNING: Partition %d is an extended partition\n"),
|
2006-12-06 17:25:32 -06:00
|
|
|
i + 1);
|
2006-12-06 17:25:43 -06:00
|
|
|
p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
|
|
|
|
pe->changed = 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
toggle_dos_compatibility_flag(void) {
|
2006-12-06 17:25:32 -06:00
|
|
|
dos_compatible_flag = ~dos_compatible_flag;
|
2006-12-06 17:25:39 -06:00
|
|
|
if (dos_compatible_flag) {
|
2006-12-06 17:25:32 -06:00
|
|
|
sector_offset = sectors;
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("DOS Compatibility flag is set\n"));
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
else {
|
|
|
|
sector_offset = 1;
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("DOS Compatibility flag is not set\n"));
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
delete_partition(int i) {
|
|
|
|
struct pte *pe = &ptes[i];
|
|
|
|
struct partition *p = pe->part_table;
|
|
|
|
struct partition *q = pe->ext_pointer;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
|
|
|
/* Note that for the fifth partition (i == 4) we don't actually
|
|
|
|
* decrement partitions.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (warn_geometry())
|
2006-12-06 17:25:49 -06:00
|
|
|
return; /* C/H/S not set */
|
2006-12-06 17:25:43 -06:00
|
|
|
pe->changed = 1;
|
2006-12-06 17:25:37 -06:00
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
if (sun_label) {
|
|
|
|
sun_delete_partition(i);
|
|
|
|
return;
|
|
|
|
}
|
2006-12-06 17:25:44 -06:00
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
if (sgi_label) {
|
|
|
|
sgi_delete_partition(i);
|
|
|
|
return;
|
|
|
|
}
|
2006-12-06 17:25:44 -06:00
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
if (i < 4) {
|
2006-12-06 17:25:35 -06:00
|
|
|
if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
|
2006-12-06 17:25:43 -06:00
|
|
|
partitions = 4;
|
|
|
|
ptes[ext_index].ext_pointer = NULL;
|
2006-12-06 17:25:32 -06:00
|
|
|
extended_offset = 0;
|
|
|
|
}
|
|
|
|
clear_partition(p);
|
2006-12-06 17:25:44 -06:00
|
|
|
return;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2006-12-06 17:25:44 -06:00
|
|
|
|
|
|
|
if (!q->sys_ind && i > 4) {
|
2006-12-06 17:25:46 -06:00
|
|
|
/* the last one in the chain - just delete */
|
2006-12-06 17:25:43 -06:00
|
|
|
--partitions;
|
|
|
|
--i;
|
|
|
|
clear_partition(ptes[i].ext_pointer);
|
|
|
|
ptes[i].changed = 1;
|
2006-12-06 17:25:44 -06:00
|
|
|
} else {
|
2006-12-06 17:25:46 -06:00
|
|
|
/* not the last one - further ones will be moved down */
|
2006-12-06 17:25:32 -06:00
|
|
|
if (i > 4) {
|
2006-12-06 17:25:46 -06:00
|
|
|
/* delete this link in the chain */
|
2006-12-06 17:25:43 -06:00
|
|
|
p = ptes[i-1].ext_pointer;
|
2006-12-06 17:25:48 -06:00
|
|
|
*p = *q;
|
2006-12-06 17:25:35 -06:00
|
|
|
set_start_sect(p, get_start_sect(q));
|
|
|
|
set_nr_sects(p, get_nr_sects(q));
|
2006-12-06 17:25:43 -06:00
|
|
|
ptes[i-1].changed = 1;
|
2006-12-06 17:25:44 -06:00
|
|
|
} else if (partitions > 5) { /* 5 will be moved to 4 */
|
2006-12-06 17:25:46 -06:00
|
|
|
/* the first logical in a longer chain */
|
2006-12-06 17:25:43 -06:00
|
|
|
struct pte *pe = &ptes[5];
|
|
|
|
|
2006-12-06 17:25:58 -06:00
|
|
|
if (pe->part_table) /* prevent SEGFAULT */
|
2006-12-06 17:25:43 -06:00
|
|
|
set_start_sect(pe->part_table,
|
|
|
|
get_partition_start(pe) -
|
|
|
|
extended_offset);
|
|
|
|
pe->offset = extended_offset;
|
|
|
|
pe->changed = 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2006-12-06 17:25:44 -06:00
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
if (partitions > 5) {
|
|
|
|
partitions--;
|
|
|
|
while (i < partitions) {
|
2006-12-06 17:25:43 -06:00
|
|
|
ptes[i] = ptes[i+1];
|
2006-12-06 17:25:32 -06:00
|
|
|
i++;
|
|
|
|
}
|
2006-12-06 17:25:43 -06:00
|
|
|
} else
|
2006-12-06 17:25:46 -06:00
|
|
|
/* the only logical: clear only */
|
2006-12-06 17:25:43 -06:00
|
|
|
clear_partition(ptes[i].part_table);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
change_sysid(void) {
|
2006-12-06 17:25:32 -06:00
|
|
|
char *temp;
|
2006-12-06 17:26:03 -06:00
|
|
|
int i, sys, origsys;
|
|
|
|
struct partition *p;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:26:12 -06:00
|
|
|
/* 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. */
|
|
|
|
if (!sgi_label) {
|
|
|
|
i = get_existing_partition(0, partitions);
|
|
|
|
} else {
|
|
|
|
i = get_partition(0, partitions);
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:26:03 -06:00
|
|
|
if (i == -1)
|
|
|
|
return;
|
|
|
|
p = ptes[i].part_table;
|
2006-12-06 17:25:37 -06:00
|
|
|
origsys = sys = get_sysid(i);
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2006-12-06 17:26:02 -06:00
|
|
|
/* if changing types T to 0 is allowed, then
|
|
|
|
the reverse change must be allowed, too */
|
|
|
|
if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Partition %d does not exist yet!\n"), i + 1);
|
2006-12-06 17:25:35 -06:00
|
|
|
else while (1) {
|
2006-12-06 17:25:37 -06:00
|
|
|
sys = read_hex (get_sys_types());
|
|
|
|
|
2006-12-06 17:25:46 -06:00
|
|
|
if (!sys && !sgi_label && !sun_label) {
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Type 0 means free space to many systems\n"
|
2006-12-06 17:25:37 -06:00
|
|
|
"(but not to Linux). Having partitions of\n"
|
|
|
|
"type 0 is probably unwise. You can delete\n"
|
2006-12-06 17:25:39 -06:00
|
|
|
"a partition using the `d' command.\n"));
|
2006-12-06 17:25:37 -06:00
|
|
|
/* break; */
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
if (!sun_label && !sgi_label) {
|
2006-12-06 17:25:35 -06:00
|
|
|
if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("You cannot change a partition into"
|
2006-12-06 17:25:35 -06:00
|
|
|
" an extended one or vice versa\n"
|
2006-12-06 17:25:39 -06:00
|
|
|
"Delete it first.\n"));
|
2006-12-06 17:25:32 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-12-06 17:25:35 -06:00
|
|
|
|
|
|
|
if (sys < 256) {
|
fdisk: many significant improvements and fixes to Sun label handling
1) Properly describe the exact layout and fields of the sun disk
label. Several fields were incorrectly mentioned and others
wrongly sized.
2) Properly set the version, sane, and num_partitions fields.
Because we weren't doing this, programs such as Solaris's format
and the Solaris kernel itself refused to recognize our disk labels
as valid.
3) Move SSWAP*() macros into fdisksunlabel.c as there is no reason
for them to be exposed to the rest of fdisk.
4) Kill the sun_predefined_drives array hack and assosciated code.
Instead size the disk and figure out the geometry properly just
like the SGI and MSDOS partition handling do, by means of the
HD_GETGEO ioctl() and disksize().
5) If the disk label read is found to not have the proper values
set in version, sane, or num_partitions, fix them, recompute the
label checksum, dirty the disk label, and let the user know what
we did and that the fixed values will be written out if they 'w'.
This gives users an easy way to fix up disk labels created by
disk labelling programs which had this bug.
6) Create a sun_sys_getid() function so that fdisk.c does not need
to reference the sun disk label details directly, just like the
SGI code does.
Signed-off-by: David S. Miller <davem@davemloft.net>
2007-06-29 17:50:21 -05:00
|
|
|
if (sun_label && i == 2 && sys != SUN_TAG_BACKUP)
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Consider leaving partition 3 "
|
2006-12-06 17:25:35 -06:00
|
|
|
"as Whole disk (5),\n"
|
|
|
|
"as SunOS/Solaris expects it and "
|
2006-12-06 17:25:39 -06:00
|
|
|
"even Linux likes it.\n\n"));
|
2006-12-06 17:25:37 -06:00
|
|
|
if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
|
|
|
|
|| (i == 8 && sys != 0)))
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Consider leaving partition 9 "
|
2006-12-06 17:25:37 -06:00
|
|
|
"as volume header (0),\nand "
|
2007-09-29 08:14:42 -05:00
|
|
|
"partition 11 as entire volume (6), "
|
2006-12-06 17:25:39 -06:00
|
|
|
"as IRIX expects it.\n\n"));
|
2006-12-06 17:25:35 -06:00
|
|
|
if (sys == origsys)
|
2006-12-06 17:26:02 -06:00
|
|
|
break;
|
2006-12-06 17:25:37 -06:00
|
|
|
if (sun_label) {
|
2007-07-14 12:32:37 -05:00
|
|
|
ptes[i].changed = sun_change_sysid(i, sys);
|
2006-12-06 17:25:35 -06:00
|
|
|
} else
|
2006-12-06 17:25:37 -06:00
|
|
|
if (sgi_label) {
|
2007-07-14 12:32:37 -05:00
|
|
|
ptes[i].changed = sgi_change_sysid(i, sys);
|
|
|
|
} else {
|
2006-12-06 17:25:43 -06:00
|
|
|
p->sys_ind = sys;
|
2007-07-14 12:32:37 -05:00
|
|
|
ptes[i].changed = 1;
|
|
|
|
}
|
|
|
|
temp = partition_type(sys) ? : _("Unknown");
|
|
|
|
if (ptes[i].changed)
|
|
|
|
printf (_("Changed system type of partition %d "
|
|
|
|
"to %x (%s)\n"), i + 1, sys, temp);
|
|
|
|
else
|
2008-04-14 05:16:14 -05:00
|
|
|
printf (_("System type of partition %d is unchanged: "
|
|
|
|
"%x (%s)\n"), i + 1, sys, temp);
|
2006-12-06 17:25:49 -06:00
|
|
|
if (is_dos_partition(origsys) ||
|
|
|
|
is_dos_partition(sys))
|
|
|
|
dos_changed = 1;
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-12-06 17:25:32 -06: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-12-06 17:26:12 -06:00
|
|
|
static void
|
|
|
|
long2chs(ulong ls, unsigned int *c, unsigned int *h, unsigned int *s) {
|
|
|
|
int spc = heads * sectors;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
|
|
|
*c = ls / spc;
|
|
|
|
ls = ls % spc;
|
|
|
|
*h = ls / sectors;
|
|
|
|
*s = ls % sectors + 1; /* sectors count from 1 */
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void check_consistency(struct partition *p, int partition) {
|
2006-12-06 17:26:12 -06:00
|
|
|
unsigned int pbc, pbh, pbs; /* physical beginning c, h, s */
|
|
|
|
unsigned int pec, peh, pes; /* physical ending c, h, s */
|
|
|
|
unsigned int lbc, lbh, lbs; /* logical beginning c, h, s */
|
|
|
|
unsigned int lec, leh, les; /* logical ending c, h, s */
|
2006-12-06 17:25:32 -06:00
|
|
|
|
|
|
|
if (!heads || !sectors || (partition >= 4))
|
|
|
|
return; /* do not check extended partitions */
|
|
|
|
|
|
|
|
/* physical beginning c, h, s */
|
2006-12-06 17:25:34 -06:00
|
|
|
pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
|
2006-12-06 17:25:32 -06:00
|
|
|
pbh = p->head;
|
|
|
|
pbs = p->sector & 0x3f;
|
|
|
|
|
|
|
|
/* physical ending c, h, s */
|
2006-12-06 17:25:34 -06:00
|
|
|
pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
|
2006-12-06 17:25:32 -06:00
|
|
|
peh = p->end_head;
|
|
|
|
pes = p->end_sector & 0x3f;
|
|
|
|
|
|
|
|
/* compute logical beginning (c, h, s) */
|
2006-12-06 17:25:35 -06:00
|
|
|
long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
|
|
|
/* compute logical ending (c, h, s) */
|
2006-12-06 17:25:35 -06:00
|
|
|
long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
|
|
|
/* Same physical / logical beginning? */
|
|
|
|
if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
|
2006-12-06 17:25:39 -06:00
|
|
|
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);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Same physical / logical ending? */
|
|
|
|
if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
|
2006-12-06 17:25:39 -06:00
|
|
|
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);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:33 -06:00
|
|
|
#if 0
|
2006-12-06 17:25:32 -06:00
|
|
|
/* Beginning on cylinder boundary? */
|
|
|
|
if (pbh != !pbc || pbs != 1) {
|
2006-12-06 17:25:39 -06:00
|
|
|
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);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2006-12-06 17:25:33 -06:00
|
|
|
#endif
|
2006-12-06 17:25:32 -06:00
|
|
|
|
|
|
|
/* Ending on cylinder boundary? */
|
|
|
|
if (peh != (heads - 1) || pes != sectors) {
|
2006-12-06 17:26:08 -06:00
|
|
|
printf(_("Partition %i does not end on cylinder boundary.\n"),
|
2006-12-06 17:25:32 -06:00
|
|
|
partition + 1);
|
2006-12-06 17:26:03 -06:00
|
|
|
#if 0
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
|
|
|
|
printf(_("should be (%d, %d, %d)\n"),
|
2006-12-06 17:25:32 -06:00
|
|
|
pec, heads - 1, sectors);
|
2006-12-06 17:26:03 -06:00
|
|
|
#endif
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
list_disk_geometry(void) {
|
2006-12-06 17:26:12 -06:00
|
|
|
long long bytes = (total_number_of_sectors << 9);
|
2006-12-06 17:26:03 -06:00
|
|
|
long megabytes = bytes/1000000;
|
|
|
|
|
|
|
|
if (megabytes < 10000)
|
|
|
|
printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
|
|
|
|
disk_device, megabytes, bytes);
|
|
|
|
else
|
|
|
|
printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
|
|
|
|
disk_device, megabytes/1000, (megabytes/100)%10, bytes);
|
2007-05-30 10:10:43 -05:00
|
|
|
printf(_("%d heads, %llu sectors/track, %d cylinders"),
|
2006-12-06 17:26:03 -06:00
|
|
|
heads, sectors, cylinders);
|
|
|
|
if (units_per_sector == 1)
|
2006-12-06 17:26:12 -06:00
|
|
|
printf(_(", total %llu sectors"),
|
2006-12-06 17:26:03 -06:00
|
|
|
total_number_of_sectors / (sector_size/512));
|
|
|
|
printf("\n");
|
2007-07-06 20:32:31 -05:00
|
|
|
printf(_("Units = %s of %d * %d = %d bytes\n"),
|
2006-12-06 17:26:03 -06:00
|
|
|
str_units(PLURAL),
|
|
|
|
units_per_sector, sector_size, units_per_sector * sector_size);
|
2007-07-06 20:32:31 -05:00
|
|
|
if (dos_label)
|
|
|
|
dos_print_mbr_id();
|
|
|
|
printf("\n");
|
2006-12-06 17:25:37 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06: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
|
|
|
|
wrong_p_order(int *prev) {
|
|
|
|
struct pte *pe;
|
|
|
|
struct partition *p;
|
2006-12-06 17:26:12 -06:00
|
|
|
unsigned int last_p_start_pos = 0, p_start_pos;
|
2006-12-06 17:25:43 -06: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;
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:48 -06:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
fix_chain_of_logicals(void) {
|
|
|
|
int j, oj, ojj, sj, sjj;
|
|
|
|
struct partition *pj,*pjj,tmp;
|
|
|
|
|
|
|
|
/* Stage 1: sort sectors but leave sector of part 4 */
|
|
|
|
/* (Its sector is the global extended_offset.) */
|
|
|
|
stage1:
|
2006-12-06 17:25:58 -06:00
|
|
|
for (j = 5; j < partitions-1; j++) {
|
2006-12-06 17:25:48 -06:00
|
|
|
oj = ptes[j].offset;
|
|
|
|
ojj = ptes[j+1].offset;
|
|
|
|
if (oj > ojj) {
|
|
|
|
ptes[j].offset = ojj;
|
|
|
|
ptes[j+1].offset = oj;
|
|
|
|
pj = ptes[j].part_table;
|
|
|
|
set_start_sect(pj, get_start_sect(pj)+oj-ojj);
|
|
|
|
pjj = ptes[j+1].part_table;
|
|
|
|
set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
|
|
|
|
set_start_sect(ptes[j-1].ext_pointer,
|
|
|
|
ojj-extended_offset);
|
|
|
|
set_start_sect(ptes[j].ext_pointer,
|
|
|
|
oj-extended_offset);
|
|
|
|
goto stage1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Stage 2: sort starting sectors */
|
|
|
|
stage2:
|
2006-12-06 17:25:58 -06:00
|
|
|
for (j = 4; j < partitions-1; j++) {
|
2006-12-06 17:25:48 -06:00
|
|
|
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 */
|
2006-12-06 17:25:58 -06:00
|
|
|
for (j = 4; j < partitions; j++)
|
2006-12-06 17:25:48 -06:00
|
|
|
ptes[j].changed = 1;
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
fix_partition_table_order(void) {
|
2006-12-06 17:25:48 -06:00
|
|
|
struct pte *pei, *pek;
|
2006-12-06 17:25:43 -06:00
|
|
|
int i,k;
|
|
|
|
|
2006-12-06 17:25:58 -06:00
|
|
|
if (!wrong_p_order(NULL)) {
|
2006-12-06 17:25:43 -06:00
|
|
|
printf(_("Nothing to do. Ordering is correct already.\n\n"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:48 -06:00
|
|
|
while ((i = wrong_p_order(&k)) != 0 && i < 4) {
|
2006-12-06 17:25:43 -06:00
|
|
|
/* partition i should have come earlier, move it */
|
2006-12-06 17:25:48 -06:00
|
|
|
/* We have to move data in the MBR */
|
|
|
|
struct partition *pi, *pk, *pe, pbuf;
|
2006-12-06 17:25:43 -06:00
|
|
|
pei = &ptes[i];
|
|
|
|
pek = &ptes[k];
|
|
|
|
|
2006-12-06 17:25:48 -06:00
|
|
|
pe = pei->ext_pointer;
|
|
|
|
pei->ext_pointer = pek->ext_pointer;
|
|
|
|
pek->ext_pointer = pe;
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2006-12-06 17:25:48 -06:00
|
|
|
pi = pei->part_table;
|
|
|
|
pk = pek->part_table;
|
2006-12-06 17:25:43 -06:00
|
|
|
|
2006-12-06 17:25:48 -06:00
|
|
|
memmove(&pbuf, pi, sizeof(struct partition));
|
|
|
|
memmove(pi, pk, sizeof(struct partition));
|
|
|
|
memmove(pk, &pbuf, sizeof(struct partition));
|
2006-12-06 17:25:43 -06:00
|
|
|
|
|
|
|
pei->changed = pek->changed = 1;
|
|
|
|
}
|
2006-12-06 17:25:48 -06:00
|
|
|
|
|
|
|
if (i)
|
|
|
|
fix_chain_of_logicals();
|
|
|
|
|
|
|
|
printf("Done.\n");
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
list_table(int xtra) {
|
2006-12-06 17:25:32 -06:00
|
|
|
struct partition *p;
|
|
|
|
char *type;
|
2006-12-06 17:25:35 -06:00
|
|
|
int i, w;
|
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
if (sun_label) {
|
2006-12-06 17:25:35 -06:00
|
|
|
sun_list_table(xtra);
|
2006-12-06 17:25:37 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sgi_label) {
|
|
|
|
sgi_list_table(xtra);
|
|
|
|
return;
|
|
|
|
}
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
list_disk_geometry();
|
|
|
|
|
|
|
|
if (osf_label) {
|
|
|
|
xbsd_print_disklabel(xtra);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:26:24 -06:00
|
|
|
if (is_garbage_table()) {
|
|
|
|
printf(_("This doesn't look like a partition table\n"
|
|
|
|
"Probably you selected the wrong device.\n\n"));
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
/* 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. */
|
2006-12-06 17:25:43 -06:00
|
|
|
w = strlen(disk_device);
|
|
|
|
if (w && isdigit(disk_device[w-1]))
|
|
|
|
w++;
|
2006-12-06 17:25:32 -06:00
|
|
|
if (w < 5)
|
|
|
|
w = 5;
|
2006-12-06 17:25:39 -06:00
|
|
|
|
2006-12-06 17:26:12 -06:00
|
|
|
printf(_("%*s Boot Start End Blocks Id System\n"),
|
2006-12-06 17:25:43 -06:00
|
|
|
w+1, _("Device"));
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2006-12-06 17:26:03 -06:00
|
|
|
for (i = 0; i < partitions; i++) {
|
2006-12-06 17:25:43 -06:00
|
|
|
struct pte *pe = &ptes[i];
|
|
|
|
|
|
|
|
p = pe->part_table;
|
2006-12-06 17:25:49 -06:00
|
|
|
if (p && !is_cleared_partition(p)) {
|
2006-12-06 17:25:35 -06:00
|
|
|
unsigned int psects = get_nr_sects(p);
|
2006-12-06 17:25:37 -06:00
|
|
|
unsigned int pblocks = psects;
|
|
|
|
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);
|
2006-12-06 17:25:35 -06:00
|
|
|
printf(
|
2006-12-06 17:26:12 -06:00
|
|
|
"%s %c %11lu %11lu %11lu%c %2x %s\n",
|
2006-12-06 17:25:43 -06:00
|
|
|
partname(disk_device, i+1, w+2),
|
2006-12-06 17:25:33 -06:00
|
|
|
/* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
|
2006-12-06 17:25:32 -06:00
|
|
|
? '*' : '?',
|
2006-12-06 17:26:12 -06:00
|
|
|
/* start */ (unsigned long) cround(get_partition_start(pe)),
|
|
|
|
/* end */ (unsigned long) cround(get_partition_start(pe) + psects
|
2006-12-06 17:25:35 -06:00
|
|
|
- (psects ? 1 : 0)),
|
2006-12-06 17:26:12 -06:00
|
|
|
/* odd flag on end */ (unsigned long) pblocks, podd ? '+' : ' ',
|
2006-12-06 17:25:33 -06:00
|
|
|
/* type id */ p->sys_ind,
|
|
|
|
/* type name */ (type = partition_type(p->sys_ind)) ?
|
2006-12-06 17:25:39 -06:00
|
|
|
type : _("Unknown"));
|
2006-12-06 17:25:32 -06:00
|
|
|
check_consistency(p, i);
|
|
|
|
}
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
2006-12-06 17:25:46 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
/* Is partition table in disk order? It need not be, but... */
|
|
|
|
/* partition table entries are not checked for correct order if this
|
|
|
|
is a sgi, sun or aix labeled disk... */
|
|
|
|
if (dos_label && wrong_p_order(NULL)) {
|
|
|
|
printf(_("\nPartition table entries are not in disk order\n"));
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
x_list_table(int extend) {
|
|
|
|
struct pte *pe;
|
|
|
|
struct partition *p;
|
2006-12-06 17:25:32 -06:00
|
|
|
int i;
|
|
|
|
|
2007-05-30 10:10:43 -05:00
|
|
|
printf(_("\nDisk %s: %d heads, %llu sectors, %d cylinders\n\n"),
|
2006-12-06 17:25:32 -06:00
|
|
|
disk_device, heads, sectors, cylinders);
|
2006-12-06 17:26:12 -06:00
|
|
|
printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
|
2006-12-06 17:25:43 -06:00
|
|
|
for (i = 0 ; i < partitions; i++) {
|
|
|
|
pe = &ptes[i];
|
|
|
|
p = (extend ? pe->ext_pointer : pe->part_table);
|
|
|
|
if (p != NULL) {
|
2007-05-30 10:10:43 -05:00
|
|
|
printf("%2d %02x%4d%4d%5d%4d%4d%5d%11lu%11lu %02x\n",
|
2006-12-06 17:25:32 -06: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),
|
2007-05-30 10:10:43 -05:00
|
|
|
(unsigned long) get_start_sect(p),
|
|
|
|
(unsigned long) get_nr_sects(p), p->sys_ind);
|
2006-12-06 17:25:32 -06:00
|
|
|
if (p->sys_ind)
|
|
|
|
check_consistency(p, i);
|
|
|
|
}
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
2007-05-30 10:10:43 -05:00
|
|
|
fill_bounds(unsigned long long *first, unsigned long long *last) {
|
2006-12-06 17:25:32 -06:00
|
|
|
int i;
|
2006-12-06 17:25:43 -06:00
|
|
|
struct pte *pe = &ptes[0];
|
|
|
|
struct partition *p;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
for (i = 0; i < partitions; pe++,i++) {
|
|
|
|
p = pe->part_table;
|
2006-12-06 17:25:35 -06:00
|
|
|
if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
|
2006-12-06 17:25:37 -06:00
|
|
|
first[i] = 0xffffffff;
|
2006-12-06 17:25:32 -06:00
|
|
|
last[i] = 0;
|
2006-12-06 17:25:35 -06:00
|
|
|
} else {
|
2006-12-06 17:25:43 -06:00
|
|
|
first[i] = get_partition_start(pe);
|
2006-12-06 17:25:37 -06:00
|
|
|
last[i] = first[i] + get_nr_sects(p) - 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
2006-12-06 17:26:12 -06:00
|
|
|
check(int n, unsigned int h, unsigned int s, unsigned int c,
|
|
|
|
unsigned int start) {
|
|
|
|
unsigned int total, real_s, real_c;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
|
|
|
real_s = sector(s) - 1;
|
|
|
|
real_c = cylinder(s, c);
|
|
|
|
total = (real_c * sectors + real_s) * heads + h;
|
|
|
|
if (!total)
|
2006-12-06 17:25:39 -06:00
|
|
|
fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
|
2006-12-06 17:25:32 -06:00
|
|
|
if (h >= heads)
|
|
|
|
fprintf(stderr,
|
2006-12-06 17:25:39 -06:00
|
|
|
_("Partition %d: head %d greater than maximum %d\n"),
|
2006-12-06 17:25:32 -06:00
|
|
|
n, h + 1, heads);
|
|
|
|
if (real_s >= sectors)
|
2006-12-06 17:25:39 -06:00
|
|
|
fprintf(stderr, _("Partition %d: sector %d greater than "
|
2007-05-30 10:10:43 -05:00
|
|
|
"maximum %llu\n"), n, s, sectors);
|
2006-12-06 17:25:32 -06:00
|
|
|
if (real_c >= cylinders)
|
2006-12-06 17:25:39 -06:00
|
|
|
fprintf(stderr, _("Partitions %d: cylinder %d greater than "
|
|
|
|
"maximum %d\n"), n, real_c + 1, cylinders);
|
2006-12-06 17:25:33 -06:00
|
|
|
if (cylinders <= 1024 && start != total)
|
2006-12-06 17:25:32 -06:00
|
|
|
fprintf(stderr,
|
2006-12-06 17:25:39 -06:00
|
|
|
_("Partition %d: previous sectors %d disagrees with "
|
|
|
|
"total %d\n"), n, start, total);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
verify(void) {
|
2006-12-06 17:25:32 -06:00
|
|
|
int i, j;
|
2007-05-30 10:10:43 -05:00
|
|
|
unsigned long total = 1;
|
|
|
|
unsigned long long first[partitions], last[partitions];
|
2006-12-06 17:25:46 -06:00
|
|
|
struct partition *p;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
|
|
|
if (warn_geometry())
|
|
|
|
return;
|
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
if (sun_label) {
|
2006-12-06 17:25:35 -06:00
|
|
|
verify_sun();
|
2006-12-06 17:25:37 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sgi_label) {
|
|
|
|
verify_sgi(1);
|
|
|
|
return;
|
|
|
|
}
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
fill_bounds(first, last);
|
2006-12-06 17:25:43 -06:00
|
|
|
for (i = 0; i < partitions; i++) {
|
|
|
|
struct pte *pe = &ptes[i];
|
|
|
|
|
|
|
|
p = pe->part_table;
|
2006-12-06 17:25:35 -06:00
|
|
|
if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
|
2006-12-06 17:25:32 -06:00
|
|
|
check_consistency(p, i);
|
2006-12-06 17:25:43 -06:00
|
|
|
if (get_partition_start(pe) < first[i])
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Warning: bad start-of-data in "
|
|
|
|
"partition %d\n"), i + 1);
|
2006-12-06 17:25:32 -06:00
|
|
|
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++)
|
2006-12-06 17:25:34 -06:00
|
|
|
if ((first[i] >= first[j] && first[i] <= last[j])
|
|
|
|
|| ((last[i] <= last[j] && last[i] >= first[j]))) {
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Warning: partition %d overlaps "
|
|
|
|
"partition %d.\n"), j + 1, i + 1);
|
2006-12-06 17:25:32 -06:00
|
|
|
total += first[i] >= first[j] ?
|
|
|
|
first[i] : first[j];
|
|
|
|
total -= last[i] <= last[j] ?
|
|
|
|
last[i] : last[j];
|
|
|
|
}
|
|
|
|
}
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
|
|
|
|
if (extended_offset) {
|
2006-12-06 17:25:43 -06:00
|
|
|
struct pte *pex = &ptes[ext_index];
|
2007-05-30 10:10:43 -05:00
|
|
|
unsigned long long e_last = get_start_sect(pex->part_table) +
|
2006-12-06 17:25:43 -06:00
|
|
|
get_nr_sects(pex->part_table) - 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
for (i = 4; i < partitions; i++) {
|
2006-12-06 17:25:32 -06:00
|
|
|
total++;
|
2006-12-06 17:25:43 -06:00
|
|
|
p = ptes[i].part_table;
|
2006-12-06 17:25:32 -06:00
|
|
|
if (!p->sys_ind) {
|
|
|
|
if (i != 4 || i + 1 < partitions)
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Warning: partition %d "
|
|
|
|
"is empty\n"), i + 1);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
else if (first[i] < extended_offset ||
|
|
|
|
last[i] > e_last)
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Logical partition %d not entirely in "
|
|
|
|
"partition %d\n"), i + 1, ext_index + 1);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:26:14 -06:00
|
|
|
if (total > total_number_of_sectors)
|
2007-05-30 10:10:43 -05:00
|
|
|
printf(_("Total allocated sectors %ld greater than the maximum"
|
|
|
|
" %lld\n"), total, total_number_of_sectors);
|
2006-12-06 17:26:14 -06:00
|
|
|
else if (total < total_number_of_sectors)
|
|
|
|
printf(_("%lld unallocated sectors\n"),
|
|
|
|
total_number_of_sectors - total);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
add_partition(int n, int sys) {
|
2006-12-06 17:25:41 -06:00
|
|
|
char mesg[256]; /* 48 does not suffice in Japanese */
|
2006-12-06 17:25:32 -06:00
|
|
|
int i, read = 0;
|
2006-12-06 17:25:43 -06:00
|
|
|
struct partition *p = ptes[n].part_table;
|
|
|
|
struct partition *q = ptes[ext_index].part_table;
|
2006-12-06 17:26:12 -06:00
|
|
|
long long llimit;
|
2007-05-30 10:10:43 -05:00
|
|
|
unsigned long long start, stop = 0, limit, temp,
|
2006-12-06 17:25:32 -06:00
|
|
|
first[partitions], last[partitions];
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
if (p && p->sys_ind) {
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Partition %d is already defined. Delete "
|
2006-12-06 17:25:48 -06:00
|
|
|
"it before re-adding it.\n"), n + 1);
|
2006-12-06 17:25:32 -06:00
|
|
|
return;
|
|
|
|
}
|
2006-12-06 17:25:37 -06:00
|
|
|
fill_bounds(first, last);
|
2006-12-06 17:25:32 -06:00
|
|
|
if (n < 4) {
|
|
|
|
start = sector_offset;
|
2006-12-06 17:26:12 -06:00
|
|
|
if (display_in_cyl_units || !total_number_of_sectors)
|
|
|
|
llimit = heads * sectors * cylinders - 1;
|
2006-12-06 17:26:03 -06:00
|
|
|
else
|
2006-12-06 17:26:12 -06:00
|
|
|
llimit = total_number_of_sectors - 1;
|
|
|
|
limit = llimit;
|
|
|
|
if (limit != llimit)
|
|
|
|
limit = 0x7fffffff;
|
2006-12-06 17:25:32 -06:00
|
|
|
if (extended_offset) {
|
|
|
|
first[ext_index] = extended_offset;
|
2006-12-06 17:25:35 -06:00
|
|
|
last[ext_index] = get_start_sect(q) +
|
|
|
|
get_nr_sects(q) - 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2006-12-06 17:25:35 -06:00
|
|
|
} else {
|
2006-12-06 17:25:32 -06:00
|
|
|
start = extended_offset + sector_offset;
|
2006-12-06 17:25:35 -06:00
|
|
|
limit = get_start_sect(q) + get_nr_sects(q) - 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2006-12-06 17:25:39 -06:00
|
|
|
if (display_in_cyl_units)
|
2006-12-06 17:25:32 -06:00
|
|
|
for (i = 0; i < partitions; i++)
|
2006-12-06 17:25:39 -06:00
|
|
|
first[i] = (cround(first[i]) - 1) * units_per_sector;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:46 -06:00
|
|
|
snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
|
2006-12-06 17:25:32 -06:00
|
|
|
do {
|
|
|
|
temp = start;
|
|
|
|
for (i = 0; i < partitions; i++) {
|
2006-12-06 17:25:35 -06:00
|
|
|
int lastplusoff;
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
if (start == ptes[i].offset)
|
2006-12-06 17:25:32 -06:00
|
|
|
start += sector_offset;
|
2006-12-06 17:25:35 -06:00
|
|
|
lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
|
|
|
|
if (start >= first[i] && start <= lastplusoff)
|
|
|
|
start = lastplusoff + 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
if (start > limit)
|
|
|
|
break;
|
2006-12-06 17:25:39 -06:00
|
|
|
if (start >= temp+units_per_sector && read) {
|
2007-05-30 10:10:43 -05:00
|
|
|
printf(_("Sector %llu is already allocated\n"), temp);
|
2006-12-06 17:25:35 -06:00
|
|
|
temp = start;
|
2006-12-06 17:25:32 -06:00
|
|
|
read = 0;
|
|
|
|
}
|
|
|
|
if (!read && start == temp) {
|
2006-12-06 17:26:12 -06:00
|
|
|
unsigned int i = start;
|
|
|
|
|
2006-12-06 17:25:33 -06:00
|
|
|
start = read_int(cround(i), cround(i), cround(limit),
|
2006-12-06 17:25:37 -06:00
|
|
|
0, mesg);
|
2006-12-06 17:25:39 -06:00
|
|
|
if (display_in_cyl_units) {
|
|
|
|
start = (start - 1) * units_per_sector;
|
2006-12-06 17:25:32 -06:00
|
|
|
if (start < i) start = i;
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
read = 1;
|
|
|
|
}
|
|
|
|
} while (start != temp || !read);
|
2006-12-06 17:25:39 -06:00
|
|
|
if (n > 4) { /* NOT for fifth partition */
|
2006-12-06 17:25:43 -06:00
|
|
|
struct pte *pe = &ptes[n];
|
|
|
|
|
|
|
|
pe->offset = start - sector_offset;
|
|
|
|
if (pe->offset == extended_offset) { /* must be corrected */
|
2006-12-06 17:25:48 -06:00
|
|
|
pe->offset++;
|
|
|
|
if (sector_offset == 1)
|
|
|
|
start++;
|
2006-12-06 17:25:39 -06:00
|
|
|
}
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
|
|
|
|
for (i = 0; i < partitions; i++) {
|
2006-12-06 17:25:43 -06:00
|
|
|
struct pte *pe = &ptes[i];
|
|
|
|
|
|
|
|
if (start < pe->offset && limit >= pe->offset)
|
|
|
|
limit = pe->offset - 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
if (start < first[i] && limit >= first[i])
|
|
|
|
limit = first[i] - 1;
|
|
|
|
}
|
|
|
|
if (start > limit) {
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("No free sectors available\n"));
|
2006-12-06 17:25:43 -06:00
|
|
|
if (n > 4)
|
2006-12-06 17:25:32 -06:00
|
|
|
partitions--;
|
|
|
|
return;
|
|
|
|
}
|
2006-12-06 17:25:39 -06:00
|
|
|
if (cround(start) == cround(limit)) {
|
|
|
|
stop = limit;
|
|
|
|
} else {
|
2006-12-06 17:25:46 -06:00
|
|
|
snprintf(mesg, sizeof(mesg),
|
2007-12-12 18:06:44 -06:00
|
|
|
_("Last %1$s, +%2$s or +size{K,M,G}"),
|
|
|
|
str_units(SINGULAR), str_units(PLURAL));
|
|
|
|
|
2006-12-06 17:25:33 -06:00
|
|
|
stop = read_int(cround(start), cround(limit), cround(limit),
|
2006-12-06 17:25:37 -06:00
|
|
|
cround(start), mesg);
|
2006-12-06 17:25:39 -06:00
|
|
|
if (display_in_cyl_units) {
|
|
|
|
stop = stop * units_per_sector - 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
if (stop >limit)
|
|
|
|
stop = limit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:48 -06:00
|
|
|
set_partition(n, 0, start, stop, sys);
|
|
|
|
if (n > 4)
|
|
|
|
set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
if (IS_EXTENDED (sys)) {
|
2006-12-06 17:25:43 -06:00
|
|
|
struct pte *pe4 = &ptes[4];
|
|
|
|
struct pte *pen = &ptes[n];
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
ext_index = n;
|
2006-12-06 17:25:43 -06:00
|
|
|
pen->ext_pointer = p;
|
|
|
|
pe4->offset = extended_offset = start;
|
|
|
|
if (!(pe4->sectorbuffer = calloc(1, sector_size)))
|
2006-12-06 17:25:32 -06:00
|
|
|
fatal(out_of_memory);
|
2006-12-06 17:25:43 -06:00
|
|
|
pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
|
|
|
|
pe4->ext_pointer = pe4->part_table + 1;
|
|
|
|
pe4->changed = 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
partitions = 5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
add_logical(void) {
|
|
|
|
if (partitions > 5 || ptes[4].part_table->sys_ind) {
|
|
|
|
struct pte *pe = &ptes[partitions];
|
|
|
|
|
|
|
|
if (!(pe->sectorbuffer = calloc(1, sector_size)))
|
2006-12-06 17:25:32 -06:00
|
|
|
fatal(out_of_memory);
|
2006-12-06 17:25:43 -06:00
|
|
|
pe->part_table = pt_offset(pe->sectorbuffer, 0);
|
|
|
|
pe->ext_pointer = pe->part_table + 1;
|
|
|
|
pe->offset = 0;
|
|
|
|
pe->changed = 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
partitions++;
|
|
|
|
}
|
|
|
|
add_partition(partitions - 1, LINUX_NATIVE);
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
new_partition(void) {
|
2006-12-06 17:25:32 -06:00
|
|
|
int i, free_primary = 0;
|
|
|
|
|
|
|
|
if (warn_geometry())
|
|
|
|
return;
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
if (sun_label) {
|
2006-12-06 17:25:35 -06:00
|
|
|
add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
|
2006-12-06 17:25:37 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sgi_label) {
|
|
|
|
sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
|
|
|
|
return;
|
|
|
|
}
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2006-12-06 17:25:49 -06:00
|
|
|
if (aix_label) {
|
|
|
|
printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
|
|
|
|
"\n\tIf you want to add DOS-type partitions, create"
|
|
|
|
"\n\ta new empty DOS partition table first. (Use o.)"
|
|
|
|
"\n\tWARNING: "
|
|
|
|
"This will destroy the present disk contents.\n"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-06-27 16:49:56 -05:00
|
|
|
if (mac_label) {
|
|
|
|
printf(_("\tSorry - this fdisk cannot handle Mac disk labels."
|
|
|
|
"\n\tIf you want to add DOS-type partitions, create"
|
|
|
|
"\n\ta new empty DOS partition table first. (Use o.)"
|
|
|
|
"\n\tWARNING: "
|
|
|
|
"This will destroy the present disk contents.\n"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:26:05 -06:00
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
free_primary += !ptes[i].part_table->sys_ind;
|
|
|
|
|
|
|
|
if (!free_primary && partitions >= MAXIMUM_PARTS) {
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("The maximum number of partitions has been created\n"));
|
2006-12-06 17:25:32 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
if (!free_primary) {
|
2006-12-06 17:25:32 -06:00
|
|
|
if (extended_offset)
|
|
|
|
add_logical();
|
|
|
|
else
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("You must delete some partition and add "
|
2006-12-06 17:25:46 -06:00
|
|
|
"an extended partition first\n"));
|
2006-12-06 17:26:14 -06:00
|
|
|
} else if (partitions >= MAXIMUM_PARTS) {
|
|
|
|
printf(_("All logical partitions are in use\n"));
|
|
|
|
printf(_("Adding a primary partition\n"));
|
|
|
|
add_partition(get_partition(0, 4), LINUX_NATIVE);
|
2006-12-06 17:25:37 -06:00
|
|
|
} else {
|
2006-12-06 17:25:32 -06:00
|
|
|
char c, line[LINE_LENGTH];
|
2006-12-06 17:25:46 -06:00
|
|
|
snprintf(line, sizeof(line),
|
|
|
|
_("Command action\n %s\n p primary "
|
|
|
|
"partition (1-4)\n"), extended_offset ?
|
|
|
|
_("l logical (5 or over)") : _("e extended"));
|
|
|
|
while (1) {
|
2006-12-06 17:25:32 -06:00
|
|
|
if ((c = tolower(read_char(line))) == 'p') {
|
2006-12-06 17:26:03 -06:00
|
|
|
int i = get_nonexisting_partition(0, 4);
|
|
|
|
if (i >= 0)
|
|
|
|
add_partition(i, LINUX_NATIVE);
|
2006-12-06 17:25:32 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (c == 'l' && extended_offset) {
|
|
|
|
add_logical();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (c == 'e' && !extended_offset) {
|
2006-12-06 17:26:03 -06:00
|
|
|
int i = get_nonexisting_partition(0, 4);
|
|
|
|
if (i >= 0)
|
|
|
|
add_partition(i, EXTENDED);
|
2006-12-06 17:25:32 -06:00
|
|
|
return;
|
|
|
|
}
|
2006-12-06 17:25:33 -06:00
|
|
|
else
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Invalid partition number "
|
2006-12-06 17:25:46 -06:00
|
|
|
"for type `%c'\n"), c);
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
write_table(void) {
|
2006-12-06 17:25:41 -06:00
|
|
|
int i;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
if (dos_label) {
|
|
|
|
for (i=0; i<3; i++)
|
2006-12-06 17:25:58 -06:00
|
|
|
if (ptes[i].changed)
|
2006-12-06 17:25:43 -06:00
|
|
|
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(fd, pe->offset, pe->sectorbuffer);
|
|
|
|
}
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
2006-12-06 17:25:56 -06:00
|
|
|
}
|
|
|
|
else if (sgi_label) {
|
2006-12-06 17:25:43 -06:00
|
|
|
/* no test on change? the printf below might be mistaken */
|
|
|
|
sgi_write_table();
|
2006-12-06 17:25:37 -06:00
|
|
|
} else if (sun_label) {
|
2006-12-06 17:25:43 -06:00
|
|
|
int needw = 0;
|
|
|
|
|
|
|
|
for (i=0; i<8; i++)
|
2006-12-06 17:25:58 -06:00
|
|
|
if (ptes[i].changed)
|
2006-12-06 17:25:43 -06:00
|
|
|
needw = 1;
|
|
|
|
if (needw)
|
|
|
|
sun_write_table();
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("The partition table has been altered!\n\n"));
|
2006-12-06 17:25:41 -06:00
|
|
|
reread_partition_table(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
reread_partition_table(int leave) {
|
|
|
|
int i;
|
2007-09-03 17:10:16 -05:00
|
|
|
struct stat statbuf;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2007-09-03 17:10:16 -05:00
|
|
|
i = fstat(fd, &statbuf);
|
|
|
|
if (i == 0 && S_ISBLK(statbuf.st_mode)) {
|
|
|
|
sync();
|
|
|
|
sleep(2);
|
2008-07-23 17:46:05 -05:00
|
|
|
#ifdef BLKRRPART
|
|
|
|
printf(_("Calling ioctl() to re-read partition table.\n"));
|
2007-09-03 17:10:16 -05:00
|
|
|
i = ioctl(fd, BLKRRPART);
|
2008-07-23 17:46:05 -05:00
|
|
|
#else
|
|
|
|
errno = ENOSYS;
|
|
|
|
i = 1;
|
|
|
|
#endif
|
2006-12-06 17:25:33 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:49 -06:00
|
|
|
if (i) {
|
|
|
|
printf(_("\nWARNING: 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"),
|
2007-09-03 17:10:16 -05:00
|
|
|
errno, strerror(errno));
|
2006-12-06 17:25:49 -06:00
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:49 -06:00
|
|
|
if (dos_changed)
|
2006-12-06 17:25:35 -06:00
|
|
|
printf(
|
2006-12-06 17:25:39 -06:00
|
|
|
_("\nWARNING: If you have created or modified any DOS 6.x\n"
|
2006-12-06 17:25:32 -06:00
|
|
|
"partitions, please see the fdisk manual page for additional\n"
|
2006-12-06 17:25:39 -06:00
|
|
|
"information.\n"));
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:41 -06:00
|
|
|
if (leave) {
|
2006-12-06 17:26:30 -06:00
|
|
|
if (fsync(fd) || close(fd)) {
|
|
|
|
fprintf(stderr, _("\nError closing file\n"));
|
|
|
|
exit(1);
|
|
|
|
}
|
2006-12-06 17:25:41 -06:00
|
|
|
|
|
|
|
printf(_("Syncing disks.\n"));
|
|
|
|
sync();
|
|
|
|
sleep(4); /* for sync() */
|
|
|
|
exit(!!i);
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#define MAX_PER_LINE 16
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
2007-05-30 10:10:43 -05:00
|
|
|
print_buffer(unsigned char pbuffer[]) {
|
2006-12-06 17:25:32 -06:00
|
|
|
int i,
|
|
|
|
l;
|
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
for (i = 0, l = 0; i < sector_size; i++, l++) {
|
2006-12-06 17:25:32 -06:00
|
|
|
if (l == 0)
|
|
|
|
printf("0x%03X:", i);
|
2007-05-30 10:10:43 -05:00
|
|
|
printf(" %02X", pbuffer[i]);
|
2006-12-06 17:25:32 -06:00
|
|
|
if (l == MAX_PER_LINE - 1) {
|
|
|
|
printf("\n");
|
|
|
|
l = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (l > 0)
|
|
|
|
printf("\n");
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
print_raw(void) {
|
2006-12-06 17:25:32 -06:00
|
|
|
int i;
|
|
|
|
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Device: %s\n"), disk_device);
|
2006-12-06 17:25:37 -06:00
|
|
|
if (sun_label || sgi_label)
|
2006-12-06 17:25:43 -06:00
|
|
|
print_buffer(MBRbuffer);
|
2006-12-06 17:25:35 -06:00
|
|
|
else for (i = 3; i < partitions; i++)
|
2006-12-06 17:25:43 -06:00
|
|
|
print_buffer(ptes[i].sectorbuffer);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
move_begin(int i) {
|
|
|
|
struct pte *pe = &ptes[i];
|
|
|
|
struct partition *p = pe->part_table;
|
2006-12-06 17:26:12 -06:00
|
|
|
unsigned int new, first;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
|
|
|
if (warn_geometry())
|
|
|
|
return;
|
2006-12-06 17:25:35 -06:00
|
|
|
if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("Partition %d has no data area\n"), i + 1);
|
2006-12-06 17:25:32 -06:00
|
|
|
return;
|
|
|
|
}
|
2006-12-06 17:25:43 -06:00
|
|
|
first = get_partition_start(pe);
|
|
|
|
new = read_int(first, first, first + get_nr_sects(p) - 1, first,
|
|
|
|
_("New beginning of data")) - pe->offset;
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:35 -06: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);
|
2006-12-06 17:25:43 -06:00
|
|
|
pe->changed = 1;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
xselect(void) {
|
|
|
|
char c;
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
while(1) {
|
|
|
|
putchar('\n');
|
2006-12-06 17:25:43 -06:00
|
|
|
c = tolower(read_char(_("Expert command (m for help): ")));
|
|
|
|
switch (c) {
|
2006-12-06 17:25:35 -06:00
|
|
|
case 'a':
|
|
|
|
if (sun_label)
|
|
|
|
sun_set_alt_cyl();
|
|
|
|
break;
|
|
|
|
case 'b':
|
2006-12-06 17:25:43 -06:00
|
|
|
if (dos_label)
|
2006-12-06 17:25:35 -06:00
|
|
|
move_begin(get_partition(0, partitions));
|
|
|
|
break;
|
|
|
|
case 'c':
|
2006-12-06 17:25:43 -06:00
|
|
|
user_cylinders = cylinders =
|
2006-12-06 17:25:56 -06:00
|
|
|
read_int(1, cylinders, 1048576, 0,
|
2006-12-06 17:25:43 -06:00
|
|
|
_("Number of cylinders"));
|
2006-12-06 17:25:35 -06:00
|
|
|
if (sun_label)
|
|
|
|
sun_set_ncyl(cylinders);
|
2006-12-06 17:25:43 -06:00
|
|
|
if (dos_label)
|
|
|
|
warn_cylinders();
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
print_raw();
|
|
|
|
break;
|
|
|
|
case 'e':
|
2006-12-06 17:25:37 -06:00
|
|
|
if (sgi_label)
|
|
|
|
sgi_set_xcyl();
|
|
|
|
else if (sun_label)
|
2006-12-06 17:25:35 -06:00
|
|
|
sun_set_xcyl();
|
2006-12-06 17:25:56 -06:00
|
|
|
else
|
|
|
|
if (dos_label)
|
2006-12-06 17:25:37 -06:00
|
|
|
x_list_table(1);
|
|
|
|
break;
|
2006-12-06 17:25:43 -06:00
|
|
|
case 'f':
|
2006-12-06 17:25:58 -06:00
|
|
|
if (dos_label)
|
2006-12-06 17:25:43 -06:00
|
|
|
fix_partition_table_order();
|
|
|
|
break;
|
2006-12-06 17:25:37 -06:00
|
|
|
case 'g':
|
|
|
|
create_sgilabel();
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'h':
|
2006-12-06 17:25:43 -06:00
|
|
|
user_heads = heads = read_int(1, heads, 256, 0,
|
2006-12-06 17:25:39 -06:00
|
|
|
_("Number of heads"));
|
2006-12-06 17:25:35 -06:00
|
|
|
update_units();
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
if (sun_label)
|
|
|
|
sun_set_ilfact();
|
2007-07-06 20:32:31 -05:00
|
|
|
if (dos_label)
|
|
|
|
dos_set_mbr_id();
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
if (sun_label)
|
|
|
|
sun_set_rspeed();
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
if (sun_label)
|
|
|
|
list_table(1);
|
|
|
|
else
|
|
|
|
x_list_table(0);
|
|
|
|
break;
|
|
|
|
case 'q':
|
|
|
|
close(fd);
|
2006-12-06 17:25:39 -06:00
|
|
|
printf("\n");
|
2006-12-06 17:25:35 -06:00
|
|
|
exit(0);
|
|
|
|
case 'r':
|
|
|
|
return;
|
|
|
|
case 's':
|
2006-12-06 17:25:43 -06:00
|
|
|
user_sectors = sectors = read_int(1, sectors, 63, 0,
|
2006-12-06 17:25:39 -06:00
|
|
|
_("Number of sectors"));
|
2006-12-06 17:25:35 -06:00
|
|
|
if (dos_compatible_flag) {
|
|
|
|
sector_offset = sectors;
|
2006-12-06 17:25:39 -06:00
|
|
|
fprintf(stderr, _("Warning: setting "
|
2006-12-06 17:25:35 -06:00
|
|
|
"sector offset for DOS "
|
2006-12-06 17:25:39 -06:00
|
|
|
"compatiblity\n"));
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
|
|
|
update_units();
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
verify();
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
write_table(); /* does not return */
|
|
|
|
break;
|
|
|
|
case 'y':
|
|
|
|
if (sun_label)
|
|
|
|
sun_set_pcylcount();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
xmenu();
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static int
|
2006-12-06 17:25:49 -06:00
|
|
|
is_ide_cdrom_or_tape(char *device) {
|
|
|
|
FILE *procf;
|
|
|
|
char buf[100];
|
|
|
|
struct stat statbuf;
|
|
|
|
int is_ide = 0;
|
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
/* No device was given explicitly, and we are trying some
|
2006-12-06 17:25:49 -06:00
|
|
|
likely things. But opening /dev/hdc may produce errors like
|
2006-12-06 17:25:35 -06:00
|
|
|
"hdc: tray open or drive not ready"
|
2006-12-06 17:25:49 -06:00
|
|
|
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. */
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2006-12-06 17:25:49 -06:00
|
|
|
if (strncmp("/dev/hd", device, 7))
|
|
|
|
return 0;
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2006-12-06 17:25:49 -06:00
|
|
|
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);
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2006-12-06 17:25:49 -06:00
|
|
|
if (procf)
|
|
|
|
fclose(procf);
|
|
|
|
return is_ide;
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
|
|
|
|
2007-05-31 07:31:51 -05:00
|
|
|
static void
|
|
|
|
gpt_warning(char *dev)
|
|
|
|
{
|
|
|
|
if (dev && gpt_probe_signature_devname(dev))
|
|
|
|
fprintf(stderr, _("\nWARNING: GPT (GUID Partition Table) detected on '%s'! "
|
|
|
|
"The util fdisk doesn't support GPT. Use GNU Parted.\n\n"), dev);
|
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
try(char *device, int user_specified) {
|
2006-12-06 17:25:49 -06:00
|
|
|
int gb;
|
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
disk_device = device;
|
2006-12-06 17:25:46 -06:00
|
|
|
if (setjmp(listingbuf))
|
|
|
|
return;
|
|
|
|
if (!user_specified)
|
2006-12-06 17:25:49 -06:00
|
|
|
if (is_ide_cdrom_or_tape(device))
|
2006-12-06 17:25:46 -06:00
|
|
|
return;
|
2007-05-31 07:31:51 -05:00
|
|
|
gpt_warning(device);
|
2006-12-06 17:25:46 -06:00
|
|
|
if ((fd = open(disk_device, type_open)) >= 0) {
|
2006-12-06 17:25:49 -06:00
|
|
|
gb = get_boot(try_only);
|
2006-12-06 17:26:16 -06:00
|
|
|
if (gb > 0) { /* I/O error */
|
2006-12-06 17:25:49 -06:00
|
|
|
} else if (gb < 0) { /* no DOS signature */
|
2006-12-06 17:25:46 -06:00
|
|
|
list_disk_geometry();
|
2007-06-27 16:49:56 -05:00
|
|
|
if (!aix_label && !mac_label && btrydev(device) < 0)
|
2006-12-06 17:25:46 -06:00
|
|
|
fprintf(stderr,
|
|
|
|
_("Disk %s doesn't contain a valid "
|
|
|
|
"partition table\n"), device);
|
2006-12-06 17:25:34 -06:00
|
|
|
} else {
|
2006-12-06 17:25:46 -06:00
|
|
|
list_table(0);
|
|
|
|
}
|
2006-12-06 17:26:16 -06:00
|
|
|
close(fd);
|
2006-12-06 17:25:46 -06:00
|
|
|
} else {
|
|
|
|
/* Ignore other errors, since we try IDE
|
|
|
|
and SCSI hard disks which may not be
|
|
|
|
installed on the system. */
|
2006-12-06 17:25:58 -06:00
|
|
|
if (errno == EACCES) {
|
2006-12-06 17:25:46 -06:00
|
|
|
fprintf(stderr, _("Cannot open %s\n"), device);
|
|
|
|
return;
|
2006-12-06 17:25:34 -06:00
|
|
|
}
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:26:16 -06:00
|
|
|
/*
|
|
|
|
* for fdisk -l:
|
|
|
|
* try all things in /proc/partitions that look like a full disk
|
|
|
|
*/
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
tryprocpt(void) {
|
2006-12-06 17:25:41 -06:00
|
|
|
FILE *procpt;
|
2006-12-06 17:26:16 -06:00
|
|
|
char line[100], ptname[100], devname[120];
|
2006-12-06 17:25:41 -06:00
|
|
|
int ma, mi, sz;
|
|
|
|
|
|
|
|
procpt = fopen(PROC_PARTITIONS, "r");
|
|
|
|
if (procpt == NULL) {
|
|
|
|
fprintf(stderr, _("cannot open %s\n"), PROC_PARTITIONS);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (fgets(line, sizeof(line), procpt)) {
|
2006-12-06 17:25:46 -06:00
|
|
|
if (sscanf (line, " %d %d %d %[^\n ]",
|
2006-12-06 17:25:41 -06:00
|
|
|
&ma, &mi, &sz, ptname) != 4)
|
|
|
|
continue;
|
2006-12-06 17:25:46 -06:00
|
|
|
snprintf(devname, sizeof(devname), "/dev/%s", ptname);
|
2006-12-06 17:26:16 -06:00
|
|
|
if (is_probably_full_disk(devname))
|
|
|
|
try(devname, 0);
|
2006-12-06 17:25:41 -06:00
|
|
|
}
|
2006-12-06 17:25:49 -06:00
|
|
|
fclose(procpt);
|
2006-12-06 17:25:41 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
dummy(int *kk) {}
|
2006-12-06 17:25:39 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
static void
|
|
|
|
unknown_command(int c) {
|
|
|
|
printf(_("%c: unknown command\n"), c);
|
2006-12-06 17:25:39 -06:00
|
|
|
}
|
|
|
|
|
2007-05-31 07:31:51 -05:00
|
|
|
|
|
|
|
|
2006-12-06 17:25:37 -06:00
|
|
|
int
|
2006-12-06 17:25:41 -06:00
|
|
|
main(int argc, char **argv) {
|
2006-12-06 17:25:39 -06:00
|
|
|
int j, c;
|
2006-12-06 17:25:35 -06:00
|
|
|
int optl = 0, opts = 0;
|
|
|
|
|
2006-12-06 17:25:39 -06:00
|
|
|
setlocale(LC_ALL, "");
|
|
|
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
|
|
|
textdomain(PACKAGE);
|
2006-12-06 17:25:35 -06:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Calls:
|
|
|
|
* fdisk -v
|
2006-12-06 17:25:39 -06:00
|
|
|
* fdisk -l [-b sectorsize] [-u] device ...
|
2006-12-06 17:25:35 -06:00
|
|
|
* fdisk -s [partition] ...
|
2006-12-06 17:25:39 -06:00
|
|
|
* fdisk [-b sectorsize] [-u] device
|
2006-12-06 17:26:02 -06:00
|
|
|
*
|
|
|
|
* Options -C, -H, -S set the geometry.
|
|
|
|
*
|
2006-12-06 17:25:35 -06:00
|
|
|
*/
|
2006-12-06 17:26:02 -06:00
|
|
|
while ((c = getopt(argc, argv, "b:C:H:lsS:uvV")) != -1) {
|
2006-12-06 17:25:35 -06:00
|
|
|
switch (c) {
|
|
|
|
case 'b':
|
2006-12-06 17:26:02 -06:00
|
|
|
/* 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.
|
|
|
|
*/
|
2006-12-06 17:25:37 -06:00
|
|
|
sector_size = atoi(optarg);
|
|
|
|
if (sector_size != 512 && sector_size != 1024 &&
|
|
|
|
sector_size != 2048)
|
|
|
|
fatal(usage);
|
|
|
|
sector_offset = 2;
|
2006-12-06 17:25:39 -06:00
|
|
|
user_set_sector_size = 1;
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
2006-12-06 17:26:02 -06:00
|
|
|
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;
|
2006-12-06 17:25:35 -06:00
|
|
|
case 'l':
|
|
|
|
optl = 1;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
opts = 1;
|
|
|
|
break;
|
|
|
|
case 'u':
|
2006-12-06 17:25:39 -06:00
|
|
|
display_in_cyl_units = 0;
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
2006-12-06 17:25:43 -06:00
|
|
|
case 'V':
|
2006-12-06 17:25:35 -06:00
|
|
|
case 'v':
|
2006-12-06 17:26:58 -06:00
|
|
|
printf("fdisk (%s)\n", PACKAGE_STRING);
|
2006-12-06 17:25:35 -06:00
|
|
|
exit(0);
|
|
|
|
default:
|
|
|
|
fatal(usage);
|
|
|
|
}
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2006-12-06 17:25:35 -06:00
|
|
|
|
2006-12-06 17:25:39 -06:00
|
|
|
#if 0
|
2006-12-06 17:25:58 -06:00
|
|
|
printf(_("This kernel finds the sector size itself - "
|
|
|
|
"-b option ignored\n"));
|
2006-12-06 17:25:39 -06:00
|
|
|
#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
|
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
if (optl) {
|
|
|
|
nowarn = 1;
|
|
|
|
type_open = O_RDONLY;
|
|
|
|
if (argc > optind) {
|
|
|
|
int k;
|
|
|
|
/* avoid gcc warning:
|
|
|
|
variable `k' might be clobbered by `longjmp' */
|
|
|
|
dummy(&k);
|
2006-12-06 17:25:41 -06:00
|
|
|
listing = 1;
|
2006-12-06 17:26:16 -06:00
|
|
|
for (k = optind; k < argc; k++)
|
2006-12-06 17:25:35 -06:00
|
|
|
try(argv[k], 1);
|
|
|
|
} else {
|
2006-12-06 17:25:39 -06:00
|
|
|
/* we no longer have default device names */
|
2006-12-06 17:26:16 -06:00
|
|
|
/* but we can use /proc/partitions instead */
|
2006-12-06 17:25:41 -06:00
|
|
|
tryprocpt();
|
2006-12-06 17:25:35 -06:00
|
|
|
}
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opts) {
|
2006-12-06 17:26:18 -06:00
|
|
|
unsigned long long size;
|
2006-12-06 17:25:39 -06:00
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
nowarn = 1;
|
|
|
|
type_open = O_RDONLY;
|
|
|
|
|
|
|
|
opts = argc - optind;
|
|
|
|
if (opts <= 0)
|
|
|
|
fatal(usage);
|
|
|
|
|
|
|
|
for (j = optind; j < argc; j++) {
|
2006-12-06 17:25:39 -06:00
|
|
|
disk_device = argv[j];
|
2007-05-31 07:31:51 -05:00
|
|
|
gpt_warning(disk_device);
|
2006-12-06 17:25:35 -06:00
|
|
|
if ((fd = open(disk_device, type_open)) < 0)
|
|
|
|
fatal(unable_to_open);
|
2007-11-07 12:05:31 -06:00
|
|
|
if (blkdev_get_sectors(fd, &size) == -1)
|
2006-12-06 17:25:39 -06:00
|
|
|
fatal(ioctl_error);
|
2006-12-06 17:25:35 -06:00
|
|
|
close(fd);
|
|
|
|
if (opts == 1)
|
2006-12-06 17:26:18 -06:00
|
|
|
printf("%llu\n", size/2);
|
2006-12-06 17:25:35 -06:00
|
|
|
else
|
2006-12-06 17:26:18 -06:00
|
|
|
printf("%s: %llu\n", argv[j], size/2);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
2006-12-06 17:25:35 -06:00
|
|
|
exit(0);
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
|
2006-12-06 17:25:35 -06:00
|
|
|
if (argc-optind == 1)
|
|
|
|
disk_device = argv[optind];
|
|
|
|
else if (argc-optind != 0)
|
|
|
|
fatal(usage);
|
2006-12-06 17:25:39 -06:00
|
|
|
else
|
|
|
|
fatal(usage2);
|
|
|
|
|
2007-05-31 07:31:51 -05:00
|
|
|
gpt_warning(disk_device);
|
2006-12-06 17:25:35 -06:00
|
|
|
get_boot(fdisk);
|
2006-12-06 17:25:32 -06:00
|
|
|
|
2006-12-06 17:25:43 -06:00
|
|
|
if (osf_label) {
|
2006-12-06 17:25:58 -06:00
|
|
|
/* OSF label, and no DOS label */
|
|
|
|
printf(_("Detected an OSF/1 disklabel on %s, entering "
|
|
|
|
"disklabel mode.\n"),
|
2006-12-06 17:25:43 -06:00
|
|
|
disk_device);
|
|
|
|
bselect();
|
2006-12-06 17:25:58 -06:00
|
|
|
osf_label = 0;
|
|
|
|
/* If we return we may want to make an empty DOS label? */
|
2006-12-06 17:25:43 -06:00
|
|
|
}
|
2006-12-06 17:25:58 -06:00
|
|
|
|
2006-12-06 17:25:32 -06:00
|
|
|
while (1) {
|
|
|
|
putchar('\n');
|
2006-12-06 17:25:43 -06:00
|
|
|
c = tolower(read_char(_("Command (m for help): ")));
|
|
|
|
switch (c) {
|
2006-12-06 17:25:35 -06:00
|
|
|
case 'a':
|
2006-12-06 17:25:43 -06:00
|
|
|
if (dos_label)
|
|
|
|
toggle_active(get_partition(1, partitions));
|
|
|
|
else if (sun_label)
|
2006-12-06 17:25:35 -06:00
|
|
|
toggle_sunflags(get_partition(1, partitions),
|
fdisk: many significant improvements and fixes to Sun label handling
1) Properly describe the exact layout and fields of the sun disk
label. Several fields were incorrectly mentioned and others
wrongly sized.
2) Properly set the version, sane, and num_partitions fields.
Because we weren't doing this, programs such as Solaris's format
and the Solaris kernel itself refused to recognize our disk labels
as valid.
3) Move SSWAP*() macros into fdisksunlabel.c as there is no reason
for them to be exposed to the rest of fdisk.
4) Kill the sun_predefined_drives array hack and assosciated code.
Instead size the disk and figure out the geometry properly just
like the SGI and MSDOS partition handling do, by means of the
HD_GETGEO ioctl() and disksize().
5) If the disk label read is found to not have the proper values
set in version, sane, or num_partitions, fix them, recompute the
label checksum, dirty the disk label, and let the user know what
we did and that the fixed values will be written out if they 'w'.
This gives users an easy way to fix up disk labels created by
disk labelling programs which had this bug.
6) Create a sun_sys_getid() function so that fdisk.c does not need
to reference the sun disk label details directly, just like the
SGI code does.
Signed-off-by: David S. Miller <davem@davemloft.net>
2007-06-29 17:50:21 -05:00
|
|
|
SUN_FLAG_UNMNT);
|
2006-12-06 17:25:43 -06:00
|
|
|
else if (sgi_label)
|
|
|
|
sgi_set_bootpartition(
|
|
|
|
get_partition(1, partitions));
|
2006-12-06 17:25:35 -06:00
|
|
|
else
|
2006-12-06 17:25:43 -06:00
|
|
|
unknown_command(c);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'b':
|
2006-12-06 17:25:37 -06:00
|
|
|
if (sgi_label) {
|
2006-12-06 17:25:39 -06:00
|
|
|
printf(_("\nThe current boot file is: %s\n"),
|
2006-12-06 17:25:37 -06:00
|
|
|
sgi_get_bootfile());
|
2006-12-06 17:25:39 -06:00
|
|
|
if (read_chars(_("Please enter the name of the "
|
|
|
|
"new boot file: ")) == '\n')
|
|
|
|
printf(_("Boot file unchanged\n"));
|
2006-12-06 17:25:37 -06:00
|
|
|
else
|
|
|
|
sgi_set_bootfile(line_ptr);
|
|
|
|
} else
|
|
|
|
bselect();
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'c':
|
2006-12-06 17:25:43 -06:00
|
|
|
if (dos_label)
|
|
|
|
toggle_dos_compatibility_flag();
|
|
|
|
else if (sun_label)
|
2006-12-06 17:25:35 -06:00
|
|
|
toggle_sunflags(get_partition(1, partitions),
|
fdisk: many significant improvements and fixes to Sun label handling
1) Properly describe the exact layout and fields of the sun disk
label. Several fields were incorrectly mentioned and others
wrongly sized.
2) Properly set the version, sane, and num_partitions fields.
Because we weren't doing this, programs such as Solaris's format
and the Solaris kernel itself refused to recognize our disk labels
as valid.
3) Move SSWAP*() macros into fdisksunlabel.c as there is no reason
for them to be exposed to the rest of fdisk.
4) Kill the sun_predefined_drives array hack and assosciated code.
Instead size the disk and figure out the geometry properly just
like the SGI and MSDOS partition handling do, by means of the
HD_GETGEO ioctl() and disksize().
5) If the disk label read is found to not have the proper values
set in version, sane, or num_partitions, fix them, recompute the
label checksum, dirty the disk label, and let the user know what
we did and that the fixed values will be written out if they 'w'.
This gives users an easy way to fix up disk labels created by
disk labelling programs which had this bug.
6) Create a sun_sys_getid() function so that fdisk.c does not need
to reference the sun disk label details directly, just like the
SGI code does.
Signed-off-by: David S. Miller <davem@davemloft.net>
2007-06-29 17:50:21 -05:00
|
|
|
SUN_FLAG_RONLY);
|
2006-12-06 17:25:43 -06:00
|
|
|
else if (sgi_label)
|
|
|
|
sgi_set_swappartition(
|
2006-12-06 17:25:37 -06:00
|
|
|
get_partition(1, partitions));
|
2006-12-06 17:25:43 -06:00
|
|
|
else
|
|
|
|
unknown_command(c);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
|
|
|
case 'd':
|
2006-12-06 17:26:12 -06:00
|
|
|
/* 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 */
|
|
|
|
if (!sgi_label) {
|
|
|
|
j = get_existing_partition(1, partitions);
|
|
|
|
} else {
|
|
|
|
j = get_partition(1, partitions);
|
|
|
|
}
|
2006-12-06 17:26:03 -06:00
|
|
|
if (j >= 0)
|
|
|
|
delete_partition(j);
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
2006-12-06 17:25:37 -06:00
|
|
|
case 'i':
|
|
|
|
if (sgi_label)
|
|
|
|
create_sgiinfo();
|
2006-12-06 17:25:35 -06:00
|
|
|
else
|
2006-12-06 17:25:43 -06:00
|
|
|
unknown_command(c);
|
2006-12-06 17:25:37 -06:00
|
|
|
case 'l':
|
|
|
|
list_types(get_sys_types());
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
2006-12-06 17:25:43 -06:00
|
|
|
case 'm':
|
|
|
|
menu();
|
|
|
|
break;
|
2006-12-06 17:25:35 -06:00
|
|
|
case 'n':
|
|
|
|
new_partition();
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
create_doslabel();
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
list_table(0);
|
|
|
|
break;
|
|
|
|
case 'q':
|
|
|
|
close(fd);
|
2006-12-06 17:25:39 -06:00
|
|
|
printf("\n");
|
2006-12-06 17:25:35 -06:00
|
|
|
exit(0);
|
|
|
|
case 's':
|
|
|
|
create_sunlabel();
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
change_sysid();
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
change_units();
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
verify();
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
write_table(); /* does not return */
|
|
|
|
break;
|
|
|
|
case 'x':
|
2006-12-06 17:25:58 -06:00
|
|
|
if (sgi_label) {
|
2006-12-06 17:25:37 -06:00
|
|
|
fprintf(stderr,
|
2006-12-06 17:25:39 -06:00
|
|
|
_("\n\tSorry, no experts menu for SGI "
|
|
|
|
"partition tables available.\n\n"));
|
2006-12-06 17:25:37 -06:00
|
|
|
} else
|
|
|
|
xselect();
|
2006-12-06 17:25:35 -06:00
|
|
|
break;
|
2006-12-06 17:25:43 -06:00
|
|
|
default:
|
|
|
|
unknown_command(c);
|
|
|
|
menu();
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|
|
|
|
}
|
2006-12-06 17:25:37 -06:00
|
|
|
return 0;
|
2006-12-06 17:25:32 -06:00
|
|
|
}
|