fdisk: do not open device twice. Complain on fdisk -l /dev/bogus.
  Made enums UPPERCASE. Removed one global variable.
  Added some FIXMEs.

   text    data     bss     dec     hex filename
 804708     645    7112  812465   c65b1 busybox_old
 804685     641    7112  812438   c6596 busybox_unstripped

diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c
index dcfae96..57d4d65 100644
--- a/util-linux/fdisk.c
+++ b/util-linux/fdisk.c
@@ -78,13 +78,13 @@
 static void fdisk_fatal(const char *why) ATTRIBUTE_NORETURN;
 
 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
@@ -92,7 +92,7 @@
 #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
@@ -100,7 +100,7 @@
 #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
@@ -108,14 +108,14 @@
 #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 };
+enum action { OPEN_MAIN, TRY_ONLY, CREATE_EMPTY_DOS, CREATE_EMPTY_SUN };
 
 static void update_units(void);
 #if ENABLE_FEATURE_FDISK_WRITABLE
@@ -263,14 +263,15 @@
 	NULL
 };
 
+enum {
+	dev_fd = 3                  /* the disk */
+};
 
 /* Globals */
-
 struct globals {
 	char *line_ptr;
 
 	const char *disk_device;
-	int fd;                         /* the disk */
 	int g_partitions; // = 4;       /* maximum partition + 1 */
 	unsigned units_per_sector; // = 1;
 	unsigned sector_size; // = DEFAULT_SECTOR_SIZE;
@@ -295,7 +296,6 @@
 #define G (*ptr_to_globals)
 #define line_ptr        (G.line_ptr)
 #define disk_device          (G.disk_device         )
-#define fd                   (G.fd                  )
 #define g_partitions         (G.g_partitions        )
 #define units_per_sector     (G.units_per_sector    )
 #define sector_size          (G.sector_size         )
@@ -323,7 +323,7 @@
 
 
 /* TODO: move to libbb? */
-static ullong bb_BLKGETSIZE_sectors(void)
+static ullong bb_BLKGETSIZE_sectors(int fd)
 {
 	uint64_t v64;
 	unsigned long longsectors;
@@ -642,9 +642,6 @@
 	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 smallint listing;                /* no aborts for fdisk -l */
 static smallint dos_compatible_flag = 1;
@@ -663,7 +660,7 @@
 static void fdisk_fatal(const char *why)
 {
 	if (listing) {
-		close(fd);
+		close(dev_fd);
 		longjmp(listingbuf, 1);
 	}
 	bb_error_msg_and_die(why, disk_device);
@@ -674,11 +671,11 @@
 {
 	secno *= sector_size;
 #if ENABLE_FDISK_SUPPORT_LARGE_DISKS
-	if (lseek64(fd, (off64_t)secno, SEEK_SET) == (off64_t) -1)
+	if (lseek64(dev_fd, (off64_t)secno, SEEK_SET) == (off64_t) -1)
 		fdisk_fatal(unable_to_seek);
 #else
 	if (secno > MAXINT(off_t)
-	 || lseek(fd, (off_t)secno, SEEK_SET) == (off_t) -1
+	 || lseek(dev_fd, (off_t)secno, SEEK_SET) == (off_t) -1
 	) {
 		fdisk_fatal(unable_to_seek);
 	}
@@ -690,7 +687,7 @@
 write_sector(ullong secno, char *buf)
 {
 	seek_sector(secno);
-	if (write(fd, buf, sector_size) != sector_size)
+	if (write(dev_fd, buf, sector_size) != sector_size)
 		fdisk_fatal(unable_to_write);
 }
 #endif
@@ -702,7 +699,7 @@
 	pe->offset = offset;
 	pe->sectorbuffer = xmalloc(sector_size);
 	seek_sector(offset);
-	if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
+	if (read(dev_fd, pe->sectorbuffer, sector_size) != sector_size)
 		fdisk_fatal(unable_to_read);
 #if ENABLE_FEATURE_FDISK_WRITABLE
 	pe->changed = 0;
@@ -1126,7 +1123,7 @@
 
 	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;
@@ -1139,7 +1136,7 @@
 	extended_offset = 0;
 	set_all_unchanged();
 	set_changed(0);
-	get_boot(create_empty_dos);
+	get_boot(CREATE_EMPTY_DOS);
 }
 #endif /* FEATURE_FDISK_WRITABLE */
 
@@ -1148,7 +1145,7 @@
 {
 	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",
@@ -1161,7 +1158,7 @@
 {
 	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 */
@@ -1224,7 +1221,7 @@
 	g_sectors = user_sectors ? user_sectors :
 		pt_sectors ? pt_sectors :
 		kern_sectors ? kern_sectors : 63;
-	total_number_of_sectors = bb_BLKGETSIZE_sectors();
+	total_number_of_sectors = bb_BLKGETSIZE_sectors(dev_fd);
 
 	sector_offset = 1;
 	if (dos_compatible_flag)
@@ -1236,7 +1233,9 @@
 }
 
 /*
- * 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
@@ -1248,82 +1247,80 @@
 #define get_boot(what) get_boot()
 #endif
 {
-	int i;
+	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, type_open);
+	fd = open(disk_device, (option_mask32 & OPT_l) ? O_RDONLY : O_RDWR);
+
 	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");
+		}
+		xmove_fd(fd, dev_fd);
+		printf("'%s' is opened for read only\n", disk_device);
 	}
-
-	if (512 != read(fd, MBRbuffer, 512)) {
-		if (what == try_only)
+	if (512 != 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 != 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"
@@ -1331,49 +1328,34 @@
 	}
 #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 (IS_EXTENDED(ptes[i].part_table->sys_ind)) {
 			if (g_partitions != 4)
 				printf("Ignoring extra extended "
 					"partition %d\n", i + 1);
@@ -1384,16 +1366,13 @@
 
 	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;)
 		}
 	}
 
@@ -2474,7 +2453,7 @@
 	printf("Calling ioctl() to re-read partition table\n");
 	sync();
 	/* sleep(2); Huh? */
-	i = ioctl_or_perror(fd, BLKRRPART, NULL,
+	i = ioctl_or_perror(dev_fd, BLKRRPART, NULL,
 			"WARNING: rereading partition table "
 			"failed, kernel still uses old table");
 #if 0
@@ -2487,7 +2466,7 @@
 
 	if (leave) {
 		if (ENABLE_FEATURE_CLEAN_UP)
-			close(fd);
+			close(dev_fd);
 		exit(i != 0);
 	}
 }
@@ -2619,7 +2598,8 @@
 				x_list_table(0);
 			break;
 		case 'q':
-			close(fd);
+			if (ENABLE_FEATURE_CLEAN_UP)
+				close(dev_fd);
 			bb_putchar('\n');
 			exit(0);
 		case 'r':
@@ -2687,7 +2667,7 @@
 
 
 static void
-trydev(const char *device, int user_specified)
+open_list_and_close(const char *device, int user_specified)
 {
 	int gb;
 
@@ -2697,46 +2677,44 @@
 	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 && g_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;
@@ -2753,7 +2731,7 @@
 		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);
@@ -2792,6 +2770,8 @@
 
 	INIT_G();
 
+	close(dev_fd); /* just in case */
+
 	opt_complementary = "b+:C+:H+:S+"; /* numeric params */
 	opt = getopt32(argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"),
 				&sector_size, &user_cylinders, &user_heads, &user_sectors);
@@ -2819,16 +2799,15 @@
 	if (opt & OPT_l) {
 		nowarn = 1;
 #endif
-		type_open = O_RDONLY;
 		if (*argv) {
 			listing = 1;
 			do {
-				trydev(*argv, 1);
+				open_list_and_close(*argv, 1);
 			} while (*++argv);
 		} else {
 			/* we don't have device names, */
 			/* use /proc/partitions instead */
-			tryprocpt();
+			list_devs_in_proc_partititons();
 		}
 		return 0;
 #if ENABLE_FEATURE_FDISK_WRITABLE
@@ -2845,7 +2824,7 @@
 		for (j = 0; j < argc; j++) {
 			unsigned long long size;
 			fd = xopen(argv[j], O_RDONLY);
-			size = bb_BLKGETSIZE_sectors() / 2;
+			size = bb_BLKGETSIZE_sectors(fd) / 2;
 			close(fd);
 			if (argc == 1)
 				printf("%lld\n", size);
@@ -2861,7 +2840,7 @@
 		bb_show_usage();
 
 	disk_device = argv[0];
-	get_boot(fdisk);
+	get_boot(OPEN_MAIN);
 
 	if (LABEL_IS_OSF) {
 		/* OSF label, and no DOS label */
@@ -2869,7 +2848,7 @@
 			"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? */
 	}
 
@@ -2954,7 +2933,7 @@
 			list_table(0);
 			break;
 		case 'q':
-			close(fd);
+			close(dev_fd);
 			bb_putchar('\n');
 			return 0;
 		case 's':