* Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
*/
+#ifndef _LARGEFILE64_SOURCE
+/* For lseek64 */
+#define _LARGEFILE64_SOURCE
+#endif
#include <assert.h> /* assert */
-#include "busybox.h"
+#include "libbb.h"
/* Looks like someone forgot to add this to config system */
#ifndef ENABLE_FEATURE_FDISK_BLKSIZE
# define USE_FEATURE_FDISK_BLKSIZE(a)
#endif
-#define SIZE(a) (sizeof(a)/sizeof((a)[0]))
-
-#define DEFAULT_SECTOR_SIZE 512
-#define MAX_SECTOR_SIZE 2048
-#define SECTOR_SIZE 512 /* still used in osf/sgi/sun code */
-#define MAXIMUM_PARTS 60
+#define DEFAULT_SECTOR_SIZE 512
+#define DEFAULT_SECTOR_SIZE_STR "512"
+#define MAX_SECTOR_SIZE 2048
+#define SECTOR_SIZE 512 /* still used in osf/sgi/sun code */
+#define MAXIMUM_PARTS 60
+
+#define ACTIVE_FLAG 0x80
+
+#define EXTENDED 0x05
+#define WIN98_EXTENDED 0x0f
+#define LINUX_PARTITION 0x81
+#define LINUX_SWAP 0x82
+#define LINUX_NATIVE 0x83
+#define LINUX_EXTENDED 0x85
+#define LINUX_LVM 0x8e
+#define LINUX_RAID 0xfd
+
+
+enum {
+ OPT_b = 1 << 0,
+ OPT_C = 1 << 1,
+ OPT_H = 1 << 2,
+ OPT_l = 1 << 3,
+ OPT_S = 1 << 4,
+ OPT_u = 1 << 5,
+ OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
+};
-#define ACTIVE_FLAG 0x80
-#define EXTENDED 0x05
-#define WIN98_EXTENDED 0x0f
-#define LINUX_PARTITION 0x81
-#define LINUX_SWAP 0x82
-#define LINUX_NATIVE 0x83
-#define LINUX_EXTENDED 0x85
-#define LINUX_LVM 0x8e
-#define LINUX_RAID 0xfd
+/* Used for sector numbers. Today's disk sizes make it necessary */
+typedef unsigned long long ullong;
struct hd_geometry {
unsigned char heads;
#define HDIO_GETGEO 0x0301 /* get device geometry */
-static const char msg_building_new_label[] =
+static const char msg_building_new_label[] ALIGN1 =
"Building a new %s. Changes will remain in memory only,\n"
"until you decide to write them. After that the previous content\n"
"won't be recoverable.\n\n";
-static const char msg_part_already_defined[] =
+static const char msg_part_already_defined[] ALIGN1 =
"Partition %d is already defined, delete it before re-adding\n";
-static unsigned sector_size = DEFAULT_SECTOR_SIZE;
-static unsigned user_set_sector_size;
-static unsigned sector_offset = 1;
-
-#if ENABLE_FEATURE_OSF_LABEL
-static int possibly_osf_label;
-#endif
-
-static unsigned heads, sectors, cylinders;
-static void update_units(void);
-
-
struct partition {
unsigned char boot_ind; /* 0x80 - active */
unsigned char head; /* starting head */
unsigned char sector; /* starting sector */
unsigned char cyl; /* starting cylinder */
- unsigned char sys_ind; /* What partition type */
+ unsigned char sys_ind; /* what partition type */
unsigned char end_head; /* end head */
unsigned char end_sector; /* end sector */
unsigned char end_cyl; /* end cylinder */
unsigned char start4[4]; /* starting sector counting from 0 */
unsigned char size4[4]; /* nr of sectors in partition */
-} ATTRIBUTE_PACKED;
+} PACKED;
-enum failure {
- ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
- unable_to_write
-};
+static const char unable_to_open[] ALIGN1 = "can't open %s";
+static const char unable_to_read[] ALIGN1 = "can't read from %s";
+static const char unable_to_seek[] ALIGN1 = "can't seek on %s";
enum label_type {
- label_dos, label_sun, label_sgi, label_aix, label_osf
+ LABEL_DOS, LABEL_SUN, LABEL_SGI, LABEL_AIX, LABEL_OSF
};
-#define LABEL_IS_DOS (label_dos == current_label_type)
+#define LABEL_IS_DOS (LABEL_DOS == current_label_type)
#if ENABLE_FEATURE_SUN_LABEL
-#define LABEL_IS_SUN (label_sun == current_label_type)
+#define LABEL_IS_SUN (LABEL_SUN == current_label_type)
#define STATIC_SUN static
#else
#define LABEL_IS_SUN 0
#endif
#if ENABLE_FEATURE_SGI_LABEL
-#define LABEL_IS_SGI (label_sgi == current_label_type)
+#define LABEL_IS_SGI (LABEL_SGI == current_label_type)
#define STATIC_SGI static
#else
#define LABEL_IS_SGI 0
#endif
#if ENABLE_FEATURE_AIX_LABEL
-#define LABEL_IS_AIX (label_aix == current_label_type)
+#define LABEL_IS_AIX (LABEL_AIX == current_label_type)
#define STATIC_AIX static
#else
#define LABEL_IS_AIX 0
#endif
#if ENABLE_FEATURE_OSF_LABEL
-#define LABEL_IS_OSF (label_osf == current_label_type)
+#define LABEL_IS_OSF (LABEL_OSF == current_label_type)
#define STATIC_OSF static
#else
#define LABEL_IS_OSF 0
#define STATIC_OSF extern
#endif
-enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
-
-static enum label_type current_label_type;
+enum action { OPEN_MAIN, TRY_ONLY, CREATE_EMPTY_DOS, CREATE_EMPTY_SUN };
-static const char *disk_device;
-static int fd; /* the disk */
-static int partitions = 4; /* maximum partition + 1 */
-static int display_in_cyl_units = 1;
-static unsigned units_per_sector = 1;
+static void update_units(void);
#if ENABLE_FEATURE_FDISK_WRITABLE
static void change_units(void);
static void reread_partition_table(int leave);
static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg);
#endif
static const char *partition_type(unsigned char type);
-static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN;
static void get_geometry(void);
+#if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE
static int get_boot(enum action what);
+#else
+static int get_boot(void);
+#endif
#define PLURAL 0
#define SINGULAR 1
struct pte {
struct partition *part_table; /* points into sectorbuffer */
struct partition *ext_pointer; /* points into sectorbuffer */
- off_t offset; /* disk sector number */
+ ullong offset; /* disk sector number */
char *sectorbuffer; /* disk sector contents */
#if ENABLE_FEATURE_FDISK_WRITABLE
char changed; /* boolean */
NULL
};
+enum {
+ dev_fd = 3 /* the disk */
+};
/* Globals */
-
struct globals {
char *line_ptr;
+
+ const char *disk_device;
+ int g_partitions; // = 4; /* maximum partition + 1 */
+ unsigned units_per_sector; // = 1;
+ unsigned sector_size; // = DEFAULT_SECTOR_SIZE;
+ unsigned user_set_sector_size;
+ unsigned sector_offset; // = 1;
+ unsigned g_heads, g_sectors, g_cylinders;
+ smallint /* enum label_type */ current_label_type;
+ smallint display_in_cyl_units; // = 1;
+#if ENABLE_FEATURE_OSF_LABEL
+ smallint possibly_osf_label;
+#endif
+
+ smallint listing; /* no aborts for fdisk -l */
+ smallint dos_compatible_flag; // = 1;
+#if ENABLE_FEATURE_FDISK_WRITABLE
+ //int dos_changed;
+ smallint nowarn; /* no warnings for fdisk -l/-s */
+#endif
+ int ext_index; /* the prime extended partition */
+ unsigned user_cylinders, user_heads, user_sectors;
+ unsigned pt_heads, pt_sectors;
+ unsigned kern_heads, kern_sectors;
+ ullong extended_offset; /* offset of link pointers */
+ ullong total_number_of_sectors;
+
+ jmp_buf listingbuf;
char line_buffer[80];
char partname_buffer[80];
- jmp_buf listingbuf;
/* Raw disk label. For DOS-type partition tables the MBR,
* with descriptions of the primary partitions. */
char MBRbuffer[MAX_SECTOR_SIZE];
/* Partition tables */
struct pte ptes[MAXIMUM_PARTS];
};
-/* bb_common_bufsiz1 is too small for this on 64 bit CPUs */
#define G (*ptr_to_globals)
-
-#define line_ptr (G.line_ptr)
-#define listingbuf (G.listingbuf)
-#define line_buffer (G.line_buffer)
+#define line_ptr (G.line_ptr )
+#define disk_device (G.disk_device )
+#define g_partitions (G.g_partitions )
+#define units_per_sector (G.units_per_sector )
+#define sector_size (G.sector_size )
+#define user_set_sector_size (G.user_set_sector_size)
+#define sector_offset (G.sector_offset )
+#define g_heads (G.g_heads )
+#define g_sectors (G.g_sectors )
+#define g_cylinders (G.g_cylinders )
+#define current_label_type (G.current_label_type )
+#define display_in_cyl_units (G.display_in_cyl_units)
+#define possibly_osf_label (G.possibly_osf_label )
+#define listing (G.listing )
+#define dos_compatible_flag (G.dos_compatible_flag )
+#define nowarn (G.nowarn )
+#define ext_index (G.ext_index )
+#define user_cylinders (G.user_cylinders )
+#define user_heads (G.user_heads )
+#define user_sectors (G.user_sectors )
+#define pt_heads (G.pt_heads )
+#define pt_sectors (G.pt_sectors )
+#define kern_heads (G.kern_heads )
+#define kern_sectors (G.kern_sectors )
+#define extended_offset (G.extended_offset )
+#define total_number_of_sectors (G.total_number_of_sectors)
+#define listingbuf (G.listingbuf )
+#define line_buffer (G.line_buffer )
#define partname_buffer (G.partname_buffer)
-#define MBRbuffer (G.MBRbuffer)
-#define ptes (G.ptes)
-
+#define MBRbuffer (G.MBRbuffer )
+#define ptes (G.ptes )
+#define INIT_G() do { \
+ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
+ sector_size = DEFAULT_SECTOR_SIZE; \
+ sector_offset = 1; \
+ g_partitions = 4; \
+ display_in_cyl_units = 1; \
+ units_per_sector = 1; \
+ dos_compatible_flag = 1; \
+} while (0)
+
+
+/* TODO: move to libbb? */
+static ullong bb_BLKGETSIZE_sectors(int fd)
+{
+ uint64_t v64;
+ unsigned long longsectors;
+
+ if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
+ /* Got bytes, convert to 512 byte sectors */
+ return (v64 >> 9);
+ }
+ /* Needs temp of type long */
+ if (ioctl(fd, BLKGETSIZE, &longsectors))
+ longsectors = 0;
+ return longsectors;
+}
-/* Code */
#define IS_EXTENDED(i) \
((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
#define set_hsc(h,s,c,sector) \
do { \
- s = sector % sectors + 1; \
- sector /= sectors; \
- h = sector % heads; \
- sector /= heads; \
- c = sector & 0xff; \
- s |= (sector >> 2) & 0xc0; \
+ s = sector % g_sectors + 1; \
+ sector /= g_sectors; \
+ h = sector % g_heads; \
+ sector /= g_heads; \
+ c = sector & 0xff; \
+ s |= (sector >> 2) & 0xc0; \
} while (0)
-/* read line; return 0 or first printable char */
+static void
+close_dev_fd(void)
+{
+ /* Not really closing, but making sure it is open, and to harmless place */
+ xmove_fd(xopen(bb_dev_null, O_RDONLY), dev_fd);
+}
+
+#if ENABLE_FEATURE_FDISK_WRITABLE
+/* Read line; return 0 or first printable char */
static int
read_line(const char *prompt)
{
sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
if (sz <= 0)
- exit(0); /* Ctrl-D or Ctrl-C */
+ exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
if (line_buffer[sz-1] == '\n')
line_buffer[--sz] = '\0';
line_ptr++;
return *line_ptr;
}
+#endif
/*
- * return partition name - uses static storage
+ * Return partition name - uses static storage
*/
static const char *
partname(const char *dev, int pno, int lth)
ptes[i].changed = 0;
}
-static ATTRIBUTE_ALWAYS_INLINE void
+static ALWAYS_INLINE void
set_changed(int i)
{
ptes[i].changed = 1;
}
#endif /* FEATURE_FDISK_WRITABLE */
-static ATTRIBUTE_ALWAYS_INLINE struct partition *
+static ALWAYS_INLINE struct partition *
get_part_table(int i)
{
return ptes[i].part_table;
}
#if ENABLE_FEATURE_FDISK_WRITABLE
-static ATTRIBUTE_ALWAYS_INLINE void
+static ALWAYS_INLINE void
write_part_table_flag(char *b)
{
b[510] = 0x55;
static char
read_nonempty(const char *mesg)
{
- while (!read_line(mesg)) /* repeat */;
+ while (!read_line(mesg))
+ continue;
return *line_ptr;
}
}
#endif /* FEATURE_FDISK_WRITABLE */
+static void fdisk_fatal(const char *why)
+{
+ if (listing) {
+ close_dev_fd();
+ longjmp(listingbuf, 1);
+ }
+ bb_error_msg_and_die(why, disk_device);
+}
+
+static void
+seek_sector(ullong secno)
+{
+ secno *= sector_size;
+#if ENABLE_FDISK_SUPPORT_LARGE_DISKS
+ if (lseek64(dev_fd, (off64_t)secno, SEEK_SET) == (off64_t) -1)
+ fdisk_fatal(unable_to_seek);
+#else
+ if (secno > MAXINT(off_t)
+ || lseek(dev_fd, (off_t)secno, SEEK_SET) == (off_t) -1
+ ) {
+ fdisk_fatal(unable_to_seek);
+ }
+#endif
+}
+
+#if ENABLE_FEATURE_FDISK_WRITABLE
+static void
+write_sector(ullong secno, const void *buf)
+{
+ seek_sector(secno);
+ xwrite(dev_fd, buf, sector_size);
+}
+#endif
+
+
#include "fdisk_aix.c"
typedef struct {
STATIC_SUN void sun_write_table(void);
#include "fdisk_sun.c"
+
#if ENABLE_FEATURE_FDISK_WRITABLE
/* start_sect and nr_sects are stored little endian on all machines */
/* moreover, they are not aligned correctly */
return read4_little_endian(p->size4);
}
-/* normally O_RDWR, -l option gives O_RDONLY */
-static int type_open = O_RDWR;
-
-
-static int ext_index; /* the prime extended partition */
-static int listing; /* no aborts for fdisk -l */
-static int dos_compatible_flag = ~0;
-#if ENABLE_FEATURE_FDISK_WRITABLE
-static int dos_changed;
-static int nowarn; /* no warnings for fdisk -l/-s */
-#endif
-
-
-
-static unsigned user_cylinders, user_heads, user_sectors;
-static unsigned pt_heads, pt_sectors;
-static unsigned kern_heads, kern_sectors;
-
-static off_t extended_offset; /* offset of link pointers */
-
-static unsigned long long total_number_of_sectors;
-
-
-static void fdisk_fatal(enum failure why)
-{
- const char *message;
-
- if (listing) {
- close(fd);
- longjmp(listingbuf, 1);
- }
-
- switch (why) {
- case unable_to_open:
- message = "cannot open %s";
- break;
- case unable_to_read:
- message = "cannot read from %s";
- break;
- case unable_to_seek:
- message = "cannot seek on %s";
- break;
- case unable_to_write:
- message = "cannot write to %s";
- break;
- case ioctl_error:
- message = "BLKGETSIZE ioctl failed on %s";
- break;
- default:
- message = "fatal error";
- }
-
- bb_error_msg_and_die(message, disk_device);
-}
-
-static void
-seek_sector(off_t secno)
-{
- off_t offset = secno * sector_size;
- if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
- fdisk_fatal(unable_to_seek);
-}
-
-#if ENABLE_FEATURE_FDISK_WRITABLE
-static void
-write_sector(off_t secno, char *buf)
-{
- seek_sector(secno);
- if (write(fd, buf, sector_size) != sector_size)
- fdisk_fatal(unable_to_write);
-}
-#endif
-
/* Allocate a buffer and read a partition table sector */
static void
-read_pte(struct pte *pe, off_t offset)
+read_pte(struct pte *pe, ullong offset)
{
pe->offset = offset;
- pe->sectorbuffer = xmalloc(sector_size);
+ pe->sectorbuffer = xzalloc(sector_size);
seek_sector(offset);
- if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
+ /* xread would make us abort - bad for fdisk -l */
+ if (full_read(dev_fd, pe->sectorbuffer, sector_size) != sector_size)
fdisk_fatal(unable_to_read);
#if ENABLE_FEATURE_FDISK_WRITABLE
pe->changed = 0;
* We might also do the opposite and warn in all cases except
* for "is probably nondos partition".
*/
+#ifdef UNUSED
static int
is_dos_partition(int t)
{
t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
t == 0xc1 || t == 0xc4 || t == 0xc6);
}
+#endif
static void
menu(void)
unsigned done, next, size;
int i;
- for (size = 0; sys[size]; size++) /* */;
+ for (size = 0; sys[size]; size++)
+ continue;
done = 0;
for (i = COLS-1; i >= 0; i--) {
next = ++done;
}
} while (done < last[0]);
- putchar('\n');
+ bb_putchar('\n');
}
#endif /* FEATURE_FDISK_WRITABLE */
#if ENABLE_FEATURE_FDISK_WRITABLE
static void
-set_partition(int i, int doext, off_t start, off_t stop, int sysid)
+set_partition(int i, int doext, ullong start, ullong stop, int sysid)
{
struct partition *p;
- off_t offset;
+ ullong offset;
if (doext) {
p = ptes[i].ext_pointer;
p->sys_ind = sysid;
set_start_sect(p, start - offset);
set_nr_sects(p, stop - start + 1);
- if (dos_compatible_flag && (start/(sectors*heads) > 1023))
- start = heads*sectors*1024 - 1;
+ if (dos_compatible_flag && (start / (g_sectors * g_heads) > 1023))
+ start = g_heads * g_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;
+ if (dos_compatible_flag && (stop / (g_sectors * g_heads) > 1023))
+ stop = g_heads * g_sectors * 1024 - 1;
set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
ptes[i].changed = 1;
}
static int
warn_geometry(void)
{
- if (heads && sectors && cylinders)
+ if (g_heads && g_sectors && g_cylinders)
return 0;
printf("Unknown value(s) for:");
- if (!heads)
+ if (!g_heads)
printf(" heads");
- if (!sectors)
+ if (!g_sectors)
printf(" sectors");
- if (!cylinders)
+ if (!g_cylinders)
printf(" cylinders");
printf(
#if ENABLE_FEATURE_FDISK_WRITABLE
static void
update_units(void)
{
- int cyl_units = heads * sectors;
+ int cyl_units = g_heads * g_sectors;
if (display_in_cyl_units && cyl_units)
units_per_sector = cyl_units;
static void
warn_cylinders(void)
{
- if (LABEL_IS_DOS && cylinders > 1024 && !nowarn)
+ if (LABEL_IS_DOS && g_cylinders > 1024 && !nowarn)
printf("\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"
"1) software that runs at boot time (e.g., old versions of LILO)\n"
"2) booting and partitioning software from other OSs\n"
" (e.g., DOS FDISK, OS/2 FDISK)\n",
- cylinders);
+ g_cylinders);
}
#endif
}
while (IS_EXTENDED(p->sys_ind)) {
- struct pte *pe = &ptes[partitions];
+ struct pte *pe = &ptes[g_partitions];
- if (partitions >= MAXIMUM_PARTS) {
+ if (g_partitions >= MAXIMUM_PARTS) {
/* This is not a Linux restriction, but
this program uses arrays of size MAXIMUM_PARTS.
Do not try to 'improve' this test. */
- struct pte *pre = &ptes[partitions-1];
+ struct pte *pre = &ptes[g_partitions - 1];
#if ENABLE_FEATURE_FDISK_WRITABLE
printf("Warning: deleting partitions after %d\n",
- partitions);
+ g_partitions);
pre->changed = 1;
#endif
clear_partition(pre->ext_pointer);
if (pe->ext_pointer)
printf("Warning: extra link "
"pointer in partition table"
- " %d\n", partitions + 1);
+ " %d\n", g_partitions + 1);
else
pe->ext_pointer = p;
} else if (p->sys_ind) {
if (pe->part_table)
printf("Warning: ignoring extra "
"data in partition table"
- " %d\n", partitions + 1);
+ " %d\n", g_partitions + 1);
else
pe->part_table = p;
}
}
p = pe->ext_pointer;
- partitions++;
+ g_partitions++;
}
#if ENABLE_FEATURE_FDISK_WRITABLE
/* remove empty links */
remove:
- for (i = 4; i < partitions; i++) {
+ for (i = 4; i < g_partitions; i++) {
struct pte *pe = &ptes[i];
if (!get_nr_sects(pe->part_table)
- && (partitions > 5 || ptes[4].part_table->sys_ind)
+ && (g_partitions > 5 || ptes[4].part_table->sys_ind)
) {
printf("Omitting empty partition (%d)\n", i+1);
delete_partition(i);
printf(msg_building_new_label, "DOS disklabel");
- current_label_type = label_dos;
+ current_label_type = LABEL_DOS;
#if ENABLE_FEATURE_OSF_LABEL
possibly_osf_label = 0;
#endif
- partitions = 4;
+ g_partitions = 4;
for (i = 510-64; i < 510; i++)
MBRbuffer[i] = 0;
extended_offset = 0;
set_all_unchanged();
set_changed(0);
- get_boot(create_empty_dos);
+ get_boot(CREATE_EMPTY_DOS);
}
#endif /* FEATURE_FDISK_WRITABLE */
{
if (!user_set_sector_size) {
int arg;
- if (ioctl(fd, BLKSSZGET, &arg) == 0)
+ if (ioctl(dev_fd, BLKSSZGET, &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);
+ printf("Note: sector size is %d "
+ "(not " DEFAULT_SECTOR_SIZE_STR ")\n",
+ sector_size);
}
}
{
struct hd_geometry geometry;
- if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
+ if (!ioctl(dev_fd, HDIO_GETGEO, &geometry)) {
kern_heads = geometry.heads;
kern_sectors = geometry.sectors;
/* never use geometry.cylinders - it is truncated */
get_geometry(void)
{
int sec_fac;
- unsigned long long bytes; /* really u64 */
get_sectorsize();
sec_fac = sector_size / 512;
#if ENABLE_FEATURE_SUN_LABEL
guess_device_type();
#endif
- heads = cylinders = sectors = 0;
+ g_heads = g_cylinders = g_sectors = 0;
kern_heads = kern_sectors = 0;
pt_heads = pt_sectors = 0;
get_kernel_geometry();
get_partition_table_geometry();
- heads = user_heads ? user_heads :
+ g_heads = user_heads ? user_heads :
pt_heads ? pt_heads :
kern_heads ? kern_heads : 255;
- sectors = user_sectors ? user_sectors :
+ g_sectors = user_sectors ? user_sectors :
pt_sectors ? pt_sectors :
kern_sectors ? kern_sectors : 63;
- if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
- /* got bytes */
- } else {
- unsigned long longsectors;
-
- if (ioctl(fd, BLKGETSIZE, &longsectors))
- longsectors = 0;
- bytes = ((unsigned long long) longsectors) << 9;
- }
-
- total_number_of_sectors = (bytes >> 9);
+ total_number_of_sectors = bb_BLKGETSIZE_sectors(dev_fd);
sector_offset = 1;
if (dos_compatible_flag)
- sector_offset = sectors;
+ sector_offset = g_sectors;
- cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
- if (!cylinders)
- cylinders = user_cylinders;
+ g_cylinders = total_number_of_sectors / (g_heads * g_sectors * sec_fac);
+ if (!g_cylinders)
+ g_cylinders = user_cylinders;
}
/*
- * Read MBR. Returns:
+ * Opens disk_device and optionally reads MBR.
+ * FIXME: document what each 'what' value will do!
+ * Returns:
* -1: no 0xaa55 flag present (possibly entire disk BSD)
* 0: found or created label
* 1: I/O error
*/
-static int
-get_boot(enum action what)
+#if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE
+static int get_boot(enum action what)
+#else
+static int get_boot(void)
+#define get_boot(what) get_boot()
+#endif
{
- int i;
-
- partitions = 4;
+ int i, fd;
+ g_partitions = 4;
for (i = 0; i < 4; i++) {
struct pte *pe = &ptes[i];
-
pe->part_table = pt_offset(MBRbuffer, i);
pe->ext_pointer = NULL;
pe->offset = 0;
pe->sectorbuffer = MBRbuffer;
#if ENABLE_FEATURE_FDISK_WRITABLE
- pe->changed = (what == create_empty_dos);
+ pe->changed = (what == CREATE_EMPTY_DOS);
#endif
}
-#if ENABLE_FEATURE_SUN_LABEL
- if (what == create_empty_sun && check_sun_label())
- return 0;
-#endif
-
- memset(MBRbuffer, 0, 512);
-
#if ENABLE_FEATURE_FDISK_WRITABLE
- if (what == create_empty_dos)
- goto got_dos_table; /* skip reading disk */
+// ALERT! highly idiotic design!
+// We end up here when we call get_boot() recursively
+// via get_boot() [table is bad] -> create_doslabel() -> get_boot(CREATE_EMPTY_DOS).
+// or get_boot() [table is bad] -> create_sunlabel() -> get_boot(CREATE_EMPTY_SUN).
+// (just factor out re-init of ptes[0,1,2,3] in a separate fn instead?)
+// So skip opening device _again_...
+ if (what == CREATE_EMPTY_DOS USE_FEATURE_SUN_LABEL(|| what == CREATE_EMPTY_SUN))
+ goto created_table;
+
+ fd = open(disk_device, (option_mask32 & OPT_l) ? O_RDONLY : O_RDWR);
- fd = open(disk_device, type_open);
if (fd < 0) {
fd = open(disk_device, O_RDONLY);
if (fd < 0) {
- if (what == try_only)
+ if (what == TRY_ONLY)
return 1;
fdisk_fatal(unable_to_open);
- } else
- printf("You will not be able to write "
- "the partition table\n");
+ }
+ printf("'%s' is opened for read only\n", disk_device);
}
-
- if (512 != read(fd, MBRbuffer, 512)) {
- if (what == try_only)
+ xmove_fd(fd, dev_fd);
+ if (512 != full_read(dev_fd, MBRbuffer, 512)) {
+ if (what == TRY_ONLY) {
+ close_dev_fd();
return 1;
+ }
fdisk_fatal(unable_to_read);
}
#else
fd = open(disk_device, O_RDONLY);
if (fd < 0)
return 1;
- if (512 != read(fd, MBRbuffer, 512))
+ if (512 != full_read(fd, MBRbuffer, 512)) {
+ close(fd);
return 1;
+ }
+ xmove_fd(fd, dev_fd);
#endif
get_geometry();
-
update_units();
#if ENABLE_FEATURE_SUN_LABEL
if (check_sun_label())
return 0;
#endif
-
#if ENABLE_FEATURE_SGI_LABEL
if (check_sgi_label())
return 0;
#endif
-
#if ENABLE_FEATURE_AIX_LABEL
if (check_aix_label())
return 0;
#endif
-
#if ENABLE_FEATURE_OSF_LABEL
if (check_osf_label()) {
possibly_osf_label = 1;
if (!valid_part_table_flag(MBRbuffer)) {
- current_label_type = label_osf;
+ current_label_type = LABEL_OSF;
return 0;
}
printf("This disk has both DOS and BSD magic.\n"
}
#endif
-#if ENABLE_FEATURE_FDISK_WRITABLE
- got_dos_table:
-#endif
-
- if (!valid_part_table_flag(MBRbuffer)) {
#if !ENABLE_FEATURE_FDISK_WRITABLE
+ if (!valid_part_table_flag(MBRbuffer))
return -1;
#else
- switch (what) {
- case fdisk:
+ if (!valid_part_table_flag(MBRbuffer)) {
+ if (what == OPEN_MAIN) {
printf("Device contains neither a valid DOS "
"partition table, nor Sun, SGI or OSF "
"disklabel\n");
#ifdef __sparc__
-#if ENABLE_FEATURE_SUN_LABEL
- create_sunlabel();
-#endif
+ USE_FEATURE_SUN_LABEL(create_sunlabel();)
#else
create_doslabel();
#endif
return 0;
- case try_only:
- return -1;
- case create_empty_dos:
-#if ENABLE_FEATURE_SUN_LABEL
- case create_empty_sun:
-#endif
- break;
- default:
- bb_error_msg_and_die("internal error");
}
-#endif /* FEATURE_FDISK_WRITABLE */
+ /* TRY_ONLY: */
+ return -1;
}
+ created_table:
+#endif /* FEATURE_FDISK_WRITABLE */
-#if ENABLE_FEATURE_FDISK_WRITABLE
- warn_cylinders();
-#endif
+
+ USE_FEATURE_FDISK_WRITABLE(warn_cylinders();)
warn_geometry();
for (i = 0; i < 4; i++) {
- struct pte *pe = &ptes[i];
-
- if (IS_EXTENDED(pe->part_table->sys_ind)) {
- if (partitions != 4)
+ if (IS_EXTENDED(ptes[i].part_table->sys_ind)) {
+ if (g_partitions != 4)
printf("Ignoring extra extended "
"partition %d\n", i + 1);
else
}
}
- for (i = 3; i < partitions; i++) {
+ for (i = 3; i < g_partitions; i++) {
struct pte *pe = &ptes[i];
-
if (!valid_part_table_flag(pe->sectorbuffer)) {
printf("Warning: invalid flag 0x%02x,0x%02x of partition "
"table %d will be corrected by w(rite)\n",
pe->sectorbuffer[510],
pe->sectorbuffer[511],
i + 1);
-#if ENABLE_FEATURE_FDISK_WRITABLE
- pe->changed = 1;
-#endif
+ USE_FEATURE_FDISK_WRITABLE(pe->changed = 1;)
}
}
case 'c':
case 'C':
if (!display_in_cyl_units)
- i *= heads * sectors;
+ i *= g_heads * g_sectors;
break;
case 'K':
absolute = 1024;
break;
}
if (absolute) {
- unsigned long long bytes;
+ ullong bytes;
unsigned long unit;
- bytes = (unsigned long long) i * absolute;
+ bytes = (ullong) i * absolute;
unit = sector_size * units_per_sector;
bytes += unit/2; /* round */
bytes /= unit;
static void
toggle_dos_compatibility_flag(void)
{
- dos_compatible_flag = ~dos_compatible_flag;
+ dos_compatible_flag = 1 - dos_compatible_flag;
if (dos_compatible_flag) {
- sector_offset = sectors;
+ sector_offset = g_sectors;
printf("DOS Compatibility flag is set\n");
} else {
sector_offset = 1;
if (i < 4) {
if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
- partitions = 4;
+ g_partitions = 4;
ptes[ext_index].ext_pointer = NULL;
extended_offset = 0;
}
if (!q->sys_ind && i > 4) {
/* the last one in the chain - just delete */
- --partitions;
+ --g_partitions;
--i;
clear_partition(ptes[i].ext_pointer);
ptes[i].changed = 1;
set_start_sect(p, get_start_sect(q));
set_nr_sects(p, get_nr_sects(q));
ptes[i-1].changed = 1;
- } else if (partitions > 5) { /* 5 will be moved to 4 */
+ } else if (g_partitions > 5) { /* 5 will be moved to 4 */
/* the first logical in a longer chain */
pe = &ptes[5];
pe->changed = 1;
}
- if (partitions > 5) {
- partitions--;
- while (i < partitions) {
+ if (g_partitions > 5) {
+ g_partitions--;
+ while (i < g_partitions) {
ptes[i] = ptes[i+1];
i++;
}
let the user select a partition, since get_existing_partition()
only works for Linux like partition tables. */
if (!LABEL_IS_SGI) {
- i = get_existing_partition(0, partitions);
+ i = get_existing_partition(0, g_partitions);
} else {
- i = get_partition(0, partitions);
+ i = get_partition(0, g_partitions);
}
if (i == -1)
return;
"to %x (%s)\n", i + 1, sys,
partition_type(sys));
ptes[i].changed = 1;
- if (is_dos_partition(origsys) ||
- is_dos_partition(sys))
- dos_changed = 1;
+ //if (is_dos_partition(origsys) || is_dos_partition(sys))
+ // dos_changed = 1;
break;
}
}
static void
linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
{
- int spc = heads * sectors;
+ int spc = g_heads * g_sectors;
*c = ls / spc;
ls = ls % spc;
- *h = ls / sectors;
- *s = ls % sectors + 1; /* sectors count from 1 */
+ *h = ls / g_sectors;
+ *s = ls % g_sectors + 1; /* sectors count from 1 */
}
static void
unsigned lbc, lbh, lbs; /* logical beginning c, h, s */
unsigned lec, leh, les; /* logical ending c, h, s */
- if (!heads || !sectors || (partition >= 4))
+ if (!g_heads || !g_sectors || (partition >= 4))
return; /* do not check extended partitions */
/* physical beginning c, h, s */
linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
/* Same physical / logical beginning? */
- if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
+ if (g_cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
printf("Partition %d has different physical/logical "
"beginnings (non-Linux?):\n", partition + 1);
printf(" phys=(%d, %d, %d) ", pbc, pbh, pbs);
- printf("logical=(%d, %d, %d)\n",lbc, lbh, lbs);
+ printf("logical=(%d, %d, %d)\n", lbc, lbh, lbs);
}
/* Same physical / logical ending? */
- if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
+ if (g_cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
printf("Partition %d has different physical/logical "
"endings:\n", partition + 1);
printf(" phys=(%d, %d, %d) ", pec, peh, pes);
}
/* Ending on cylinder boundary? */
- if (peh != (heads - 1) || pes != sectors) {
+ if (peh != (g_heads - 1) || pes != g_sectors) {
printf("Partition %i does not end on cylinder boundary\n",
partition + 1);
}
printf("\nDisk %s: %ld.%ld GB, %lld bytes\n",
disk_device, megabytes/1000, (megabytes/100)%10, bytes);
printf("%d heads, %d sectors/track, %d cylinders",
- heads, sectors, cylinders);
+ g_heads, g_sectors, g_cylinders);
if (units_per_sector == 1)
printf(", total %llu sectors",
total_number_of_sectors / (sector_size/512));
{
const struct pte *pe;
const struct partition *p;
- off_t last_p_start_pos = 0, p_start_pos;
+ ullong last_p_start_pos = 0, p_start_pos;
int i, last_i = 0;
- for (i = 0 ; i < partitions; i++) {
+ for (i = 0; i < g_partitions; i++) {
if (i == 4) {
last_i = 4;
last_p_start_pos = 0;
}
pe = &ptes[i];
- if ((p = pe->part_table)->sys_ind) {
+ p = pe->part_table;
+ if (p->sys_ind) {
p_start_pos = get_partition_start(pe);
if (last_p_start_pos > p_start_pos) {
/* Stage 1: sort sectors but leave sector of part 4 */
/* (Its sector is the global extended_offset.) */
stage1:
- for (j = 5; j < partitions-1; j++) {
+ for (j = 5; j < g_partitions - 1; j++) {
oj = ptes[j].offset;
ojj = ptes[j+1].offset;
if (oj > ojj) {
/* Stage 2: sort starting sectors */
stage2:
- for (j = 4; j < partitions-1; j++) {
+ for (j = 4; j < g_partitions - 1; j++) {
pj = ptes[j].part_table;
pjj = ptes[j+1].part_table;
sj = get_start_sect(pj);
}
/* Probably something was changed */
- for (j = 4; j < partitions; j++)
+ for (j = 4; j < g_partitions; j++)
ptes[j].changed = 1;
}
printf("%*s Boot Start End Blocks Id System\n",
w+1, "Device");
- for (i = 0; i < partitions; i++) {
+ for (i = 0; i < g_partitions; i++) {
const struct pte *pe = &ptes[i];
- off_t psects;
- off_t pblocks;
+ ullong psects;
+ ullong pblocks;
unsigned podd;
p = pe->part_table;
partname(disk_device, i+1, w+2),
!p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
? '*' : '?',
- (unsigned long long) cround(get_partition_start(pe)), /* start */
- (unsigned long long) cround(get_partition_start(pe) + psects /* end */
+ (ullong) cround(get_partition_start(pe)), /* start */
+ (ullong) cround(get_partition_start(pe) + psects /* end */
- (psects ? 1 : 0)),
- (unsigned long long) pblocks, podd ? '+' : ' ', /* odd flag on end */
+ (ullong) pblocks, podd ? '+' : ' ', /* odd flag on end */
p->sys_ind, /* type id */
partition_type(p->sys_ind)); /* type name */
int i;
printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n",
- disk_device, heads, sectors, cylinders);
+ disk_device, g_heads, g_sectors, g_cylinders);
printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n");
- for (i = 0 ; i < partitions; i++) {
+ for (i = 0; i < g_partitions; i++) {
pe = &ptes[i];
p = (extend ? pe->ext_pointer : pe->part_table);
if (p != NULL) {
#if ENABLE_FEATURE_FDISK_WRITABLE
static void
-fill_bounds(off_t *first, off_t *last)
+fill_bounds(ullong *first, ullong *last)
{
int i;
const struct pte *pe = &ptes[0];
const struct partition *p;
- for (i = 0; i < partitions; pe++,i++) {
+ for (i = 0; i < g_partitions; pe++,i++) {
p = pe->part_table;
if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
first[i] = 0xffffffff;
}
static void
-check(int n, unsigned h, unsigned s, unsigned c, off_t start)
+check(int n, unsigned h, unsigned s, unsigned c, ullong start)
{
- off_t total, real_s, real_c;
+ ullong total, real_s, real_c;
real_s = sector(s) - 1;
real_c = cylinder(s, c);
- total = (real_c * sectors + real_s) * heads + h;
+ total = (real_c * g_sectors + real_s) * g_heads + h;
if (!total)
printf("Partition %d contains sector 0\n", n);
- if (h >= heads)
+ if (h >= g_heads)
printf("Partition %d: head %d greater than maximum %d\n",
- n, h + 1, heads);
- if (real_s >= sectors)
+ n, h + 1, g_heads);
+ if (real_s >= g_sectors)
printf("Partition %d: sector %d greater than "
- "maximum %d\n", n, s, sectors);
- if (real_c >= cylinders)
- printf("Partition %d: cylinder %"OFF_FMT"u greater than "
- "maximum %d\n", n, real_c + 1, cylinders);
- if (cylinders <= 1024 && start != total)
- printf("Partition %d: previous sectors %"OFF_FMT"u disagrees with "
- "total %"OFF_FMT"u\n", n, start, total);
+ "maximum %d\n", n, s, g_sectors);
+ if (real_c >= g_cylinders)
+ printf("Partition %d: cylinder %llu greater than "
+ "maximum %d\n", n, real_c + 1, g_cylinders);
+ if (g_cylinders <= 1024 && start != total)
+ printf("Partition %d: previous sectors %llu disagrees with "
+ "total %llu\n", n, start, total);
}
static void
{
int i, j;
unsigned total = 1;
- off_t first[partitions], last[partitions];
+ ullong first[g_partitions], last[g_partitions];
struct partition *p;
if (warn_geometry())
}
fill_bounds(first, last);
- for (i = 0; i < partitions; i++) {
+ for (i = 0; i < g_partitions; i++) {
struct pte *pe = &ptes[i];
p = pe->part_table;
if (extended_offset) {
struct pte *pex = &ptes[ext_index];
- off_t e_last = get_start_sect(pex->part_table) +
+ ullong e_last = get_start_sect(pex->part_table) +
get_nr_sects(pex->part_table) - 1;
- for (i = 4; i < partitions; i++) {
+ for (i = 4; i < g_partitions; i++) {
total++;
p = ptes[i].part_table;
if (!p->sys_ind) {
- if (i != 4 || i + 1 < partitions)
+ if (i != 4 || i + 1 < g_partitions)
printf("Warning: partition %d "
"is empty\n", i + 1);
} else if (first[i] < extended_offset || last[i] > e_last) {
}
}
- if (total > heads * sectors * cylinders)
+ if (total > g_heads * g_sectors * g_cylinders)
printf("Total allocated sectors %d greater than the maximum "
- "%d\n", total, heads * sectors * cylinders);
+ "%d\n", total, g_heads * g_sectors * g_cylinders);
else {
- total = heads * sectors * cylinders - total;
+ total = g_heads * g_sectors * g_cylinders - total;
if (total != 0)
printf("%d unallocated sectors\n", total);
}
int i, num_read = 0;
struct partition *p = ptes[n].part_table;
struct partition *q = ptes[ext_index].part_table;
- long long llimit;
- off_t start, stop = 0, limit, temp,
- first[partitions], last[partitions];
+ ullong limit, temp;
+ ullong start, stop = 0;
+ ullong first[g_partitions], last[g_partitions];
if (p && p->sys_ind) {
printf(msg_part_already_defined, n + 1);
if (n < 4) {
start = sector_offset;
if (display_in_cyl_units || !total_number_of_sectors)
- llimit = heads * sectors * cylinders - 1;
+ limit = (ullong) g_heads * g_sectors * g_cylinders - 1;
else
- llimit = total_number_of_sectors - 1;
- limit = llimit;
- if (limit != llimit)
- limit = 0x7fffffff;
+ limit = total_number_of_sectors - 1;
if (extended_offset) {
first[ext_index] = extended_offset;
last[ext_index] = get_start_sect(q) +
limit = get_start_sect(q) + get_nr_sects(q) - 1;
}
if (display_in_cyl_units)
- for (i = 0; i < partitions; i++)
+ for (i = 0; i < g_partitions; i++)
first[i] = (cround(first[i]) - 1) * units_per_sector;
snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
do {
temp = start;
- for (i = 0; i < partitions; i++) {
+ for (i = 0; i < g_partitions; i++) {
int lastplusoff;
if (start == ptes[i].offset)
if (start > limit)
break;
if (start >= temp+units_per_sector && num_read) {
- printf("Sector %"OFF_FMT"d is already allocated\n", temp);
+ printf("Sector %lld is already allocated\n", temp);
temp = start;
num_read = 0;
}
if (!num_read && start == temp) {
- off_t saved_start;
+ ullong saved_start;
saved_start = start;
start = read_int(cround(saved_start), cround(saved_start), cround(limit),
}
}
- for (i = 0; i < partitions; i++) {
+ for (i = 0; i < g_partitions; i++) {
struct pte *pe = &ptes[i];
if (start < pe->offset && limit >= pe->offset)
if (start > limit) {
printf("No free sectors available\n");
if (n > 4)
- partitions--;
+ g_partitions--;
return;
}
if (cround(start) == cround(limit)) {
pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
pe4->ext_pointer = pe4->part_table + 1;
pe4->changed = 1;
- partitions = 5;
+ g_partitions = 5;
}
}
static void
add_logical(void)
{
- if (partitions > 5 || ptes[4].part_table->sys_ind) {
- struct pte *pe = &ptes[partitions];
+ if (g_partitions > 5 || ptes[4].part_table->sys_ind) {
+ struct pte *pe = &ptes[g_partitions];
pe->sectorbuffer = xzalloc(sector_size);
pe->part_table = pt_offset(pe->sectorbuffer, 0);
pe->ext_pointer = pe->part_table + 1;
pe->offset = 0;
pe->changed = 1;
- partitions++;
+ g_partitions++;
}
- add_partition(partitions - 1, LINUX_NATIVE);
+ add_partition(g_partitions - 1, LINUX_NATIVE);
}
static void
return;
if (LABEL_IS_SUN) {
- add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
+ add_sun_partition(get_partition(0, g_partitions), LINUX_NATIVE);
return;
}
if (LABEL_IS_SGI) {
- sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
+ sgi_add_partition(get_partition(0, g_partitions), LINUX_NATIVE);
return;
}
if (LABEL_IS_AIX) {
for (i = 0; i < 4; i++)
free_primary += !ptes[i].part_table->sys_ind;
- if (!free_primary && partitions >= MAXIMUM_PARTS) {
+ if (!free_primary && g_partitions >= MAXIMUM_PARTS) {
printf("The maximum number of partitions has been created\n");
return;
}
for (i = 0; i < 3; i++)
if (ptes[i].changed)
ptes[3].changed = 1;
- for (i = 3; i < partitions; i++) {
+ for (i = 3; i < g_partitions; i++) {
struct pte *pe = &ptes[i];
if (pe->changed) {
printf("Calling ioctl() to re-read partition table\n");
sync();
/* sleep(2); Huh? */
- i = ioctl(fd, BLKRRPART);
-#if 0
- else {
- /* some kernel versions (1.2.x) seem to have trouble
- rereading the partition table, but if asked to do it
- twice, the second time works. - biro@yggdrasil.com */
- sync();
- sleep(2);
- i = ioctl(fd, BLKRRPART);
- }
-#endif
-
- if (i) {
- bb_perror_msg("WARNING: rereading partition table "
+ i = ioctl_or_perror(dev_fd, BLKRRPART, NULL,
+ "WARNING: rereading partition table "
"failed, kernel still uses old table");
- }
-
#if 0
if (dos_changed)
printf(
if (leave) {
if (ENABLE_FEATURE_CLEAN_UP)
- close(fd);
+ close_dev_fd();
exit(i != 0);
}
}
printf("0x%03X:", i);
printf(" %02X", (unsigned char) pbuffer[i]);
if (l == MAX_PER_LINE - 1) {
- puts("");
+ bb_putchar('\n');
l = -1;
}
}
if (l > 0)
- puts("");
- puts("");
+ bb_putchar('\n');
+ bb_putchar('\n');
}
static void
if (LABEL_IS_SGI || LABEL_IS_SUN)
print_buffer(MBRbuffer);
else {
- for (i = 3; i < partitions; i++)
+ for (i = 3; i < g_partitions; i++)
print_buffer(ptes[i].sectorbuffer);
}
}
{
struct pte *pe = &ptes[i];
struct partition *p = pe->part_table;
- off_t new, first;
+ ullong new, first;
if (warn_geometry())
return;
char c;
while (1) {
- putchar('\n');
+ bb_putchar('\n');
c = tolower(read_nonempty("Expert command (m for help): "));
switch (c) {
case 'a':
break;
case 'b':
if (LABEL_IS_DOS)
- move_begin(get_partition(0, partitions));
+ move_begin(get_partition(0, g_partitions));
break;
case 'c':
- user_cylinders = cylinders =
- read_int(1, cylinders, 1048576, 0,
+ user_cylinders = g_cylinders =
+ read_int(1, g_cylinders, 1048576, 0,
"Number of cylinders");
if (LABEL_IS_SUN)
- sun_set_ncyl(cylinders);
+ sun_set_ncyl(g_cylinders);
if (LABEL_IS_DOS)
warn_cylinders();
break;
#endif
break;
case 'h':
- user_heads = heads = read_int(1, heads, 256, 0,
+ user_heads = g_heads = read_int(1, g_heads, 256, 0,
"Number of heads");
update_units();
break;
x_list_table(0);
break;
case 'q':
- close(fd);
- puts("");
- exit(0);
+ if (ENABLE_FEATURE_CLEAN_UP)
+ close_dev_fd();
+ bb_putchar('\n');
+ exit(EXIT_SUCCESS);
case 'r':
return;
case 's':
- user_sectors = sectors = read_int(1, sectors, 63, 0,
+ user_sectors = g_sectors = read_int(1, g_sectors, 63, 0,
"Number of sectors");
if (dos_compatible_flag) {
- sector_offset = sectors;
+ sector_offset = g_sectors;
printf("Warning: setting sector offset for DOS "
"compatiblity\n");
}
return 0;
snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
- procf = fopen(buf, "r");
+ procf = fopen_for_read(buf);
if (procf != NULL && fgets(buf, sizeof(buf), procf))
is_ide = (!strncmp(buf, "cdrom", 5) ||
!strncmp(buf, "tape", 4));
static void
-trydev(const char *device, int user_specified)
+open_list_and_close(const char *device, int user_specified)
{
int gb;
if (!user_specified)
if (is_ide_cdrom_or_tape(device))
return;
- fd = open(disk_device, type_open);
- if (fd >= 0) {
- gb = get_boot(try_only);
- if (gb > 0) { /* I/O error */
- close(fd);
- } else if (gb < 0) { /* no DOS signature */
- list_disk_geometry();
- if (LABEL_IS_AIX) {
- return;
- }
-#if ENABLE_FEATURE_OSF_LABEL
- if (bsd_trydev(device) < 0)
-#endif
- printf("Disk %s doesn't contain a valid "
- "partition table\n", device);
- close(fd);
- } else {
- close(fd);
- list_table(0);
-#if ENABLE_FEATURE_FDISK_WRITABLE
- if (!LABEL_IS_SUN && partitions > 4){
- delete_partition(ext_index);
- }
-#endif
- }
- } else {
+
+ /* Open disk_device, save file descriptor to dev_fd */
+ errno = 0;
+ gb = get_boot(TRY_ONLY);
+ if (gb > 0) { /* I/O error */
/* Ignore other errors, since we try IDE
and SCSI hard disks which may not be
installed on the system. */
- if (errno == EACCES) {
- printf("Cannot open %s\n", device);
- return;
+ if (user_specified || errno == EACCES)
+ bb_perror_msg("can't open '%s'", device);
+ return;
+ }
+
+ if (gb < 0) { /* no DOS signature */
+ list_disk_geometry();
+ if (LABEL_IS_AIX)
+ goto ret;
+#if ENABLE_FEATURE_OSF_LABEL
+ if (bsd_trydev(device) < 0)
+#endif
+ printf("Disk %s doesn't contain a valid "
+ "partition table\n", device);
+ } else {
+ list_table(0);
+#if ENABLE_FEATURE_FDISK_WRITABLE
+ if (!LABEL_IS_SUN && g_partitions > 4) {
+ delete_partition(ext_index);
}
+#endif
}
+ ret:
+ close_dev_fd();
}
/* for fdisk -l: try all things in /proc/partitions
that look like a partition name (do not end in a digit) */
static void
-tryprocpt(void)
+list_devs_in_proc_partititons(void)
{
FILE *procpt;
char line[100], ptname[100], devname[120], *s;
if (sscanf(line, " %d %d %d %[^\n ]",
&ma, &mi, &sz, ptname) != 4)
continue;
- for (s = ptname; *s; s++);
+ for (s = ptname; *s; s++)
+ continue;
if (isdigit(s[-1]))
continue;
sprintf(devname, "/dev/%s", ptname);
- trydev(devname, 0);
+ open_list_and_close(devname, 0);
}
#if ENABLE_FEATURE_CLEAN_UP
fclose(procpt);
}
#endif
-int fdisk_main(int argc, char **argv);
+int fdisk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int fdisk_main(int argc, char **argv)
{
- char *str_b, *str_C, *str_H, *str_S;
unsigned opt;
/*
* fdisk -v
*
* Options -C, -H, -S set the geometry.
*/
- enum {
- OPT_b = 1 << 0,
- OPT_C = 1 << 1,
- OPT_H = 1 << 2,
- OPT_l = 1 << 3,
- OPT_S = 1 << 4,
- OPT_u = 1 << 5,
- OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
- };
-
- PTR_TO_GLOBALS = xzalloc(sizeof(G));
-
- opt = getopt32(argc, argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"),
- &str_b, &str_C, &str_H, &str_S);
+ INIT_G();
+
+ close_dev_fd(); /* needed: fd 3 must not stay closed */
+
+ opt_complementary = "b+:C+:H+:S+"; /* numeric params */
+ opt = getopt32(argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"),
+ §or_size, &user_cylinders, &user_heads, &user_sectors);
argc -= optind;
argv += optind;
if (opt & OPT_b) { // -b
so cannot be combined with multiple disks,
and the same goes for the C/H/S options.
*/
- sector_size = xatoi_u(str_b);
- if (sector_size != 512 && sector_size != 1024 &&
- sector_size != 2048)
+ if (sector_size != 512 && sector_size != 1024
+ && sector_size != 2048)
bb_show_usage();
sector_offset = 2;
user_set_sector_size = 1;
}
- if (opt & OPT_C) user_cylinders = xatoi_u(str_C); // -C
- if (opt & OPT_H) { // -H
- user_heads = xatoi_u(str_H);
- if (user_heads <= 0 || user_heads >= 256)
- user_heads = 0;
- }
- //if (opt & OPT_l) // -l
- if (opt & OPT_S) { // -S
- user_sectors = xatoi_u(str_S);
- if (user_sectors <= 0 || user_sectors >= 64)
- user_sectors = 0;
- }
- if (opt & OPT_u) display_in_cyl_units = 0; // -u
- //if (opt & OPT_s) // -s
-
- if (user_set_sector_size && argc != 1)
- printf("Warning: the -b (set sector size) option should"
- " be used with one specified device\n");
+ if (user_heads <= 0 || user_heads >= 256)
+ user_heads = 0;
+ if (user_sectors <= 0 || user_sectors >= 64)
+ user_sectors = 0;
+ if (opt & OPT_u)
+ display_in_cyl_units = 0; // -u
#if ENABLE_FEATURE_FDISK_WRITABLE
if (opt & OPT_l) {
nowarn = 1;
#endif
- type_open = O_RDONLY;
- if (argc > 0) {
- int k;
-#if defined(__GNUC__)
- /* avoid gcc warning:
- variable `k' might be clobbered by `longjmp' */
- (void)&k;
-#endif
+ if (*argv) {
listing = 1;
- for (k = 0; k < argc; k++)
- trydev(argv[k], 1);
+ do {
+ open_list_and_close(*argv, 1);
+ } while (*++argv);
} else {
- /* we no longer have default device names */
- /* but, we can use /proc/partitions instead */
- tryprocpt();
+ /* we don't have device names, */
+ /* use /proc/partitions instead */
+ list_devs_in_proc_partititons();
}
return 0;
#if ENABLE_FEATURE_FDISK_WRITABLE
#if ENABLE_FEATURE_FDISK_BLKSIZE
if (opt & OPT_s) {
- long size;
int j;
nowarn = 1;
- type_open = O_RDONLY;
-
if (argc <= 0)
bb_show_usage();
-
for (j = 0; j < argc; j++) {
- disk_device = argv[j];
- fd = open(disk_device, type_open);
- if (fd < 0)
- fdisk_fatal(unable_to_open);
- if (ioctl(fd, BLKGETSIZE, &size))
- fdisk_fatal(ioctl_error);
+ unsigned long long size;
+ fd = xopen(argv[j], O_RDONLY);
+ size = bb_BLKGETSIZE_sectors(fd) / 2;
close(fd);
if (argc == 1)
- printf("%ld\n", size/2);
+ printf("%lld\n", size);
else
- printf("%s: %ld\n", argv[j], size/2);
+ printf("%s: %lld\n", argv[j], size);
}
return 0;
}
bb_show_usage();
disk_device = argv[0];
- get_boot(fdisk);
+ get_boot(OPEN_MAIN);
if (LABEL_IS_OSF) {
/* OSF label, and no DOS label */
"disklabel mode\n", disk_device);
bsd_select();
/*Why do we do this? It seems to be counter-intuitive*/
- current_label_type = label_dos;
+ current_label_type = LABEL_DOS;
/* If we return we may want to make an empty DOS label? */
}
while (1) {
int c;
- putchar('\n');
+ bb_putchar('\n');
c = tolower(read_nonempty("Command (m for help): "));
switch (c) {
case 'a':
if (LABEL_IS_DOS)
- toggle_active(get_partition(1, partitions));
+ toggle_active(get_partition(1, g_partitions));
else if (LABEL_IS_SUN)
- toggle_sunflags(get_partition(1, partitions),
+ toggle_sunflags(get_partition(1, g_partitions),
0x01);
else if (LABEL_IS_SGI)
sgi_set_bootpartition(
- get_partition(1, partitions));
+ get_partition(1, g_partitions));
else
unknown_command(c);
break;
if (LABEL_IS_DOS)
toggle_dos_compatibility_flag();
else if (LABEL_IS_SUN)
- toggle_sunflags(get_partition(1, partitions),
+ toggle_sunflags(get_partition(1, g_partitions),
0x10);
else if (LABEL_IS_SGI)
sgi_set_swappartition(
- get_partition(1, partitions));
+ get_partition(1, g_partitions));
else
unknown_command(c);
break;
get_existing_partition() only works for Linux-like
partition tables */
if (!LABEL_IS_SGI) {
- j = get_existing_partition(1, partitions);
+ j = get_existing_partition(1, g_partitions);
} else {
- j = get_partition(1, partitions);
+ j = get_partition(1, g_partitions);
}
if (j >= 0)
delete_partition(j);
list_table(0);
break;
case 'q':
- close(fd);
- puts("");
+ if (ENABLE_FEATURE_CLEAN_UP)
+ close_dev_fd();
+ bb_putchar('\n');
return 0;
case 's':
#if ENABLE_FEATURE_SUN_LABEL