blob: da03e683eddcff7a54192177a6d5772ad81ec509 [file] [log] [blame]
"Robert P. J. Day"63fc1a92006-07-02 19:47:05 +00001/* vi: set sw=4 ts=4: */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002/* fdisk.c -- Partition table manipulator for Linux.
3 *
4 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
Mike Frysinger983e0ca2006-02-25 07:42:02 +00005 * Copyright (C) 2001,2002 Vladimir Oleynik <dzo@simtreas.ru> (initial bb port)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00006 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +02007 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00008 */
9
Pere Orga5bc8c002011-04-11 03:29:49 +020010/* Looks like someone forgot to add this to config system */
11//usage:#ifndef ENABLE_FEATURE_FDISK_BLKSIZE
12//usage:# define ENABLE_FEATURE_FDISK_BLKSIZE 0
13//usage:# define IF_FEATURE_FDISK_BLKSIZE(a)
14//usage:#endif
15//usage:
16//usage:#define fdisk_trivial_usage
17//usage: "[-ul" IF_FEATURE_FDISK_BLKSIZE("s") "] "
18//usage: "[-C CYLINDERS] [-H HEADS] [-S SECTORS] [-b SSZ] DISK"
19//usage:#define fdisk_full_usage "\n\n"
20//usage: "Change partition table\n"
21//usage: "\nOptions:"
22//usage: "\n -u Start and End are in sectors (instead of cylinders)"
23//usage: "\n -l Show partition table for each DISK, then exit"
24//usage: IF_FEATURE_FDISK_BLKSIZE(
25//usage: "\n -s Show partition sizes in kb for each DISK, then exit"
26//usage: )
27//usage: "\n -b 2048 (for certain MO disks) use 2048-byte sectors"
28//usage: "\n -C CYLINDERS Set number of cylinders/heads/sectors"
29//usage: "\n -H HEADS"
30//usage: "\n -S SECTORS"
31
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +000032#ifndef _LARGEFILE64_SOURCE
33/* For lseek64 */
Denys Vlasenkoaf3fd142009-09-22 23:16:39 +020034# define _LARGEFILE64_SOURCE
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +000035#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000036#include <assert.h> /* assert */
Denys Vlasenkoda49f582009-07-08 02:58:38 +020037#include <sys/mount.h>
38#if !defined(BLKSSZGET)
39# define BLKSSZGET _IO(0x12, 104)
40#endif
Denys Vlasenkoaf3fd142009-09-22 23:16:39 +020041#if !defined(BLKGETSIZE64)
42# define BLKGETSIZE64 _IOR(0x12,114,size_t)
43#endif
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000044#include "libbb.h"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000045
Denys Vlasenko5ea1de22010-04-06 02:31:43 +020046#if BB_LITTLE_ENDIAN
47# define inline_if_little_endian ALWAYS_INLINE
48#else
49# define inline_if_little_endian /* nothing */
50#endif
51
52
Denis Vlasenko834410a2006-11-29 12:00:28 +000053/* Looks like someone forgot to add this to config system */
54#ifndef ENABLE_FEATURE_FDISK_BLKSIZE
55# define ENABLE_FEATURE_FDISK_BLKSIZE 0
Denis Vlasenko5e34ff22009-04-21 11:09:40 +000056# define IF_FEATURE_FDISK_BLKSIZE(a)
Denis Vlasenko834410a2006-11-29 12:00:28 +000057#endif
58
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +000059#define DEFAULT_SECTOR_SIZE 512
60#define DEFAULT_SECTOR_SIZE_STR "512"
61#define MAX_SECTOR_SIZE 2048
62#define SECTOR_SIZE 512 /* still used in osf/sgi/sun code */
63#define MAXIMUM_PARTS 60
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000064
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +000065#define ACTIVE_FLAG 0x80
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000066
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +000067#define EXTENDED 0x05
68#define WIN98_EXTENDED 0x0f
69#define LINUX_PARTITION 0x81
70#define LINUX_SWAP 0x82
71#define LINUX_NATIVE 0x83
72#define LINUX_EXTENDED 0x85
73#define LINUX_LVM 0x8e
74#define LINUX_RAID 0xfd
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000075
Denis Vlasenkoc033d512008-04-17 01:52:28 +000076
77enum {
78 OPT_b = 1 << 0,
79 OPT_C = 1 << 1,
80 OPT_H = 1 << 2,
81 OPT_l = 1 << 3,
82 OPT_S = 1 << 4,
83 OPT_u = 1 << 5,
84 OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
85};
86
87
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +000088typedef unsigned long long ullong;
Denys Vlasenkoddf78502009-09-16 03:03:13 +020089/* Used for sector numbers. Partition formats we know
90 * do not support more than 2^32 sectors
91 */
92typedef uint32_t sector_t;
93#if UINT_MAX == 4294967295
94# define SECT_FMT ""
95#elif ULONG_MAX == 4294967295
96# define SECT_FMT "l"
97#else
98# error Cant detect sizeof(uint32_t)
99#endif
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000100
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000101struct hd_geometry {
Rob Landleyb73451d2006-02-24 16:29:00 +0000102 unsigned char heads;
103 unsigned char sectors;
104 unsigned short cylinders;
105 unsigned long start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000106};
107
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000108#define HDIO_GETGEO 0x0301 /* get device geometry */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000109
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000110static const char msg_building_new_label[] ALIGN1 =
Denis Vlasenkobd852072007-03-19 14:43:38 +0000111"Building a new %s. Changes will remain in memory only,\n"
112"until you decide to write them. After that the previous content\n"
113"won't be recoverable.\n\n";
114
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000115static const char msg_part_already_defined[] ALIGN1 =
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200116"Partition %u is already defined, delete it before re-adding\n";
Denis Vlasenkobd852072007-03-19 14:43:38 +0000117
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000118
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000119struct partition {
120 unsigned char boot_ind; /* 0x80 - active */
121 unsigned char head; /* starting head */
122 unsigned char sector; /* starting sector */
123 unsigned char cyl; /* starting cylinder */
Denis Vlasenko9764d692008-07-09 21:20:50 +0000124 unsigned char sys_ind; /* what partition type */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000125 unsigned char end_head; /* end head */
126 unsigned char end_sector; /* end sector */
127 unsigned char end_cyl; /* end cylinder */
128 unsigned char start4[4]; /* starting sector counting from 0 */
129 unsigned char size4[4]; /* nr of sectors in partition */
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000130} PACKED;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000131
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200132/*
133 * per partition table entry data
134 *
135 * The four primary partitions have the same sectorbuffer (MBRbuffer)
136 * and have NULL ext_pointer.
137 * Each logical partition table entry has two pointers, one for the
138 * partition and one link to the next one.
139 */
140struct pte {
141 struct partition *part_table; /* points into sectorbuffer */
142 struct partition *ext_pointer; /* points into sectorbuffer */
143 sector_t offset_from_dev_start; /* disk sector number */
144 char *sectorbuffer; /* disk sector contents */
145#if ENABLE_FEATURE_FDISK_WRITABLE
146 char changed; /* boolean */
147#endif
148};
149
Denys Vlasenkoea8b2522010-06-02 12:57:26 +0200150#define unable_to_open "can't open '%s'"
151#define unable_to_read "can't read from %s"
152#define unable_to_seek "can't seek on %s"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000153
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000154enum label_type {
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200155 LABEL_DOS, LABEL_SUN, LABEL_SGI, LABEL_AIX, LABEL_OSF, LABEL_GPT
Rob Landley5527b912006-02-25 03:46:10 +0000156};
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000157
Denis Vlasenko4437d192008-04-17 00:12:10 +0000158#define LABEL_IS_DOS (LABEL_DOS == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000159
Denis Vlasenko834410a2006-11-29 12:00:28 +0000160#if ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko4437d192008-04-17 00:12:10 +0000161#define LABEL_IS_SUN (LABEL_SUN == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000162#define STATIC_SUN static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000163#else
164#define LABEL_IS_SUN 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000165#define STATIC_SUN extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000166#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000167
Denis Vlasenko834410a2006-11-29 12:00:28 +0000168#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenko4437d192008-04-17 00:12:10 +0000169#define LABEL_IS_SGI (LABEL_SGI == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000170#define STATIC_SGI static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000171#else
172#define LABEL_IS_SGI 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000173#define STATIC_SGI extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000174#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000175
Denis Vlasenko834410a2006-11-29 12:00:28 +0000176#if ENABLE_FEATURE_AIX_LABEL
Denis Vlasenko4437d192008-04-17 00:12:10 +0000177#define LABEL_IS_AIX (LABEL_AIX == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000178#define STATIC_AIX static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000179#else
180#define LABEL_IS_AIX 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000181#define STATIC_AIX extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000182#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000183
Denis Vlasenko834410a2006-11-29 12:00:28 +0000184#if ENABLE_FEATURE_OSF_LABEL
Denis Vlasenko4437d192008-04-17 00:12:10 +0000185#define LABEL_IS_OSF (LABEL_OSF == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000186#define STATIC_OSF static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000187#else
188#define LABEL_IS_OSF 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000189#define STATIC_OSF extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000190#endif
Rob Landley5527b912006-02-25 03:46:10 +0000191
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200192#if ENABLE_FEATURE_GPT_LABEL
193#define LABEL_IS_GPT (LABEL_GPT == current_label_type)
194#define STATIC_GPT static
195#else
196#define LABEL_IS_GPT 0
197#define STATIC_GPT extern
198#endif
199
Denis Vlasenko4437d192008-04-17 00:12:10 +0000200enum action { OPEN_MAIN, TRY_ONLY, CREATE_EMPTY_DOS, CREATE_EMPTY_SUN };
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000201
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000202static void update_units(void);
Denis Vlasenko834410a2006-11-29 12:00:28 +0000203#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000204static void change_units(void);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000205static void reread_partition_table(int leave);
206static void delete_partition(int i);
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200207static unsigned get_partition(int warn, unsigned max);
Denis Vlasenkobd852072007-03-19 14:43:38 +0000208static void list_types(const char *const *sys);
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200209static sector_t read_int(sector_t low, sector_t dflt, sector_t high, sector_t base, const char *mesg);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000210#endif
211static const char *partition_type(unsigned char type);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000212static void get_geometry(void);
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200213static void read_pte(struct pte *pe, sector_t offset);
Denis Vlasenko85c24712008-03-17 09:04:04 +0000214#if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000215static int get_boot(enum action what);
Denis Vlasenko85c24712008-03-17 09:04:04 +0000216#else
217static int get_boot(void);
218#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000219
220#define PLURAL 0
221#define SINGULAR 1
222
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200223static sector_t get_start_sect(const struct partition *p);
224static sector_t get_nr_sects(const struct partition *p);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000225
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000226/* DOS partition types */
227
228static const char *const i386_sys_types[] = {
229 "\x00" "Empty",
230 "\x01" "FAT12",
231 "\x04" "FAT16 <32M",
232 "\x05" "Extended", /* DOS 3.3+ extended partition */
233 "\x06" "FAT16", /* DOS 16-bit >=32M */
234 "\x07" "HPFS/NTFS", /* OS/2 IFS, eg, HPFS or NTFS or QNX */
235 "\x0a" "OS/2 Boot Manager",/* OS/2 Boot Manager */
236 "\x0b" "Win95 FAT32",
237 "\x0c" "Win95 FAT32 (LBA)",/* LBA really is 'Extended Int 13h' */
238 "\x0e" "Win95 FAT16 (LBA)",
239 "\x0f" "Win95 Ext'd (LBA)",
240 "\x11" "Hidden FAT12",
241 "\x12" "Compaq diagnostics",
242 "\x14" "Hidden FAT16 <32M",
243 "\x16" "Hidden FAT16",
244 "\x17" "Hidden HPFS/NTFS",
245 "\x1b" "Hidden Win95 FAT32",
246 "\x1c" "Hidden W95 FAT32 (LBA)",
247 "\x1e" "Hidden W95 FAT16 (LBA)",
248 "\x3c" "Part.Magic recovery",
249 "\x41" "PPC PReP Boot",
250 "\x42" "SFS",
251 "\x63" "GNU HURD or SysV", /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
252 "\x80" "Old Minix", /* Minix 1.4a and earlier */
253 "\x81" "Minix / old Linux",/* Minix 1.4b and later */
254 "\x82" "Linux swap", /* also Solaris */
255 "\x83" "Linux",
256 "\x84" "OS/2 hidden C: drive",
257 "\x85" "Linux extended",
258 "\x86" "NTFS volume set",
259 "\x87" "NTFS volume set",
260 "\x8e" "Linux LVM",
261 "\x9f" "BSD/OS", /* BSDI */
262 "\xa0" "Thinkpad hibernation",
263 "\xa5" "FreeBSD", /* various BSD flavours */
264 "\xa6" "OpenBSD",
265 "\xa8" "Darwin UFS",
266 "\xa9" "NetBSD",
267 "\xab" "Darwin boot",
268 "\xb7" "BSDI fs",
269 "\xb8" "BSDI swap",
270 "\xbe" "Solaris boot",
271 "\xeb" "BeOS fs",
272 "\xee" "EFI GPT", /* Intel EFI GUID Partition Table */
273 "\xef" "EFI (FAT-12/16/32)", /* Intel EFI System Partition */
274 "\xf0" "Linux/PA-RISC boot", /* Linux/PA-RISC boot loader */
275 "\xf2" "DOS secondary", /* DOS 3.3+ secondary */
276 "\xfd" "Linux raid autodetect", /* New (2.2.x) raid partition with
277 autodetect using persistent
278 superblock */
279#if 0 /* ENABLE_WEIRD_PARTITION_TYPES */
280 "\x02" "XENIX root",
281 "\x03" "XENIX usr",
282 "\x08" "AIX", /* AIX boot (AIX -- PS/2 port) or SplitDrive */
283 "\x09" "AIX bootable", /* AIX data or Coherent */
284 "\x10" "OPUS",
285 "\x18" "AST SmartSleep",
286 "\x24" "NEC DOS",
287 "\x39" "Plan 9",
288 "\x40" "Venix 80286",
289 "\x4d" "QNX4.x",
290 "\x4e" "QNX4.x 2nd part",
291 "\x4f" "QNX4.x 3rd part",
292 "\x50" "OnTrack DM",
293 "\x51" "OnTrack DM6 Aux1", /* (or Novell) */
294 "\x52" "CP/M", /* CP/M or Microport SysV/AT */
295 "\x53" "OnTrack DM6 Aux3",
296 "\x54" "OnTrackDM6",
297 "\x55" "EZ-Drive",
298 "\x56" "Golden Bow",
299 "\x5c" "Priam Edisk",
300 "\x61" "SpeedStor",
301 "\x64" "Novell Netware 286",
302 "\x65" "Novell Netware 386",
303 "\x70" "DiskSecure Multi-Boot",
304 "\x75" "PC/IX",
305 "\x93" "Amoeba",
306 "\x94" "Amoeba BBT", /* (bad block table) */
307 "\xa7" "NeXTSTEP",
308 "\xbb" "Boot Wizard hidden",
309 "\xc1" "DRDOS/sec (FAT-12)",
310 "\xc4" "DRDOS/sec (FAT-16 < 32M)",
311 "\xc6" "DRDOS/sec (FAT-16)",
312 "\xc7" "Syrinx",
313 "\xda" "Non-FS data",
314 "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or
315 Concurrent DOS or CTOS */
316 "\xde" "Dell Utility", /* Dell PowerEdge Server utilities */
317 "\xdf" "BootIt", /* BootIt EMBRM */
318 "\xe1" "DOS access", /* DOS access or SpeedStor 12-bit FAT
319 extended partition */
320 "\xe3" "DOS R/O", /* DOS R/O or SpeedStor */
321 "\xe4" "SpeedStor", /* SpeedStor 16-bit FAT extended
322 partition < 1024 cyl. */
323 "\xf1" "SpeedStor",
324 "\xf4" "SpeedStor", /* SpeedStor large partition */
325 "\xfe" "LANstep", /* SpeedStor >1024 cyl. or LANstep */
326 "\xff" "BBT", /* Xenix Bad Block Table */
327#endif
328 NULL
329};
330
Denis Vlasenko4437d192008-04-17 00:12:10 +0000331enum {
332 dev_fd = 3 /* the disk */
333};
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000334
335/* Globals */
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000336struct globals {
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000337 char *line_ptr;
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000338
339 const char *disk_device;
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000340 int g_partitions; // = 4; /* maximum partition + 1 */
341 unsigned units_per_sector; // = 1;
342 unsigned sector_size; // = DEFAULT_SECTOR_SIZE;
343 unsigned user_set_sector_size;
344 unsigned sector_offset; // = 1;
345 unsigned g_heads, g_sectors, g_cylinders;
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000346 smallint /* enum label_type */ current_label_type;
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000347 smallint display_in_cyl_units; // = 1;
348#if ENABLE_FEATURE_OSF_LABEL
349 smallint possibly_osf_label;
350#endif
351
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000352 smallint listing; /* no aborts for fdisk -l */
353 smallint dos_compatible_flag; // = 1;
354#if ENABLE_FEATURE_FDISK_WRITABLE
355 //int dos_changed;
356 smallint nowarn; /* no warnings for fdisk -l/-s */
357#endif
358 int ext_index; /* the prime extended partition */
359 unsigned user_cylinders, user_heads, user_sectors;
360 unsigned pt_heads, pt_sectors;
361 unsigned kern_heads, kern_sectors;
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200362 sector_t extended_offset; /* offset of link pointers */
363 sector_t total_number_of_sectors;
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000364
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000365 jmp_buf listingbuf;
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000366 char line_buffer[80];
367 char partname_buffer[80];
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000368 /* Raw disk label. For DOS-type partition tables the MBR,
369 * with descriptions of the primary partitions. */
370 char MBRbuffer[MAX_SECTOR_SIZE];
371 /* Partition tables */
372 struct pte ptes[MAXIMUM_PARTS];
373};
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000374#define G (*ptr_to_globals)
Denis Vlasenko270d5d72008-06-29 05:16:45 +0000375#define line_ptr (G.line_ptr )
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000376#define disk_device (G.disk_device )
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000377#define g_partitions (G.g_partitions )
378#define units_per_sector (G.units_per_sector )
379#define sector_size (G.sector_size )
380#define user_set_sector_size (G.user_set_sector_size)
381#define sector_offset (G.sector_offset )
382#define g_heads (G.g_heads )
383#define g_sectors (G.g_sectors )
384#define g_cylinders (G.g_cylinders )
385#define current_label_type (G.current_label_type )
386#define display_in_cyl_units (G.display_in_cyl_units)
387#define possibly_osf_label (G.possibly_osf_label )
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000388#define listing (G.listing )
389#define dos_compatible_flag (G.dos_compatible_flag )
390#define nowarn (G.nowarn )
391#define ext_index (G.ext_index )
392#define user_cylinders (G.user_cylinders )
393#define user_heads (G.user_heads )
394#define user_sectors (G.user_sectors )
395#define pt_heads (G.pt_heads )
396#define pt_sectors (G.pt_sectors )
397#define kern_heads (G.kern_heads )
398#define kern_sectors (G.kern_sectors )
399#define extended_offset (G.extended_offset )
400#define total_number_of_sectors (G.total_number_of_sectors)
Denis Vlasenko270d5d72008-06-29 05:16:45 +0000401#define listingbuf (G.listingbuf )
402#define line_buffer (G.line_buffer )
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000403#define partname_buffer (G.partname_buffer)
Denis Vlasenko270d5d72008-06-29 05:16:45 +0000404#define MBRbuffer (G.MBRbuffer )
405#define ptes (G.ptes )
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000406#define INIT_G() do { \
Denis Vlasenko574f2f42008-02-27 18:41:59 +0000407 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000408 sector_size = DEFAULT_SECTOR_SIZE; \
409 sector_offset = 1; \
410 g_partitions = 4; \
411 display_in_cyl_units = 1; \
412 units_per_sector = 1; \
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000413 dos_compatible_flag = 1; \
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000414} while (0)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000415
Denis Vlasenkobd852072007-03-19 14:43:38 +0000416
Denis Vlasenkocdf62772008-03-17 08:42:43 +0000417/* TODO: move to libbb? */
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200418/* TODO: return unsigned long long, FEATURE_FDISK_BLKSIZE _can_ handle
419 * disks > 2^32 sectors
420 */
421static sector_t bb_BLKGETSIZE_sectors(int fd)
Denis Vlasenkocdf62772008-03-17 08:42:43 +0000422{
423 uint64_t v64;
424 unsigned long longsectors;
425
426 if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
Denis Vlasenko270d5d72008-06-29 05:16:45 +0000427 /* Got bytes, convert to 512 byte sectors */
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200428 v64 >>= 9;
429 if (v64 != (sector_t)v64) {
430 ret_trunc:
431 /* Not only DOS, but all other partition tables
432 * we support can't record more than 32 bit
433 * sector counts or offsets
434 */
435 bb_error_msg("device has more than 2^32 sectors, can't use all of them");
436 v64 = (uint32_t)-1L;
437 }
438 return v64;
Denis Vlasenkocdf62772008-03-17 08:42:43 +0000439 }
440 /* Needs temp of type long */
Denys Vlasenkod958e902010-04-06 02:32:26 +0200441 if (ioctl(fd, BLKGETSIZE, &longsectors)) {
442 /* Perhaps this is a disk image */
443 off_t sz = lseek(fd, 0, SEEK_END);
Denis Vlasenkocdf62772008-03-17 08:42:43 +0000444 longsectors = 0;
Denys Vlasenkod958e902010-04-06 02:32:26 +0200445 if (sz > 0)
446 longsectors = (uoff_t)sz / sector_size;
447 lseek(fd, 0, SEEK_SET);
448 }
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200449 if (sizeof(long) > sizeof(sector_t)
450 && longsectors != (sector_t)longsectors
451 ) {
452 goto ret_trunc;
453 }
Denis Vlasenkocdf62772008-03-17 08:42:43 +0000454 return longsectors;
455}
456
457
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000458#define IS_EXTENDED(i) \
459 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
460
461#define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
462
463#define scround(x) (((x)+units_per_sector-1)/units_per_sector)
464
465#define pt_offset(b, n) \
466 ((struct partition *)((b) + 0x1be + (n) * sizeof(struct partition)))
467
468#define sector(s) ((s) & 0x3f)
469
470#define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
471
472#define hsc2sector(h,s,c) \
473 (sector(s) - 1 + sectors * ((h) + heads * cylinder(s,c)))
474
Denis Vlasenkoc033d512008-04-17 01:52:28 +0000475static void
476close_dev_fd(void)
477{
478 /* Not really closing, but making sure it is open, and to harmless place */
479 xmove_fd(xopen(bb_dev_null, O_RDONLY), dev_fd);
480}
481
Denis Vlasenkobd852072007-03-19 14:43:38 +0000482/*
Denis Vlasenko270d5d72008-06-29 05:16:45 +0000483 * Return partition name - uses static storage
Denis Vlasenkobd852072007-03-19 14:43:38 +0000484 */
485static const char *
486partname(const char *dev, int pno, int lth)
487{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000488 const char *p;
489 int w, wp;
490 int bufsiz;
491 char *bufp;
492
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000493 bufp = partname_buffer;
494 bufsiz = sizeof(partname_buffer);
Denis Vlasenkobd852072007-03-19 14:43:38 +0000495
496 w = strlen(dev);
497 p = "";
498
499 if (isdigit(dev[w-1]))
500 p = "p";
501
502 /* devfs kludge - note: fdisk partition names are not supposed
503 to equal kernel names, so there is no reason to do this */
504 if (strcmp(dev + w - 4, "disc") == 0) {
505 w -= 4;
506 p = "part";
507 }
508
509 wp = strlen(p);
510
511 if (lth) {
512 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200513 lth-wp-2, w, dev, p, pno);
Denis Vlasenkobd852072007-03-19 14:43:38 +0000514 } else {
515 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
516 }
517 return bufp;
518}
519
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000520static ALWAYS_INLINE struct partition *
Rob Landleyb73451d2006-02-24 16:29:00 +0000521get_part_table(int i)
522{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000523 return ptes[i].part_table;
524}
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000525
526static const char *
Rob Landleyb73451d2006-02-24 16:29:00 +0000527str_units(int n)
528{ /* n==1: use singular */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000529 if (n == 1)
Denis Vlasenkobd852072007-03-19 14:43:38 +0000530 return display_in_cyl_units ? "cylinder" : "sector";
531 return display_in_cyl_units ? "cylinders" : "sectors";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000532}
533
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000534static int
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000535valid_part_table_flag(const char *mbuffer)
536{
Denis Vlasenko834410a2006-11-29 12:00:28 +0000537 return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000538}
539
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200540static void fdisk_fatal(const char *why)
541{
542 if (listing) {
543 close_dev_fd();
544 longjmp(listingbuf, 1);
545 }
546 bb_error_msg_and_die(why, disk_device);
547}
548
549static void
550seek_sector(sector_t secno)
551{
552#if ENABLE_FDISK_SUPPORT_LARGE_DISKS
553 off64_t off = (off64_t)secno * sector_size;
554 if (lseek64(dev_fd, off, SEEK_SET) == (off64_t) -1)
555 fdisk_fatal(unable_to_seek);
556#else
557 uint64_t off = (uint64_t)secno * sector_size;
558 if (off > MAXINT(off_t)
559 || lseek(dev_fd, (off_t)off, SEEK_SET) == (off_t) -1
560 ) {
561 fdisk_fatal(unable_to_seek);
562 }
563#endif
564}
565
Denis Vlasenko834410a2006-11-29 12:00:28 +0000566#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200567/* Read line; return 0 or first printable char */
568static int
569read_line(const char *prompt)
570{
571 int sz;
572
Denys Vlasenko66c5b122011-02-08 05:07:02 +0100573 sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer), /*timeout*/ -1);
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200574 if (sz <= 0)
575 exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
576
577 if (line_buffer[sz-1] == '\n')
578 line_buffer[--sz] = '\0';
579
580 line_ptr = line_buffer;
581 while (*line_ptr != '\0' && (unsigned char)*line_ptr <= ' ')
582 line_ptr++;
583 return *line_ptr;
584}
585
586static void
587set_all_unchanged(void)
588{
589 int i;
590
591 for (i = 0; i < MAXIMUM_PARTS; i++)
592 ptes[i].changed = 0;
593}
594
595static ALWAYS_INLINE void
596set_changed(int i)
597{
598 ptes[i].changed = 1;
599}
600
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000601static ALWAYS_INLINE void
Denis Vlasenko834410a2006-11-29 12:00:28 +0000602write_part_table_flag(char *b)
603{
604 b[510] = 0x55;
605 b[511] = 0xaa;
606}
607
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000608static char
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000609read_nonempty(const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000610{
Denis Vlasenko9764d692008-07-09 21:20:50 +0000611 while (!read_line(mesg))
612 continue;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000613 return *line_ptr;
614}
615
616static char
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000617read_maybe_empty(const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000618{
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000619 if (!read_line(mesg)) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000620 line_ptr = line_buffer;
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000621 line_ptr[0] = '\n';
622 line_ptr[1] = '\0';
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000623 }
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000624 return line_ptr[0];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000625}
626
627static int
Denis Vlasenkobd852072007-03-19 14:43:38 +0000628read_hex(const char *const *sys)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000629{
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000630 unsigned long v;
Rob Landleyb73451d2006-02-24 16:29:00 +0000631 while (1) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000632 read_nonempty("Hex code (type L to list codes): ");
Denys Vlasenkod958e902010-04-06 02:32:26 +0200633 if ((line_ptr[0] | 0x20) == 'l') {
Rob Landleyb73451d2006-02-24 16:29:00 +0000634 list_types(sys);
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000635 continue;
Rob Landleyb73451d2006-02-24 16:29:00 +0000636 }
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000637 v = bb_strtoul(line_ptr, NULL, 16);
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200638 if (v <= 0xff)
639 return v;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000640 }
641}
642
Denis Vlasenko9764d692008-07-09 21:20:50 +0000643static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200644write_sector(sector_t secno, const void *buf)
Denis Vlasenko9764d692008-07-09 21:20:50 +0000645{
646 seek_sector(secno);
647 xwrite(dev_fd, buf, sector_size);
648}
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200649#endif /* FEATURE_FDISK_WRITABLE */
Denis Vlasenko9764d692008-07-09 21:20:50 +0000650
651
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000652#include "fdisk_aix.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000653
Denys Vlasenko36659fd2010-02-05 14:40:23 +0100654struct sun_partition {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000655 unsigned char info[128]; /* Informative text string */
656 unsigned char spare0[14];
657 struct sun_info {
658 unsigned char spare1;
659 unsigned char id;
660 unsigned char spare2;
661 unsigned char flags;
662 } infos[8];
663 unsigned char spare1[246]; /* Boot information etc. */
664 unsigned short rspeed; /* Disk rotational speed */
665 unsigned short pcylcount; /* Physical cylinder count */
666 unsigned short sparecyl; /* extra sects per cylinder */
667 unsigned char spare2[4]; /* More magic... */
668 unsigned short ilfact; /* Interleave factor */
669 unsigned short ncyl; /* Data cylinder count */
670 unsigned short nacyl; /* Alt. cylinder count */
671 unsigned short ntrks; /* Tracks per cylinder */
672 unsigned short nsect; /* Sectors per track */
673 unsigned char spare3[4]; /* Even more magic... */
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000674 struct sun_partinfo {
Eric Andersenacd244a2002-12-11 03:49:33 +0000675 uint32_t start_cylinder;
676 uint32_t num_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000677 } partitions[8];
678 unsigned short magic; /* Magic number */
679 unsigned short csum; /* Label xor'd checksum */
Denys Vlasenko36659fd2010-02-05 14:40:23 +0100680} FIX_ALIASING;
681typedef struct sun_partition sun_partition;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000682#define sunlabel ((sun_partition *)MBRbuffer)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000683STATIC_OSF void bsd_select(void);
684STATIC_OSF void xbsd_print_disklabel(int);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000685#include "fdisk_osf.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000686
Denys Vlasenkod7559c22010-10-30 02:40:08 +0200687STATIC_GPT void gpt_list_table(int xtra);
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200688#include "fdisk_gpt.c"
689
Denis Vlasenko28703012006-12-19 20:32:02 +0000690#if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000691static uint16_t
Denis Vlasenko28703012006-12-19 20:32:02 +0000692fdisk_swap16(uint16_t x)
Rob Landleyb73451d2006-02-24 16:29:00 +0000693{
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000694 return (x << 8) | (x >> 8);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000695}
696
Rob Landley88621d72006-08-29 19:41:06 +0000697static uint32_t
Denis Vlasenko28703012006-12-19 20:32:02 +0000698fdisk_swap32(uint32_t x)
Rob Landleyb73451d2006-02-24 16:29:00 +0000699{
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000700 return (x << 24) |
701 ((x & 0xFF00) << 8) |
702 ((x & 0xFF0000) >> 8) |
703 (x >> 24);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000704}
705#endif
706
Denis Vlasenkobd852072007-03-19 14:43:38 +0000707STATIC_SGI const char *const sgi_sys_types[];
Denis Vlasenko834410a2006-11-29 12:00:28 +0000708STATIC_SGI unsigned sgi_get_num_sectors(int i);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000709STATIC_SGI int sgi_get_sysid(int i);
710STATIC_SGI void sgi_delete_partition(int i);
711STATIC_SGI void sgi_change_sysid(int i, int sys);
712STATIC_SGI void sgi_list_table(int xtra);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000713#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000714STATIC_SGI void sgi_set_xcyl(void);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000715#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000716STATIC_SGI int verify_sgi(int verbose);
717STATIC_SGI void sgi_add_partition(int n, int sys);
718STATIC_SGI void sgi_set_swappartition(int i);
719STATIC_SGI const char *sgi_get_bootfile(void);
720STATIC_SGI void sgi_set_bootfile(const char* aFile);
721STATIC_SGI void create_sgiinfo(void);
722STATIC_SGI void sgi_write_table(void);
723STATIC_SGI void sgi_set_bootpartition(int i);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000724#include "fdisk_sgi.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000725
Denis Vlasenkobd852072007-03-19 14:43:38 +0000726STATIC_SUN const char *const sun_sys_types[];
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000727STATIC_SUN void sun_delete_partition(int i);
728STATIC_SUN void sun_change_sysid(int i, int sys);
729STATIC_SUN void sun_list_table(int xtra);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000730STATIC_SUN void add_sun_partition(int n, int sys);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000731#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000732STATIC_SUN void sun_set_alt_cyl(void);
733STATIC_SUN void sun_set_ncyl(int cyl);
734STATIC_SUN void sun_set_xcyl(void);
735STATIC_SUN void sun_set_ilfact(void);
736STATIC_SUN void sun_set_rspeed(void);
737STATIC_SUN void sun_set_pcylcount(void);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000738#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000739STATIC_SUN void toggle_sunflags(int i, unsigned char mask);
740STATIC_SUN void verify_sun(void);
741STATIC_SUN void sun_write_table(void);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000742#include "fdisk_sun.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000743
Denis Vlasenko9764d692008-07-09 21:20:50 +0000744
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200745static inline_if_little_endian unsigned
Rob Landleyb73451d2006-02-24 16:29:00 +0000746read4_little_endian(const unsigned char *cp)
747{
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200748 uint32_t v;
749 move_from_unaligned32(v, cp);
750 return SWAP_LE32(v);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000751}
752
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200753static sector_t
Rob Landleyb73451d2006-02-24 16:29:00 +0000754get_start_sect(const struct partition *p)
755{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000756 return read4_little_endian(p->start4);
757}
758
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200759static sector_t
760get_nr_sects(const struct partition *p)
761{
762 return read4_little_endian(p->size4);
763}
764
Denis Vlasenko834410a2006-11-29 12:00:28 +0000765#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200766/* start_sect and nr_sects are stored little endian on all machines */
767/* moreover, they are not aligned correctly */
768static inline_if_little_endian void
769store4_little_endian(unsigned char *cp, unsigned val)
770{
771 uint32_t v = SWAP_LE32(val);
772 move_to_unaligned32(cp, v);
773}
774
775static void
776set_start_sect(struct partition *p, unsigned start_sect)
777{
778 store4_little_endian(p->start4, start_sect);
779}
780
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000781static void
Denis Vlasenko28703012006-12-19 20:32:02 +0000782set_nr_sects(struct partition *p, unsigned nr_sects)
Rob Landleyb73451d2006-02-24 16:29:00 +0000783{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000784 store4_little_endian(p->size4, nr_sects);
785}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000786#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000787
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000788/* Allocate a buffer and read a partition table sector */
789static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200790read_pte(struct pte *pe, sector_t offset)
Rob Landleyb73451d2006-02-24 16:29:00 +0000791{
Denys Vlasenkod958e902010-04-06 02:32:26 +0200792 pe->offset_from_dev_start = offset;
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000793 pe->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000794 seek_sector(offset);
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000795 /* xread would make us abort - bad for fdisk -l */
796 if (full_read(dev_fd, pe->sectorbuffer, sector_size) != sector_size)
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000797 fdisk_fatal(unable_to_read);
Denis Vlasenko834410a2006-11-29 12:00:28 +0000798#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000799 pe->changed = 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000800#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000801 pe->part_table = pe->ext_pointer = NULL;
802}
803
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200804static sector_t
Denys Vlasenkod958e902010-04-06 02:32:26 +0200805get_partition_start_from_dev_start(const struct pte *pe)
Rob Landleyb73451d2006-02-24 16:29:00 +0000806{
Denys Vlasenkod958e902010-04-06 02:32:26 +0200807 return pe->offset_from_dev_start + get_start_sect(pe->part_table);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000808}
809
Denis Vlasenko834410a2006-11-29 12:00:28 +0000810#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000811/*
812 * Avoid warning about DOS partitions when no DOS partition was changed.
813 * Here a heuristic "is probably dos partition".
814 * We might also do the opposite and warn in all cases except
815 * for "is probably nondos partition".
816 */
Denis Vlasenko89398812008-01-25 20:18:46 +0000817#ifdef UNUSED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000818static int
Rob Landleyb73451d2006-02-24 16:29:00 +0000819is_dos_partition(int t)
820{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000821 return (t == 1 || t == 4 || t == 6 ||
822 t == 0x0b || t == 0x0c || t == 0x0e ||
823 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
824 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
825 t == 0xc1 || t == 0xc4 || t == 0xc6);
826}
Denis Vlasenko89398812008-01-25 20:18:46 +0000827#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000828
829static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000830menu(void)
831{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000832 puts("Command Action");
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000833 if (LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000834 puts("a\ttoggle a read only flag"); /* sun */
835 puts("b\tedit bsd disklabel");
836 puts("c\ttoggle the mountable flag"); /* sun */
837 puts("d\tdelete a partition");
838 puts("l\tlist known partition types");
839 puts("n\tadd a new partition");
840 puts("o\tcreate a new empty DOS partition table");
841 puts("p\tprint the partition table");
842 puts("q\tquit without saving changes");
843 puts("s\tcreate a new empty Sun disklabel"); /* sun */
844 puts("t\tchange a partition's system id");
845 puts("u\tchange display/entry units");
846 puts("v\tverify the partition table");
847 puts("w\twrite table to disk and exit");
Denis Vlasenko834410a2006-11-29 12:00:28 +0000848#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkobd852072007-03-19 14:43:38 +0000849 puts("x\textra functionality (experts only)");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000850#endif
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000851 } else if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000852 puts("a\tselect bootable partition"); /* sgi flavour */
853 puts("b\tedit bootfile entry"); /* sgi */
854 puts("c\tselect sgi swap partition"); /* sgi flavour */
855 puts("d\tdelete a partition");
856 puts("l\tlist known partition types");
857 puts("n\tadd a new partition");
858 puts("o\tcreate a new empty DOS partition table");
859 puts("p\tprint the partition table");
860 puts("q\tquit without saving changes");
861 puts("s\tcreate a new empty Sun disklabel"); /* sun */
862 puts("t\tchange a partition's system id");
863 puts("u\tchange display/entry units");
864 puts("v\tverify the partition table");
865 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000866 } else if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000867 puts("o\tcreate a new empty DOS partition table");
868 puts("q\tquit without saving changes");
869 puts("s\tcreate a new empty Sun disklabel"); /* sun */
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200870 } else if (LABEL_IS_GPT) {
871 puts("o\tcreate a new empty DOS partition table");
872 puts("p\tprint the partition table");
873 puts("q\tquit without saving changes");
874 puts("s\tcreate a new empty Sun disklabel"); /* sun */
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000875 } else {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000876 puts("a\ttoggle a bootable flag");
877 puts("b\tedit bsd disklabel");
878 puts("c\ttoggle the dos compatibility flag");
879 puts("d\tdelete a partition");
880 puts("l\tlist known partition types");
881 puts("n\tadd a new partition");
882 puts("o\tcreate a new empty DOS partition table");
883 puts("p\tprint the partition table");
884 puts("q\tquit without saving changes");
885 puts("s\tcreate a new empty Sun disklabel"); /* sun */
886 puts("t\tchange a partition's system id");
887 puts("u\tchange display/entry units");
888 puts("v\tverify the partition table");
889 puts("w\twrite table to disk and exit");
Denis Vlasenko834410a2006-11-29 12:00:28 +0000890#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkobd852072007-03-19 14:43:38 +0000891 puts("x\textra functionality (experts only)");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000892#endif
893 }
894}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000895#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000896
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000897
Denis Vlasenko834410a2006-11-29 12:00:28 +0000898#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000899static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000900xmenu(void)
901{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000902 puts("Command Action");
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000903 if (LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000904 puts("a\tchange number of alternate cylinders"); /*sun*/
905 puts("c\tchange number of cylinders");
906 puts("d\tprint the raw data in the partition table");
907 puts("e\tchange number of extra sectors per cylinder");/*sun*/
908 puts("h\tchange number of heads");
909 puts("i\tchange interleave factor"); /*sun*/
910 puts("o\tchange rotation speed (rpm)"); /*sun*/
911 puts("p\tprint the partition table");
912 puts("q\tquit without saving changes");
913 puts("r\treturn to main menu");
914 puts("s\tchange number of sectors/track");
915 puts("v\tverify the partition table");
916 puts("w\twrite table to disk and exit");
917 puts("y\tchange number of physical cylinders"); /*sun*/
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000918 } else if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000919 puts("b\tmove beginning of data in a partition"); /* !sun */
920 puts("c\tchange number of cylinders");
921 puts("d\tprint the raw data in the partition table");
922 puts("e\tlist extended partitions"); /* !sun */
923 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
924 puts("h\tchange number of heads");
925 puts("p\tprint the partition table");
926 puts("q\tquit without saving changes");
927 puts("r\treturn to main menu");
928 puts("s\tchange number of sectors/track");
929 puts("v\tverify the partition table");
930 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000931 } else if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000932 puts("b\tmove beginning of data in a partition"); /* !sun */
933 puts("c\tchange number of cylinders");
934 puts("d\tprint the raw data in the partition table");
935 puts("e\tlist extended partitions"); /* !sun */
936 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
937 puts("h\tchange number of heads");
938 puts("p\tprint the partition table");
939 puts("q\tquit without saving changes");
940 puts("r\treturn to main menu");
941 puts("s\tchange number of sectors/track");
942 puts("v\tverify the partition table");
943 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000944 } else {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000945 puts("b\tmove beginning of data in a partition"); /* !sun */
946 puts("c\tchange number of cylinders");
947 puts("d\tprint the raw data in the partition table");
948 puts("e\tlist extended partitions"); /* !sun */
949 puts("f\tfix partition order"); /* !sun, !aix, !sgi */
Denis Vlasenko834410a2006-11-29 12:00:28 +0000950#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenkobd852072007-03-19 14:43:38 +0000951 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000952#endif
Denis Vlasenkobd852072007-03-19 14:43:38 +0000953 puts("h\tchange number of heads");
954 puts("p\tprint the partition table");
955 puts("q\tquit without saving changes");
956 puts("r\treturn to main menu");
957 puts("s\tchange number of sectors/track");
958 puts("v\tverify the partition table");
959 puts("w\twrite table to disk and exit");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000960 }
961}
962#endif /* ADVANCED mode */
963
Denis Vlasenko834410a2006-11-29 12:00:28 +0000964#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenkobd852072007-03-19 14:43:38 +0000965static const char *const *
Rob Landleyb73451d2006-02-24 16:29:00 +0000966get_sys_types(void)
967{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000968 return (
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000969 LABEL_IS_SUN ? sun_sys_types :
970 LABEL_IS_SGI ? sgi_sys_types :
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000971 i386_sys_types);
972}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000973#else
974#define get_sys_types() i386_sys_types
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200975#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000976
Denis Vlasenkobd852072007-03-19 14:43:38 +0000977static const char *
978partition_type(unsigned char type)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000979{
980 int i;
Denis Vlasenkobd852072007-03-19 14:43:38 +0000981 const char *const *types = get_sys_types();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000982
Denis Vlasenkobd852072007-03-19 14:43:38 +0000983 for (i = 0; types[i]; i++)
984 if ((unsigned char)types[i][0] == type)
985 return types[i] + 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000986
Denis Vlasenkobd852072007-03-19 14:43:38 +0000987 return "Unknown";
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000988}
989
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200990static int
991is_cleared_partition(const struct partition *p)
992{
993 /* We consider partition "cleared" only if it has only zeros */
994 const char *cp = (const char *)p;
995 int cnt = sizeof(*p);
996 char bits = 0;
997 while (--cnt >= 0)
998 bits |= *cp++;
999 return (bits == 0);
1000}
1001
1002static void
1003clear_partition(struct partition *p)
1004{
1005 if (p)
1006 memset(p, 0, sizeof(*p));
1007}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001008
Denis Vlasenko834410a2006-11-29 12:00:28 +00001009#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001010static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001011get_sysid(int i)
1012{
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001013 return LABEL_IS_SUN ? sunlabel->infos[i].id :
1014 (LABEL_IS_SGI ? sgi_get_sysid(i) :
1015 ptes[i].part_table->sys_ind);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001016}
1017
Denis Vlasenkobd852072007-03-19 14:43:38 +00001018static void
1019list_types(const char *const *sys)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001020{
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00001021 enum { COLS = 3 };
1022
1023 unsigned last[COLS];
1024 unsigned done, next, size;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001025 int i;
1026
Denis Vlasenko9764d692008-07-09 21:20:50 +00001027 for (size = 0; sys[size]; size++)
1028 continue;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001029
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00001030 done = 0;
1031 for (i = COLS-1; i >= 0; i--) {
1032 done += (size + i - done) / (i + 1);
1033 last[COLS-1 - i] = done;
1034 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001035
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00001036 i = done = next = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001037 do {
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00001038 printf("%c%2x %-22.22s", i ? ' ' : '\n',
Denis Vlasenkobd852072007-03-19 14:43:38 +00001039 (unsigned char)sys[next][0],
1040 sys[next] + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001041 next = last[i++] + done;
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00001042 if (i >= COLS || next >= last[i]) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001043 i = 0;
1044 next = ++done;
1045 }
1046 } while (done < last[0]);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001047 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001048}
1049
Denys Vlasenkod958e902010-04-06 02:32:26 +02001050#define set_hsc(h, s, c, sector) do \
1051{ \
1052 s = sector % g_sectors + 1; \
1053 sector /= g_sectors; \
1054 h = sector % g_heads; \
1055 sector /= g_heads; \
1056 c = sector & 0xff; \
1057 s |= (sector >> 2) & 0xc0; \
1058} while (0)
1059
1060static void set_hsc_start_end(struct partition *p, sector_t start, sector_t stop)
1061{
1062 if (dos_compatible_flag && (start / (g_sectors * g_heads) > 1023))
1063 start = g_heads * g_sectors * 1024 - 1;
1064 set_hsc(p->head, p->sector, p->cyl, start);
1065
1066 if (dos_compatible_flag && (stop / (g_sectors * g_heads) > 1023))
1067 stop = g_heads * g_sectors * 1024 - 1;
1068 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
1069}
1070
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001071static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001072set_partition(int i, int doext, sector_t start, sector_t stop, int sysid)
Rob Landleyb73451d2006-02-24 16:29:00 +00001073{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001074 struct partition *p;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001075 sector_t offset;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001076
1077 if (doext) {
1078 p = ptes[i].ext_pointer;
1079 offset = extended_offset;
1080 } else {
1081 p = ptes[i].part_table;
Denys Vlasenkod958e902010-04-06 02:32:26 +02001082 offset = ptes[i].offset_from_dev_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001083 }
1084 p->boot_ind = 0;
1085 p->sys_ind = sysid;
1086 set_start_sect(p, start - offset);
1087 set_nr_sects(p, stop - start + 1);
Denys Vlasenkod958e902010-04-06 02:32:26 +02001088 set_hsc_start_end(p, start, stop);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001089 ptes[i].changed = 1;
1090}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001091#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001092
1093static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001094warn_geometry(void)
1095{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001096 if (g_heads && g_sectors && g_cylinders)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001097 return 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001098
Denis Vlasenkobd852072007-03-19 14:43:38 +00001099 printf("Unknown value(s) for:");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001100 if (!g_heads)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001101 printf(" heads");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001102 if (!g_sectors)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001103 printf(" sectors");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001104 if (!g_cylinders)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001105 printf(" cylinders");
1106 printf(
Denis Vlasenko834410a2006-11-29 12:00:28 +00001107#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenkobd852072007-03-19 14:43:38 +00001108 " (settable in the extra functions menu)"
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001109#endif
Denis Vlasenkobd852072007-03-19 14:43:38 +00001110 "\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001111 return 1;
1112}
1113
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +00001114static void
1115update_units(void)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001116{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001117 int cyl_units = g_heads * g_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001118
1119 if (display_in_cyl_units && cyl_units)
1120 units_per_sector = cyl_units;
1121 else
1122 units_per_sector = 1; /* in sectors */
1123}
1124
Denis Vlasenko834410a2006-11-29 12:00:28 +00001125#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001126static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001127warn_cylinders(void)
1128{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001129 if (LABEL_IS_DOS && g_cylinders > 1024 && !nowarn)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001130 printf("\n"
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001131"The number of cylinders for this disk is set to %u.\n"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001132"There is nothing wrong with that, but this is larger than 1024,\n"
1133"and could in certain setups cause problems with:\n"
1134"1) software that runs at boot time (e.g., old versions of LILO)\n"
1135"2) booting and partitioning software from other OSs\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001136" (e.g., DOS FDISK, OS/2 FDISK)\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001137 g_cylinders);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001138}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001139#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001140
1141static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001142read_extended(int ext)
1143{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001144 int i;
1145 struct pte *pex;
1146 struct partition *p, *q;
1147
1148 ext_index = ext;
1149 pex = &ptes[ext];
1150 pex->ext_pointer = pex->part_table;
1151
1152 p = pex->part_table;
1153 if (!get_start_sect(p)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001154 printf("Bad offset in primary extended partition\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001155 return;
1156 }
1157
Rob Landleyb73451d2006-02-24 16:29:00 +00001158 while (IS_EXTENDED(p->sys_ind)) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001159 struct pte *pe = &ptes[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001160
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001161 if (g_partitions >= MAXIMUM_PARTS) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001162 /* This is not a Linux restriction, but
1163 this program uses arrays of size MAXIMUM_PARTS.
Denis Vlasenko89f0b342006-11-18 22:04:09 +00001164 Do not try to 'improve' this test. */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001165 struct pte *pre = &ptes[g_partitions - 1];
Denis Vlasenko834410a2006-11-29 12:00:28 +00001166#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001167 printf("Warning: deleting partitions after %u\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001168 g_partitions);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001169 pre->changed = 1;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001170#endif
1171 clear_partition(pre->ext_pointer);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001172 return;
1173 }
1174
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001175 read_pte(pe, extended_offset + get_start_sect(p));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001176
1177 if (!extended_offset)
1178 extended_offset = get_start_sect(p);
1179
1180 q = p = pt_offset(pe->sectorbuffer, 0);
1181 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001182 if (IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001183 if (pe->ext_pointer)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001184 printf("Warning: extra link "
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001185 "pointer in partition table"
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001186 " %u\n", g_partitions + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001187 else
1188 pe->ext_pointer = p;
1189 } else if (p->sys_ind) {
1190 if (pe->part_table)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001191 printf("Warning: ignoring extra "
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001192 "data in partition table"
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001193 " %u\n", g_partitions + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001194 else
1195 pe->part_table = p;
1196 }
1197 }
1198
1199 /* very strange code here... */
1200 if (!pe->part_table) {
1201 if (q != pe->ext_pointer)
1202 pe->part_table = q;
1203 else
1204 pe->part_table = q + 1;
1205 }
1206 if (!pe->ext_pointer) {
1207 if (q != pe->part_table)
1208 pe->ext_pointer = q;
1209 else
1210 pe->ext_pointer = q + 1;
1211 }
1212
1213 p = pe->ext_pointer;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001214 g_partitions++;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001215 }
1216
Denis Vlasenko834410a2006-11-29 12:00:28 +00001217#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001218 /* remove empty links */
1219 remove:
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001220 for (i = 4; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001221 struct pte *pe = &ptes[i];
1222
Denis Vlasenkobd852072007-03-19 14:43:38 +00001223 if (!get_nr_sects(pe->part_table)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001224 && (g_partitions > 5 || ptes[4].part_table->sys_ind)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001225 ) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001226 printf("Omitting empty partition (%u)\n", i+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001227 delete_partition(i);
1228 goto remove; /* numbering changed */
1229 }
1230 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001231#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001232}
1233
Denis Vlasenko834410a2006-11-29 12:00:28 +00001234#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001235static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001236create_doslabel(void)
1237{
Denis Vlasenkobd852072007-03-19 14:43:38 +00001238 printf(msg_building_new_label, "DOS disklabel");
Rob Landley5527b912006-02-25 03:46:10 +00001239
Denis Vlasenko4437d192008-04-17 00:12:10 +00001240 current_label_type = LABEL_DOS;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001241#if ENABLE_FEATURE_OSF_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001242 possibly_osf_label = 0;
1243#endif
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001244 g_partitions = 4;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001245
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001246 memset(&MBRbuffer[510 - 4*16], 0, 4*16);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001247 write_part_table_flag(MBRbuffer);
1248 extended_offset = 0;
1249 set_all_unchanged();
1250 set_changed(0);
Denis Vlasenko4437d192008-04-17 00:12:10 +00001251 get_boot(CREATE_EMPTY_DOS);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001252}
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001253#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001254
1255static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001256get_sectorsize(void)
1257{
Rob Landley736e5252006-02-25 03:36:00 +00001258 if (!user_set_sector_size) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001259 int arg;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001260 if (ioctl(dev_fd, BLKSSZGET, &arg) == 0)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001261 sector_size = arg;
1262 if (sector_size != DEFAULT_SECTOR_SIZE)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001263 printf("Note: sector size is %u "
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +00001264 "(not " DEFAULT_SECTOR_SIZE_STR ")\n",
1265 sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001266 }
1267}
1268
Rob Landley88621d72006-08-29 19:41:06 +00001269static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001270get_kernel_geometry(void)
1271{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001272 struct hd_geometry geometry;
1273
Denis Vlasenko4437d192008-04-17 00:12:10 +00001274 if (!ioctl(dev_fd, HDIO_GETGEO, &geometry)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001275 kern_heads = geometry.heads;
1276 kern_sectors = geometry.sectors;
1277 /* never use geometry.cylinders - it is truncated */
1278 }
1279}
1280
1281static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001282get_partition_table_geometry(void)
1283{
"Vladimir N. Oleynik"a972c872005-12-02 10:06:04 +00001284 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001285 struct partition *p;
1286 int i, h, s, hh, ss;
1287 int first = 1;
1288 int bad = 0;
1289
Eric Andersen3496fdc2006-01-30 23:09:20 +00001290 if (!(valid_part_table_flag((char*)bufp)))
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001291 return;
1292
1293 hh = ss = 0;
Rob Landleyb73451d2006-02-24 16:29:00 +00001294 for (i = 0; i < 4; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001295 p = pt_offset(bufp, i);
1296 if (p->sys_ind != 0) {
1297 h = p->end_head + 1;
1298 s = (p->end_sector & 077);
1299 if (first) {
1300 hh = h;
1301 ss = s;
1302 first = 0;
1303 } else if (hh != h || ss != s)
1304 bad = 1;
1305 }
1306 }
1307
1308 if (!first && !bad) {
1309 pt_heads = hh;
1310 pt_sectors = ss;
1311 }
1312}
1313
Rob Landleyb73451d2006-02-24 16:29:00 +00001314static void
1315get_geometry(void)
1316{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001317 int sec_fac;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001318
1319 get_sectorsize();
1320 sec_fac = sector_size / 512;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001321#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001322 guess_device_type();
1323#endif
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001324 g_heads = g_cylinders = g_sectors = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001325 kern_heads = kern_sectors = 0;
1326 pt_heads = pt_sectors = 0;
1327
1328 get_kernel_geometry();
1329 get_partition_table_geometry();
1330
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001331 g_heads = user_heads ? user_heads :
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001332 pt_heads ? pt_heads :
1333 kern_heads ? kern_heads : 255;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001334 g_sectors = user_sectors ? user_sectors :
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001335 pt_sectors ? pt_sectors :
1336 kern_sectors ? kern_sectors : 63;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001337 total_number_of_sectors = bb_BLKGETSIZE_sectors(dev_fd);
Eric Andersen040f4402003-07-30 08:40:37 +00001338
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001339 sector_offset = 1;
1340 if (dos_compatible_flag)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001341 sector_offset = g_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001342
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001343 g_cylinders = total_number_of_sectors / (g_heads * g_sectors * sec_fac);
1344 if (!g_cylinders)
1345 g_cylinders = user_cylinders;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001346}
1347
1348/*
Denis Vlasenko4437d192008-04-17 00:12:10 +00001349 * Opens disk_device and optionally reads MBR.
Kevin Cernekeeccb07042010-10-25 02:00:24 +02001350 * If what == OPEN_MAIN:
1351 * Open device, read MBR. Abort program on short read. Create empty
1352 * disklabel if the on-disk structure is invalid (WRITABLE mode).
1353 * If what == TRY_ONLY:
1354 * Open device, read MBR. Return an error if anything is out of place.
1355 * Do not create an empty disklabel. This is used for the "list"
1356 * operations: "fdisk -l /dev/sda" and "fdisk -l" (all devices).
1357 * If what == CREATE_EMPTY_*:
1358 * This means that get_boot() was called recursively from create_*label().
1359 * Do not re-open the device; just set up the ptes array and print
1360 * geometry warnings.
1361 *
Denis Vlasenko4437d192008-04-17 00:12:10 +00001362 * Returns:
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001363 * -1: no 0xaa55 flag present (possibly entire disk BSD)
1364 * 0: found or created label
1365 * 1: I/O error
1366 */
Denis Vlasenko85c24712008-03-17 09:04:04 +00001367#if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE
1368static int get_boot(enum action what)
1369#else
1370static int get_boot(void)
1371#define get_boot(what) get_boot()
1372#endif
Rob Landleyb73451d2006-02-24 16:29:00 +00001373{
Denis Vlasenko4437d192008-04-17 00:12:10 +00001374 int i, fd;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001375
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001376 g_partitions = 4;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001377 for (i = 0; i < 4; i++) {
1378 struct pte *pe = &ptes[i];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001379 pe->part_table = pt_offset(MBRbuffer, i);
1380 pe->ext_pointer = NULL;
Denys Vlasenkod958e902010-04-06 02:32:26 +02001381 pe->offset_from_dev_start = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001382 pe->sectorbuffer = MBRbuffer;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001383#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko4437d192008-04-17 00:12:10 +00001384 pe->changed = (what == CREATE_EMPTY_DOS);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001385#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001386 }
1387
Denis Vlasenko834410a2006-11-29 12:00:28 +00001388#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko4437d192008-04-17 00:12:10 +00001389// ALERT! highly idiotic design!
1390// We end up here when we call get_boot() recursively
1391// via get_boot() [table is bad] -> create_doslabel() -> get_boot(CREATE_EMPTY_DOS).
1392// or get_boot() [table is bad] -> create_sunlabel() -> get_boot(CREATE_EMPTY_SUN).
1393// (just factor out re-init of ptes[0,1,2,3] in a separate fn instead?)
1394// So skip opening device _again_...
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001395 if (what == CREATE_EMPTY_DOS IF_FEATURE_SUN_LABEL(|| what == CREATE_EMPTY_SUN))
Denis Vlasenko4437d192008-04-17 00:12:10 +00001396 goto created_table;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001397
Denis Vlasenko4437d192008-04-17 00:12:10 +00001398 fd = open(disk_device, (option_mask32 & OPT_l) ? O_RDONLY : O_RDWR);
1399
Denis Vlasenkobd852072007-03-19 14:43:38 +00001400 if (fd < 0) {
1401 fd = open(disk_device, O_RDONLY);
1402 if (fd < 0) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001403 if (what == TRY_ONLY)
Rob Landleyb73451d2006-02-24 16:29:00 +00001404 return 1;
1405 fdisk_fatal(unable_to_open);
Denis Vlasenko4437d192008-04-17 00:12:10 +00001406 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00001407 printf("'%s' is opened for read only\n", disk_device);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001408 }
Denis Vlasenkoc033d512008-04-17 01:52:28 +00001409 xmove_fd(fd, dev_fd);
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +00001410 if (512 != full_read(dev_fd, MBRbuffer, 512)) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001411 if (what == TRY_ONLY) {
Denis Vlasenkoc033d512008-04-17 01:52:28 +00001412 close_dev_fd();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001413 return 1;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001414 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001415 fdisk_fatal(unable_to_read);
1416 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001417#else
Denis Vlasenkobd852072007-03-19 14:43:38 +00001418 fd = open(disk_device, O_RDONLY);
1419 if (fd < 0)
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001420 return 1;
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +00001421 if (512 != full_read(fd, MBRbuffer, 512)) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001422 close(fd);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001423 return 1;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001424 }
1425 xmove_fd(fd, dev_fd);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001426#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001427
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001428 get_geometry();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001429 update_units();
1430
Denis Vlasenko834410a2006-11-29 12:00:28 +00001431#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001432 if (check_sun_label())
1433 return 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001434#endif
Denis Vlasenko834410a2006-11-29 12:00:28 +00001435#if ENABLE_FEATURE_SGI_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001436 if (check_sgi_label())
1437 return 0;
1438#endif
Denis Vlasenko834410a2006-11-29 12:00:28 +00001439#if ENABLE_FEATURE_AIX_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001440 if (check_aix_label())
1441 return 0;
1442#endif
Kevin Cernekeeccb07042010-10-25 02:00:24 +02001443#if ENABLE_FEATURE_GPT_LABEL
1444 if (check_gpt_label())
1445 return 0;
1446#endif
Denis Vlasenko834410a2006-11-29 12:00:28 +00001447#if ENABLE_FEATURE_OSF_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001448 if (check_osf_label()) {
1449 possibly_osf_label = 1;
1450 if (!valid_part_table_flag(MBRbuffer)) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001451 current_label_type = LABEL_OSF;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001452 return 0;
1453 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001454 printf("This disk has both DOS and BSD magic.\n"
1455 "Give the 'b' command to go to BSD mode.\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001456 }
1457#endif
1458
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001459#if !ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko4437d192008-04-17 00:12:10 +00001460 if (!valid_part_table_flag(MBRbuffer))
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001461 return -1;
1462#else
Denis Vlasenko4437d192008-04-17 00:12:10 +00001463 if (!valid_part_table_flag(MBRbuffer)) {
1464 if (what == OPEN_MAIN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001465 printf("Device contains neither a valid DOS "
Kevin Cernekeeccb07042010-10-25 02:00:24 +02001466 "partition table, nor Sun, SGI, OSF or GPT "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001467 "disklabel\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001468#ifdef __sparc__
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001469 IF_FEATURE_SUN_LABEL(create_sunlabel();)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001470#else
1471 create_doslabel();
1472#endif
1473 return 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001474 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00001475 /* TRY_ONLY: */
1476 return -1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001477 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00001478 created_table:
1479#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001480
Denis Vlasenko4437d192008-04-17 00:12:10 +00001481
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001482 IF_FEATURE_FDISK_WRITABLE(warn_cylinders();)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001483 warn_geometry();
1484
1485 for (i = 0; i < 4; i++) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001486 if (IS_EXTENDED(ptes[i].part_table->sys_ind)) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001487 if (g_partitions != 4)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001488 printf("Ignoring extra extended "
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001489 "partition %u\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001490 else
1491 read_extended(i);
1492 }
1493 }
1494
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001495 for (i = 3; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001496 struct pte *pe = &ptes[i];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001497 if (!valid_part_table_flag(pe->sectorbuffer)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001498 printf("Warning: invalid flag 0x%02x,0x%02x of partition "
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001499 "table %u will be corrected by w(rite)\n",
Denis Vlasenko834410a2006-11-29 12:00:28 +00001500 pe->sectorbuffer[510],
1501 pe->sectorbuffer[511],
1502 i + 1);
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001503 IF_FEATURE_FDISK_WRITABLE(pe->changed = 1;)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001504 }
1505 }
1506
1507 return 0;
1508}
1509
Denis Vlasenko834410a2006-11-29 12:00:28 +00001510#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001511/*
1512 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
1513 * If the user hits Enter, DFLT is returned.
1514 * Answers like +10 are interpreted as offsets from BASE.
1515 *
1516 * There is no default if DFLT is not between LOW and HIGH.
1517 */
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001518static sector_t
1519read_int(sector_t low, sector_t dflt, sector_t high, sector_t base, const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001520{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001521 sector_t value;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001522 int default_ok = 1;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001523 const char *fmt = "%s (%u-%u, default %u): ";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001524
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001525 if (dflt < low || dflt > high) {
1526 fmt = "%s (%u-%u): ";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001527 default_ok = 0;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001528 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001529
1530 while (1) {
1531 int use_default = default_ok;
1532
1533 /* ask question and read answer */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001534 do {
1535 printf(fmt, mesg, low, high, dflt);
1536 read_maybe_empty("");
1537 } while (*line_ptr != '\n' && !isdigit(*line_ptr)
1538 && *line_ptr != '-' && *line_ptr != '+');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001539
Eric Andersen84bdea82004-05-19 10:49:17 +00001540 if (*line_ptr == '+' || *line_ptr == '-') {
Rob Landleyb73451d2006-02-24 16:29:00 +00001541 int minus = (*line_ptr == '-');
1542 int absolute = 0;
Eric Andersenc48d49a2003-07-03 10:02:32 +00001543
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001544 value = atoi(line_ptr + 1);
Eric Andersenc48d49a2003-07-03 10:02:32 +00001545
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001546 /* (1) if 2nd char is digit, use_default = 0.
1547 * (2) move line_ptr to first non-digit. */
Rob Landleyb73451d2006-02-24 16:29:00 +00001548 while (isdigit(*++line_ptr))
1549 use_default = 0;
Eric Andersen84bdea82004-05-19 10:49:17 +00001550
Rob Landleyb73451d2006-02-24 16:29:00 +00001551 switch (*line_ptr) {
1552 case 'c':
1553 case 'C':
1554 if (!display_in_cyl_units)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001555 value *= g_heads * g_sectors;
Rob Landleyb73451d2006-02-24 16:29:00 +00001556 break;
1557 case 'K':
1558 absolute = 1024;
1559 break;
1560 case 'k':
1561 absolute = 1000;
1562 break;
1563 case 'm':
1564 case 'M':
1565 absolute = 1000000;
1566 break;
1567 case 'g':
1568 case 'G':
1569 absolute = 1000000000;
1570 break;
1571 default:
1572 break;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001573 }
Rob Landleyb73451d2006-02-24 16:29:00 +00001574 if (absolute) {
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001575 ullong bytes;
Rob Landleyb73451d2006-02-24 16:29:00 +00001576 unsigned long unit;
1577
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001578 bytes = (ullong) value * absolute;
Rob Landleyb73451d2006-02-24 16:29:00 +00001579 unit = sector_size * units_per_sector;
1580 bytes += unit/2; /* round */
1581 bytes /= unit;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001582 value = bytes;
Rob Landleyb73451d2006-02-24 16:29:00 +00001583 }
1584 if (minus)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001585 value = -value;
1586 value += base;
Eric Andersen84bdea82004-05-19 10:49:17 +00001587 } else {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001588 value = atoi(line_ptr);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001589 while (isdigit(*line_ptr)) {
1590 line_ptr++;
1591 use_default = 0;
1592 }
1593 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001594 if (use_default) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001595 value = dflt;
1596 printf("Using default value %u\n", value);
Denis Vlasenkobd852072007-03-19 14:43:38 +00001597 }
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001598 if (value >= low && value <= high)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001599 break;
Denis Vlasenkobd852072007-03-19 14:43:38 +00001600 printf("Value is out of range\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001601 }
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001602 return value;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001603}
1604
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001605static unsigned
1606get_partition(int warn, unsigned max)
Rob Landleyb73451d2006-02-24 16:29:00 +00001607{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001608 struct pte *pe;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001609 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001610
Denis Vlasenkobd852072007-03-19 14:43:38 +00001611 i = read_int(1, 0, max, 0, "Partition number") - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001612 pe = &ptes[i];
1613
1614 if (warn) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001615 if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind)
1616 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
1617 || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
1618 ) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001619 printf("Warning: partition %u has empty type\n", i+1);
Rob Landley5527b912006-02-25 03:46:10 +00001620 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001621 }
1622 return i;
1623}
1624
1625static int
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001626get_existing_partition(int warn, unsigned max)
Rob Landleyb73451d2006-02-24 16:29:00 +00001627{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001628 int pno = -1;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001629 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001630
1631 for (i = 0; i < max; i++) {
1632 struct pte *pe = &ptes[i];
1633 struct partition *p = pe->part_table;
1634
1635 if (p && !is_cleared_partition(p)) {
1636 if (pno >= 0)
1637 goto not_unique;
1638 pno = i;
1639 }
1640 }
1641 if (pno >= 0) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001642 printf("Selected partition %u\n", pno+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001643 return pno;
1644 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001645 printf("No partition is defined yet!\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001646 return -1;
1647
1648 not_unique:
1649 return get_partition(warn, max);
1650}
1651
1652static int
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001653get_nonexisting_partition(int warn, unsigned max)
Rob Landleyb73451d2006-02-24 16:29:00 +00001654{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001655 int pno = -1;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001656 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001657
1658 for (i = 0; i < max; i++) {
1659 struct pte *pe = &ptes[i];
1660 struct partition *p = pe->part_table;
1661
1662 if (p && is_cleared_partition(p)) {
1663 if (pno >= 0)
1664 goto not_unique;
1665 pno = i;
1666 }
1667 }
1668 if (pno >= 0) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001669 printf("Selected partition %u\n", pno+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001670 return pno;
1671 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001672 printf("All primary partitions have been defined already!\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001673 return -1;
1674
1675 not_unique:
1676 return get_partition(warn, max);
1677}
1678
1679
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001680static void
1681change_units(void)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001682{
1683 display_in_cyl_units = !display_in_cyl_units;
1684 update_units();
Denis Vlasenkobd852072007-03-19 14:43:38 +00001685 printf("Changing display/entry units to %s\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001686 str_units(PLURAL));
1687}
1688
1689static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001690toggle_active(int i)
1691{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001692 struct pte *pe = &ptes[i];
1693 struct partition *p = pe->part_table;
1694
Rob Landleyb73451d2006-02-24 16:29:00 +00001695 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001696 printf("WARNING: Partition %u is an extended partition\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001697 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1698 pe->changed = 1;
1699}
1700
1701static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001702toggle_dos_compatibility_flag(void)
1703{
Denis Vlasenkocdf62772008-03-17 08:42:43 +00001704 dos_compatible_flag = 1 - dos_compatible_flag;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001705 if (dos_compatible_flag) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001706 sector_offset = g_sectors;
Denis Vlasenkobd852072007-03-19 14:43:38 +00001707 printf("DOS Compatibility flag is set\n");
1708 } else {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001709 sector_offset = 1;
Denis Vlasenkobd852072007-03-19 14:43:38 +00001710 printf("DOS Compatibility flag is not set\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001711 }
1712}
1713
1714static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001715delete_partition(int i)
1716{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001717 struct pte *pe = &ptes[i];
1718 struct partition *p = pe->part_table;
1719 struct partition *q = pe->ext_pointer;
1720
1721/* Note that for the fifth partition (i == 4) we don't actually
1722 * decrement partitions.
1723 */
1724
1725 if (warn_geometry())
1726 return; /* C/H/S not set */
1727 pe->changed = 1;
1728
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001729 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001730 sun_delete_partition(i);
1731 return;
1732 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001733 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001734 sgi_delete_partition(i);
1735 return;
1736 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001737
1738 if (i < 4) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001739 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001740 g_partitions = 4;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001741 ptes[ext_index].ext_pointer = NULL;
1742 extended_offset = 0;
1743 }
1744 clear_partition(p);
1745 return;
1746 }
1747
1748 if (!q->sys_ind && i > 4) {
1749 /* the last one in the chain - just delete */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001750 --g_partitions;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001751 --i;
1752 clear_partition(ptes[i].ext_pointer);
1753 ptes[i].changed = 1;
1754 } else {
1755 /* not the last one - further ones will be moved down */
1756 if (i > 4) {
1757 /* delete this link in the chain */
1758 p = ptes[i-1].ext_pointer;
1759 *p = *q;
1760 set_start_sect(p, get_start_sect(q));
1761 set_nr_sects(p, get_nr_sects(q));
1762 ptes[i-1].changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001763 } else if (g_partitions > 5) { /* 5 will be moved to 4 */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001764 /* the first logical in a longer chain */
1765 pe = &ptes[5];
1766
1767 if (pe->part_table) /* prevent SEGFAULT */
1768 set_start_sect(pe->part_table,
Denys Vlasenkod958e902010-04-06 02:32:26 +02001769 get_partition_start_from_dev_start(pe) -
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001770 extended_offset);
Denys Vlasenkod958e902010-04-06 02:32:26 +02001771 pe->offset_from_dev_start = extended_offset;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001772 pe->changed = 1;
1773 }
1774
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001775 if (g_partitions > 5) {
1776 g_partitions--;
1777 while (i < g_partitions) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001778 ptes[i] = ptes[i+1];
1779 i++;
1780 }
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001781 } else {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001782 /* the only logical: clear only */
1783 clear_partition(ptes[i].part_table);
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001784 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001785 }
1786}
1787
1788static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001789change_sysid(void)
1790{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001791 int i, sys, origsys;
1792 struct partition *p;
1793
Eric Andersen040f4402003-07-30 08:40:37 +00001794 /* If sgi_label then don't use get_existing_partition,
1795 let the user select a partition, since get_existing_partition()
1796 only works for Linux like partition tables. */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001797 if (!LABEL_IS_SGI) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001798 i = get_existing_partition(0, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00001799 } else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001800 i = get_partition(0, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00001801 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001802 if (i == -1)
1803 return;
1804 p = ptes[i].part_table;
1805 origsys = sys = get_sysid(i);
1806
1807 /* if changing types T to 0 is allowed, then
1808 the reverse change must be allowed, too */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001809 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001810 printf("Partition %u does not exist yet!\n", i + 1);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001811 return;
1812 }
1813 while (1) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001814 sys = read_hex(get_sys_types());
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001815
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001816 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001817 printf("Type 0 means free space to many systems\n"
Rob Landleyb73451d2006-02-24 16:29:00 +00001818 "(but not to Linux). Having partitions of\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001819 "type 0 is probably unwise.\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001820 /* break; */
1821 }
1822
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001823 if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001824 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001825 printf("You cannot change a partition into"
1826 " an extended one or vice versa\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001827 break;
1828 }
1829 }
1830
1831 if (sys < 256) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001832#if ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001833 if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001834 printf("Consider leaving partition 3 "
Rob Landleyb73451d2006-02-24 16:29:00 +00001835 "as Whole disk (5),\n"
1836 "as SunOS/Solaris expects it and "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001837 "even Linux likes it\n\n");
1838#endif
1839#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001840 if (LABEL_IS_SGI &&
Rob Landley5527b912006-02-25 03:46:10 +00001841 (
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001842 (i == 10 && sys != SGI_ENTIRE_DISK) ||
Rob Landley5527b912006-02-25 03:46:10 +00001843 (i == 8 && sys != 0)
1844 )
Denis Vlasenkobd852072007-03-19 14:43:38 +00001845 ) {
1846 printf("Consider leaving partition 9 "
Rob Landleyb73451d2006-02-24 16:29:00 +00001847 "as volume header (0),\nand "
1848 "partition 11 as entire volume (6)"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001849 "as IRIX expects it\n\n");
Rob Landley5527b912006-02-25 03:46:10 +00001850 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001851#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001852 if (sys == origsys)
1853 break;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001854 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001855 sun_change_sysid(i, sys);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001856 } else if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001857 sgi_change_sysid(i, sys);
1858 } else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001859 p->sys_ind = sys;
Rob Landley5527b912006-02-25 03:46:10 +00001860
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001861 printf("Changed system type of partition %u "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001862 "to %x (%s)\n", i + 1, sys,
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001863 partition_type(sys));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001864 ptes[i].changed = 1;
Denis Vlasenkoa5549c92008-01-24 22:49:15 +00001865 //if (is_dos_partition(origsys) || is_dos_partition(sys))
1866 // dos_changed = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001867 break;
1868 }
1869 }
1870}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001871#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001872
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001873
Denis Vlasenko28703012006-12-19 20:32:02 +00001874/* check_consistency() and linear2chs() added Sat Mar 6 12:28:16 1993,
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001875 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1876 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1877 * Lubkin Oct. 1991). */
1878
Rob Landleyb73451d2006-02-24 16:29:00 +00001879static void
Denis Vlasenko28703012006-12-19 20:32:02 +00001880linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
Rob Landleyb73451d2006-02-24 16:29:00 +00001881{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001882 int spc = g_heads * g_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001883
1884 *c = ls / spc;
1885 ls = ls % spc;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001886 *h = ls / g_sectors;
1887 *s = ls % g_sectors + 1; /* sectors count from 1 */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001888}
1889
Rob Landleyb73451d2006-02-24 16:29:00 +00001890static void
1891check_consistency(const struct partition *p, int partition)
1892{
Denis Vlasenko834410a2006-11-29 12:00:28 +00001893 unsigned pbc, pbh, pbs; /* physical beginning c, h, s */
1894 unsigned pec, peh, pes; /* physical ending c, h, s */
1895 unsigned lbc, lbh, lbs; /* logical beginning c, h, s */
1896 unsigned lec, leh, les; /* logical ending c, h, s */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001897
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001898 if (!g_heads || !g_sectors || (partition >= 4))
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001899 return; /* do not check extended partitions */
1900
1901/* physical beginning c, h, s */
1902 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
1903 pbh = p->head;
1904 pbs = p->sector & 0x3f;
1905
1906/* physical ending c, h, s */
1907 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
1908 peh = p->end_head;
1909 pes = p->end_sector & 0x3f;
1910
1911/* compute logical beginning (c, h, s) */
Denis Vlasenko28703012006-12-19 20:32:02 +00001912 linear2chs(get_start_sect(p), &lbc, &lbh, &lbs);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001913
1914/* compute logical ending (c, h, s) */
Denis Vlasenko28703012006-12-19 20:32:02 +00001915 linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001916
1917/* Same physical / logical beginning? */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001918 if (g_cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001919 printf("Partition %u has different physical/logical "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001920 "beginnings (non-Linux?):\n", partition + 1);
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001921 printf(" phys=(%u, %u, %u) ", pbc, pbh, pbs);
1922 printf("logical=(%u, %u, %u)\n", lbc, lbh, lbs);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001923 }
1924
1925/* Same physical / logical ending? */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001926 if (g_cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001927 printf("Partition %u has different physical/logical "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001928 "endings:\n", partition + 1);
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001929 printf(" phys=(%u, %u, %u) ", pec, peh, pes);
1930 printf("logical=(%u, %u, %u)\n", lec, leh, les);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001931 }
1932
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001933/* Ending on cylinder boundary? */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001934 if (peh != (g_heads - 1) || pes != g_sectors) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001935 printf("Partition %u does not end on cylinder boundary\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001936 partition + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001937 }
1938}
1939
1940static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001941list_disk_geometry(void)
1942{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001943 ullong bytes = ((ullong)total_number_of_sectors << 9);
1944 long megabytes = bytes / 1000000;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001945
1946 if (megabytes < 10000)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001947 printf("\nDisk %s: %lu MB, %llu bytes\n",
1948 disk_device, megabytes, bytes);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001949 else
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001950 printf("\nDisk %s: %lu.%lu GB, %llu bytes\n",
1951 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
1952 printf("%u heads, %u sectors/track, %u cylinders",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001953 g_heads, g_sectors, g_cylinders);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001954 if (units_per_sector == 1)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001955 printf(", total %"SECT_FMT"u sectors",
1956 total_number_of_sectors / (sector_size/512));
1957 printf("\nUnits = %s of %u * %u = %u bytes\n\n",
1958 str_units(PLURAL),
1959 units_per_sector, sector_size, units_per_sector * sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001960}
1961
1962/*
1963 * Check whether partition entries are ordered by their starting positions.
1964 * Return 0 if OK. Return i if partition i should have been earlier.
1965 * Two separate checks: primary and logical partitions.
1966 */
1967static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001968wrong_p_order(int *prev)
1969{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001970 const struct pte *pe;
1971 const struct partition *p;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001972 sector_t last_p_start_pos = 0, p_start_pos;
1973 unsigned i, last_i = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001974
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001975 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001976 if (i == 4) {
1977 last_i = 4;
1978 last_p_start_pos = 0;
1979 }
1980 pe = &ptes[i];
Denis Vlasenko6bef3d12007-11-06 03:05:54 +00001981 p = pe->part_table;
1982 if (p->sys_ind) {
Denys Vlasenkod958e902010-04-06 02:32:26 +02001983 p_start_pos = get_partition_start_from_dev_start(pe);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001984
1985 if (last_p_start_pos > p_start_pos) {
1986 if (prev)
1987 *prev = last_i;
1988 return i;
1989 }
1990
1991 last_p_start_pos = p_start_pos;
1992 last_i = i;
1993 }
1994 }
1995 return 0;
1996}
1997
Denis Vlasenko834410a2006-11-29 12:00:28 +00001998#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001999/*
2000 * Fix the chain of logicals.
2001 * extended_offset is unchanged, the set of sectors used is unchanged
2002 * The chain is sorted so that sectors increase, and so that
2003 * starting sectors increase.
2004 *
2005 * After this it may still be that cfdisk doesnt like the table.
2006 * (This is because cfdisk considers expanded parts, from link to
2007 * end of partition, and these may still overlap.)
2008 * Now
2009 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
2010 * may help.
2011 */
2012static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002013fix_chain_of_logicals(void)
2014{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002015 int j, oj, ojj, sj, sjj;
2016 struct partition *pj,*pjj,tmp;
2017
2018 /* Stage 1: sort sectors but leave sector of part 4 */
2019 /* (Its sector is the global extended_offset.) */
2020 stage1:
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002021 for (j = 5; j < g_partitions - 1; j++) {
Denys Vlasenkod958e902010-04-06 02:32:26 +02002022 oj = ptes[j].offset_from_dev_start;
2023 ojj = ptes[j+1].offset_from_dev_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002024 if (oj > ojj) {
Denys Vlasenkod958e902010-04-06 02:32:26 +02002025 ptes[j].offset_from_dev_start = ojj;
2026 ptes[j+1].offset_from_dev_start = oj;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002027 pj = ptes[j].part_table;
2028 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
2029 pjj = ptes[j+1].part_table;
2030 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
2031 set_start_sect(ptes[j-1].ext_pointer,
Rob Landleyb73451d2006-02-24 16:29:00 +00002032 ojj-extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002033 set_start_sect(ptes[j].ext_pointer,
Rob Landleyb73451d2006-02-24 16:29:00 +00002034 oj-extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002035 goto stage1;
2036 }
2037 }
2038
2039 /* Stage 2: sort starting sectors */
2040 stage2:
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002041 for (j = 4; j < g_partitions - 1; j++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002042 pj = ptes[j].part_table;
2043 pjj = ptes[j+1].part_table;
2044 sj = get_start_sect(pj);
2045 sjj = get_start_sect(pjj);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002046 oj = ptes[j].offset_from_dev_start;
2047 ojj = ptes[j+1].offset_from_dev_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002048 if (oj+sj > ojj+sjj) {
2049 tmp = *pj;
2050 *pj = *pjj;
2051 *pjj = tmp;
2052 set_start_sect(pj, ojj+sjj-oj);
2053 set_start_sect(pjj, oj+sj-ojj);
2054 goto stage2;
2055 }
2056 }
2057
2058 /* Probably something was changed */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002059 for (j = 4; j < g_partitions; j++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002060 ptes[j].changed = 1;
2061}
2062
2063
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002064static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002065fix_partition_table_order(void)
2066{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002067 struct pte *pei, *pek;
2068 int i,k;
2069
2070 if (!wrong_p_order(NULL)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002071 printf("Ordering is already correct\n\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002072 return;
2073 }
2074
2075 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
2076 /* partition i should have come earlier, move it */
2077 /* We have to move data in the MBR */
2078 struct partition *pi, *pk, *pe, pbuf;
2079 pei = &ptes[i];
2080 pek = &ptes[k];
2081
2082 pe = pei->ext_pointer;
2083 pei->ext_pointer = pek->ext_pointer;
2084 pek->ext_pointer = pe;
2085
2086 pi = pei->part_table;
2087 pk = pek->part_table;
2088
2089 memmove(&pbuf, pi, sizeof(struct partition));
2090 memmove(pi, pk, sizeof(struct partition));
2091 memmove(pk, &pbuf, sizeof(struct partition));
2092
2093 pei->changed = pek->changed = 1;
2094 }
2095
2096 if (i)
2097 fix_chain_of_logicals();
2098
2099 printf("Done.\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002100}
2101#endif
2102
2103static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002104list_table(int xtra)
2105{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002106 const struct partition *p;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002107 int i, w;
2108
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002109 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002110 sun_list_table(xtra);
2111 return;
2112 }
Kevin Cernekeeccb07042010-10-25 02:00:24 +02002113 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002114 sgi_list_table(xtra);
2115 return;
2116 }
Kevin Cernekeeccb07042010-10-25 02:00:24 +02002117 if (LABEL_IS_GPT) {
2118 gpt_list_table(xtra);
2119 return;
2120 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002121
2122 list_disk_geometry();
2123
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002124 if (LABEL_IS_OSF) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002125 xbsd_print_disklabel(xtra);
2126 return;
2127 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002128
2129 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
2130 but if the device name ends in a digit, say /dev/foo1,
2131 then the partition is called /dev/foo1p3. */
2132 w = strlen(disk_device);
2133 if (w && isdigit(disk_device[w-1]))
2134 w++;
2135 if (w < 5)
2136 w = 5;
2137
Denis Vlasenkobd852072007-03-19 14:43:38 +00002138 // 1 12345678901 12345678901 12345678901 12
2139 printf("%*s Boot Start End Blocks Id System\n",
2140 w+1, "Device");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002141
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002142 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002143 const struct pte *pe = &ptes[i];
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002144 sector_t psects;
2145 sector_t pblocks;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002146 unsigned podd;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002147
2148 p = pe->part_table;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002149 if (!p || is_cleared_partition(p))
2150 continue;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002151
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002152 psects = get_nr_sects(p);
2153 pblocks = psects;
2154 podd = 0;
2155
2156 if (sector_size < 1024) {
2157 pblocks /= (1024 / sector_size);
2158 podd = psects % (1024 / sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002159 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002160 if (sector_size > 1024)
2161 pblocks *= (sector_size / 1024);
2162
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002163 printf("%s %c %11"SECT_FMT"u %11"SECT_FMT"u %11"SECT_FMT"u%c %2x %s\n",
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002164 partname(disk_device, i+1, w+2),
2165 !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
2166 ? '*' : '?',
Denys Vlasenkod958e902010-04-06 02:32:26 +02002167 cround(get_partition_start_from_dev_start(pe)), /* start */
2168 cround(get_partition_start_from_dev_start(pe) + psects /* end */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002169 - (psects ? 1 : 0)),
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002170 pblocks, podd ? '+' : ' ', /* odd flag on end */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002171 p->sys_ind, /* type id */
2172 partition_type(p->sys_ind)); /* type name */
2173
2174 check_consistency(p, i);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002175 }
2176
2177 /* Is partition table in disk order? It need not be, but... */
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002178 /* partition table entries are not checked for correct order
2179 * if this is a sgi, sun or aix labeled disk... */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002180 if (LABEL_IS_DOS && wrong_p_order(NULL)) {
Rob Landley5527b912006-02-25 03:46:10 +00002181 /* FIXME */
Denis Vlasenkobd852072007-03-19 14:43:38 +00002182 printf("\nPartition table entries are not in disk order\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002183 }
2184}
2185
Denis Vlasenko834410a2006-11-29 12:00:28 +00002186#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002187static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002188x_list_table(int extend)
2189{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002190 const struct pte *pe;
2191 const struct partition *p;
2192 int i;
2193
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002194 printf("\nDisk %s: %u heads, %u sectors, %u cylinders\n\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002195 disk_device, g_heads, g_sectors, g_cylinders);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002196 printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002197 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002198 pe = &ptes[i];
2199 p = (extend ? pe->ext_pointer : pe->part_table);
2200 if (p != NULL) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002201 printf("%2u %02x%4u%4u%5u%4u%4u%5u%11"SECT_FMT"u%11"SECT_FMT"u %02x\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002202 i + 1, p->boot_ind, p->head,
2203 sector(p->sector),
2204 cylinder(p->sector, p->cyl), p->end_head,
2205 sector(p->end_sector),
2206 cylinder(p->end_sector, p->end_cyl),
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002207 get_start_sect(p), get_nr_sects(p),
2208 p->sys_ind);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002209 if (p->sys_ind)
2210 check_consistency(p, i);
2211 }
2212 }
2213}
2214#endif
2215
Denis Vlasenko834410a2006-11-29 12:00:28 +00002216#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002217static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002218fill_bounds(sector_t *first, sector_t *last)
Rob Landleyb73451d2006-02-24 16:29:00 +00002219{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002220 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002221 const struct pte *pe = &ptes[0];
2222 const struct partition *p;
2223
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002224 for (i = 0; i < g_partitions; pe++,i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002225 p = pe->part_table;
Rob Landleyb73451d2006-02-24 16:29:00 +00002226 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002227 first[i] = 0xffffffff;
2228 last[i] = 0;
2229 } else {
Denys Vlasenkod958e902010-04-06 02:32:26 +02002230 first[i] = get_partition_start_from_dev_start(pe);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002231 last[i] = first[i] + get_nr_sects(p) - 1;
2232 }
2233 }
2234}
2235
2236static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002237check(int n, unsigned h, unsigned s, unsigned c, sector_t start)
Rob Landleyb73451d2006-02-24 16:29:00 +00002238{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002239 sector_t total, real_s, real_c;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002240
2241 real_s = sector(s) - 1;
2242 real_c = cylinder(s, c);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002243 total = (real_c * g_sectors + real_s) * g_heads + h;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002244 if (!total)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002245 printf("Partition %u contains sector 0\n", n);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002246 if (h >= g_heads)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002247 printf("Partition %u: head %u greater than maximum %u\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002248 n, h + 1, g_heads);
2249 if (real_s >= g_sectors)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002250 printf("Partition %u: sector %u greater than "
2251 "maximum %u\n", n, s, g_sectors);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002252 if (real_c >= g_cylinders)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002253 printf("Partition %u: cylinder %"SECT_FMT"u greater than "
2254 "maximum %u\n", n, real_c + 1, g_cylinders);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002255 if (g_cylinders <= 1024 && start != total)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002256 printf("Partition %u: previous sectors %"SECT_FMT"u disagrees with "
2257 "total %"SECT_FMT"u\n", n, start, total);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002258}
2259
2260static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002261verify(void)
2262{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002263 int i, j;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002264 sector_t total = 1;
2265 sector_t first[g_partitions], last[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002266 struct partition *p;
2267
2268 if (warn_geometry())
2269 return;
2270
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002271 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002272 verify_sun();
2273 return;
2274 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002275 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002276 verify_sgi(1);
2277 return;
2278 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002279
2280 fill_bounds(first, last);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002281 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002282 struct pte *pe = &ptes[i];
2283
2284 p = pe->part_table;
Rob Landleyb73451d2006-02-24 16:29:00 +00002285 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002286 check_consistency(p, i);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002287 if (get_partition_start_from_dev_start(pe) < first[i])
Denis Vlasenkobd852072007-03-19 14:43:38 +00002288 printf("Warning: bad start-of-data in "
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002289 "partition %u\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002290 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
2291 last[i]);
2292 total += last[i] + 1 - first[i];
Denis Vlasenkobd852072007-03-19 14:43:38 +00002293 for (j = 0; j < i; j++) {
2294 if ((first[i] >= first[j] && first[i] <= last[j])
2295 || ((last[i] <= last[j] && last[i] >= first[j]))) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002296 printf("Warning: partition %u overlaps "
2297 "partition %u\n", j + 1, i + 1);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002298 total += first[i] >= first[j] ?
2299 first[i] : first[j];
2300 total -= last[i] <= last[j] ?
2301 last[i] : last[j];
2302 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002303 }
2304 }
2305 }
2306
2307 if (extended_offset) {
2308 struct pte *pex = &ptes[ext_index];
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002309 sector_t e_last = get_start_sect(pex->part_table) +
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002310 get_nr_sects(pex->part_table) - 1;
2311
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002312 for (i = 4; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002313 total++;
2314 p = ptes[i].part_table;
2315 if (!p->sys_ind) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002316 if (i != 4 || i + 1 < g_partitions)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002317 printf("Warning: partition %u "
Denis Vlasenkobd852072007-03-19 14:43:38 +00002318 "is empty\n", i + 1);
2319 } else if (first[i] < extended_offset || last[i] > e_last) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002320 printf("Logical partition %u not entirely in "
2321 "partition %u\n", i + 1, ext_index + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002322 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002323 }
2324 }
2325
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002326 if (total > g_heads * g_sectors * g_cylinders)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002327 printf("Total allocated sectors %u greater than the maximum "
2328 "%u\n", total, g_heads * g_sectors * g_cylinders);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002329 else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002330 total = g_heads * g_sectors * g_cylinders - total;
Denis Vlasenkobd852072007-03-19 14:43:38 +00002331 if (total != 0)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002332 printf("%"SECT_FMT"u unallocated sectors\n", total);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002333 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002334}
2335
2336static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002337add_partition(int n, int sys)
2338{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002339 char mesg[256]; /* 48 does not suffice in Japanese */
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002340 int i, num_read = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002341 struct partition *p = ptes[n].part_table;
2342 struct partition *q = ptes[ext_index].part_table;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002343 sector_t limit, temp;
2344 sector_t start, stop = 0;
2345 sector_t first[g_partitions], last[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002346
2347 if (p && p->sys_ind) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002348 printf(msg_part_already_defined, n + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002349 return;
2350 }
2351 fill_bounds(first, last);
2352 if (n < 4) {
2353 start = sector_offset;
Eric Andersen040f4402003-07-30 08:40:37 +00002354 if (display_in_cyl_units || !total_number_of_sectors)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002355 limit = (sector_t) g_heads * g_sectors * g_cylinders - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002356 else
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002357 limit = total_number_of_sectors - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002358 if (extended_offset) {
2359 first[ext_index] = extended_offset;
2360 last[ext_index] = get_start_sect(q) +
2361 get_nr_sects(q) - 1;
2362 }
2363 } else {
2364 start = extended_offset + sector_offset;
2365 limit = get_start_sect(q) + get_nr_sects(q) - 1;
2366 }
2367 if (display_in_cyl_units)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002368 for (i = 0; i < g_partitions; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002369 first[i] = (cround(first[i]) - 1) * units_per_sector;
2370
Denis Vlasenkobd852072007-03-19 14:43:38 +00002371 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002372 do {
2373 temp = start;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002374 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002375 int lastplusoff;
2376
Denys Vlasenkod958e902010-04-06 02:32:26 +02002377 if (start == ptes[i].offset_from_dev_start)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002378 start += sector_offset;
Rob Landleyb73451d2006-02-24 16:29:00 +00002379 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002380 if (start >= first[i] && start <= lastplusoff)
2381 start = lastplusoff + 1;
2382 }
2383 if (start > limit)
2384 break;
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002385 if (start >= temp+units_per_sector && num_read) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002386 printf("Sector %"SECT_FMT"u is already allocated\n", temp);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002387 temp = start;
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002388 num_read = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002389 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002390 if (!num_read && start == temp) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002391 sector_t saved_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002392
2393 saved_start = start;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002394 start = read_int(cround(saved_start), cround(saved_start), cround(limit), 0, mesg);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002395 if (display_in_cyl_units) {
2396 start = (start - 1) * units_per_sector;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002397 if (start < saved_start)
2398 start = saved_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002399 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002400 num_read = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002401 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002402 } while (start != temp || !num_read);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002403 if (n > 4) { /* NOT for fifth partition */
2404 struct pte *pe = &ptes[n];
2405
Denys Vlasenkod958e902010-04-06 02:32:26 +02002406 pe->offset_from_dev_start = start - sector_offset;
2407 if (pe->offset_from_dev_start == extended_offset) { /* must be corrected */
2408 pe->offset_from_dev_start++;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002409 if (sector_offset == 1)
2410 start++;
2411 }
2412 }
2413
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002414 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002415 struct pte *pe = &ptes[i];
2416
Denys Vlasenkod958e902010-04-06 02:32:26 +02002417 if (start < pe->offset_from_dev_start && limit >= pe->offset_from_dev_start)
2418 limit = pe->offset_from_dev_start - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002419 if (start < first[i] && limit >= first[i])
2420 limit = first[i] - 1;
2421 }
2422 if (start > limit) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002423 printf("No free sectors available\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002424 if (n > 4)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002425 g_partitions--;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002426 return;
2427 }
2428 if (cround(start) == cround(limit)) {
2429 stop = limit;
2430 } else {
2431 snprintf(mesg, sizeof(mesg),
Denis Vlasenkobd852072007-03-19 14:43:38 +00002432 "Last %s or +size or +sizeM or +sizeK",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002433 str_units(SINGULAR));
Denys Vlasenkod958e902010-04-06 02:32:26 +02002434 stop = read_int(cround(start), cround(limit), cround(limit), cround(start), mesg);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002435 if (display_in_cyl_units) {
2436 stop = stop * units_per_sector - 1;
2437 if (stop >limit)
2438 stop = limit;
2439 }
2440 }
2441
2442 set_partition(n, 0, start, stop, sys);
2443 if (n > 4)
Denys Vlasenkod958e902010-04-06 02:32:26 +02002444 set_partition(n - 1, 1, ptes[n].offset_from_dev_start, stop, EXTENDED);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002445
Rob Landleyb73451d2006-02-24 16:29:00 +00002446 if (IS_EXTENDED(sys)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002447 struct pte *pe4 = &ptes[4];
2448 struct pte *pen = &ptes[n];
2449
2450 ext_index = n;
2451 pen->ext_pointer = p;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002452 pe4->offset_from_dev_start = extended_offset = start;
Rob Landley081e3842006-08-03 20:07:35 +00002453 pe4->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002454 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2455 pe4->ext_pointer = pe4->part_table + 1;
2456 pe4->changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002457 g_partitions = 5;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002458 }
2459}
2460
2461static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002462add_logical(void)
2463{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002464 if (g_partitions > 5 || ptes[4].part_table->sys_ind) {
2465 struct pte *pe = &ptes[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002466
Rob Landley081e3842006-08-03 20:07:35 +00002467 pe->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002468 pe->part_table = pt_offset(pe->sectorbuffer, 0);
2469 pe->ext_pointer = pe->part_table + 1;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002470 pe->offset_from_dev_start = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002471 pe->changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002472 g_partitions++;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002473 }
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002474 add_partition(g_partitions - 1, LINUX_NATIVE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002475}
2476
2477static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002478new_partition(void)
2479{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002480 int i, free_primary = 0;
2481
2482 if (warn_geometry())
2483 return;
2484
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002485 if (LABEL_IS_SUN) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002486 add_sun_partition(get_partition(0, g_partitions), LINUX_NATIVE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002487 return;
2488 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002489 if (LABEL_IS_SGI) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002490 sgi_add_partition(get_partition(0, g_partitions), LINUX_NATIVE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002491 return;
2492 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002493 if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002494 printf("Sorry - this fdisk cannot handle AIX disk labels.\n"
2495"If you want to add DOS-type partitions, create a new empty DOS partition\n"
2496"table first (use 'o'). This will destroy the present disk contents.\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002497 return;
2498 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002499
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002500 for (i = 0; i < 4; i++)
2501 free_primary += !ptes[i].part_table->sys_ind;
Eric Andersenc48d49a2003-07-03 10:02:32 +00002502
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002503 if (!free_primary && g_partitions >= MAXIMUM_PARTS) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002504 printf("The maximum number of partitions has been created\n");
Eric Andersen84bdea82004-05-19 10:49:17 +00002505 return;
Rob Landleyb73451d2006-02-24 16:29:00 +00002506 }
Eric Andersenc48d49a2003-07-03 10:02:32 +00002507
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002508 if (!free_primary) {
2509 if (extended_offset)
2510 add_logical();
2511 else
Denis Vlasenkobd852072007-03-19 14:43:38 +00002512 printf("You must delete some partition and add "
2513 "an extended partition first\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002514 } else {
Denis Vlasenkodfce08f2007-03-19 14:45:10 +00002515 char c, line[80];
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00002516 snprintf(line, sizeof(line),
2517 "Command action\n"
2518 " %s\n"
2519 " p primary partition (1-4)\n",
2520 (extended_offset ?
2521 "l logical (5 or over)" : "e extended"));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002522 while (1) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002523 c = read_nonempty(line);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002524 if ((c | 0x20) == 'p') {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002525 i = get_nonexisting_partition(0, 4);
2526 if (i >= 0)
2527 add_partition(i, LINUX_NATIVE);
2528 return;
2529 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002530 if (c == 'l' && extended_offset) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002531 add_logical();
2532 return;
2533 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002534 if (c == 'e' && !extended_offset) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002535 i = get_nonexisting_partition(0, 4);
2536 if (i >= 0)
2537 add_partition(i, EXTENDED);
2538 return;
2539 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002540 printf("Invalid partition number "
2541 "for type '%c'\n", c);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002542 }
2543 }
2544}
2545
2546static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002547write_table(void)
2548{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002549 int i;
2550
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002551 if (LABEL_IS_DOS) {
Rob Landleyb73451d2006-02-24 16:29:00 +00002552 for (i = 0; i < 3; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002553 if (ptes[i].changed)
2554 ptes[3].changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002555 for (i = 3; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002556 struct pte *pe = &ptes[i];
2557
2558 if (pe->changed) {
2559 write_part_table_flag(pe->sectorbuffer);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002560 write_sector(pe->offset_from_dev_start, pe->sectorbuffer);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002561 }
2562 }
2563 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002564 else if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002565 /* no test on change? the printf below might be mistaken */
2566 sgi_write_table();
2567 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002568 else if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002569 int needw = 0;
2570
Rob Landleyb73451d2006-02-24 16:29:00 +00002571 for (i = 0; i < 8; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002572 if (ptes[i].changed)
2573 needw = 1;
2574 if (needw)
2575 sun_write_table();
2576 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002577
Denis Vlasenkobd852072007-03-19 14:43:38 +00002578 printf("The partition table has been altered!\n\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002579 reread_partition_table(1);
2580}
2581
Rob Landleyb73451d2006-02-24 16:29:00 +00002582static void
2583reread_partition_table(int leave)
2584{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002585 int i;
2586
Denis Vlasenkobd852072007-03-19 14:43:38 +00002587 printf("Calling ioctl() to re-read partition table\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002588 sync();
Denis Vlasenkobd852072007-03-19 14:43:38 +00002589 /* sleep(2); Huh? */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002590 i = ioctl_or_perror(dev_fd, BLKRRPART, NULL,
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00002591 "WARNING: rereading partition table "
Denis Vlasenko28703012006-12-19 20:32:02 +00002592 "failed, kernel still uses old table");
Denis Vlasenko28703012006-12-19 20:32:02 +00002593#if 0
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002594 if (dos_changed)
Rob Landleyb73451d2006-02-24 16:29:00 +00002595 printf(
Denis Vlasenkobd852072007-03-19 14:43:38 +00002596 "\nWARNING: If you have created or modified any DOS 6.x\n"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002597 "partitions, please see the fdisk manual page for additional\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +00002598 "information\n");
Denis Vlasenko28703012006-12-19 20:32:02 +00002599#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002600
2601 if (leave) {
Denis Vlasenko28703012006-12-19 20:32:02 +00002602 if (ENABLE_FEATURE_CLEAN_UP)
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002603 close_dev_fd();
Denis Vlasenko28703012006-12-19 20:32:02 +00002604 exit(i != 0);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002605 }
2606}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00002607#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002608
Denis Vlasenko834410a2006-11-29 12:00:28 +00002609#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002610#define MAX_PER_LINE 16
2611static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002612print_buffer(char *pbuffer)
2613{
2614 int i,l;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002615
2616 for (i = 0, l = 0; i < sector_size; i++, l++) {
2617 if (l == 0)
2618 printf("0x%03X:", i);
2619 printf(" %02X", (unsigned char) pbuffer[i]);
2620 if (l == MAX_PER_LINE - 1) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002621 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002622 l = -1;
2623 }
2624 }
2625 if (l > 0)
Denis Vlasenko4daad902007-09-27 10:20:47 +00002626 bb_putchar('\n');
2627 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002628}
2629
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002630static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002631print_raw(void)
2632{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002633 int i;
2634
Denis Vlasenkobd852072007-03-19 14:43:38 +00002635 printf("Device: %s\n", disk_device);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002636 if (LABEL_IS_SGI || LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002637 print_buffer(MBRbuffer);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002638 else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002639 for (i = 3; i < g_partitions; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002640 print_buffer(ptes[i].sectorbuffer);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002641 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002642}
2643
2644static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002645move_begin(unsigned i)
Rob Landleyb73451d2006-02-24 16:29:00 +00002646{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002647 struct pte *pe = &ptes[i];
2648 struct partition *p = pe->part_table;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002649 sector_t new, first, nr_sects;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002650
2651 if (warn_geometry())
2652 return;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002653 nr_sects = get_nr_sects(p);
2654 if (!p->sys_ind || !nr_sects || IS_EXTENDED(p->sys_ind)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002655 printf("Partition %u has no data area\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002656 return;
2657 }
Denys Vlasenkofcad7682010-04-06 16:56:33 +02002658 first = get_partition_start_from_dev_start(pe); /* == pe->offset_from_dev_start + get_start_sect(p) */
Denys Vlasenkod958e902010-04-06 02:32:26 +02002659 new = read_int(0 /*was:first*/, first, first + nr_sects - 1, first, "New beginning of data");
2660 if (new != first) {
2661 sector_t new_relative = new - pe->offset_from_dev_start;
2662 nr_sects += (get_start_sect(p) - new_relative);
2663 set_start_sect(p, new_relative);
2664 set_nr_sects(p, nr_sects);
2665 read_nonempty("Recalculate C/H/S values? (Y/N): ");
2666 if ((line_ptr[0] | 0x20) == 'y')
2667 set_hsc_start_end(p, new, new + nr_sects - 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002668 pe->changed = 1;
2669 }
2670}
2671
2672static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002673xselect(void)
2674{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002675 char c;
2676
Rob Landleyb73451d2006-02-24 16:29:00 +00002677 while (1) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002678 bb_putchar('\n');
Denys Vlasenkod958e902010-04-06 02:32:26 +02002679 c = 0x20 | read_nonempty("Expert command (m for help): ");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002680 switch (c) {
2681 case 'a':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002682 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002683 sun_set_alt_cyl();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002684 break;
2685 case 'b':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002686 if (LABEL_IS_DOS)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002687 move_begin(get_partition(0, g_partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002688 break;
2689 case 'c':
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002690 user_cylinders = g_cylinders =
2691 read_int(1, g_cylinders, 1048576, 0,
Denis Vlasenkobd852072007-03-19 14:43:38 +00002692 "Number of cylinders");
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002693 if (LABEL_IS_SUN)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002694 sun_set_ncyl(g_cylinders);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002695 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002696 warn_cylinders();
2697 break;
2698 case 'd':
2699 print_raw();
2700 break;
2701 case 'e':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002702 if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002703 sgi_set_xcyl();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002704 else if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002705 sun_set_xcyl();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002706 else if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002707 x_list_table(1);
2708 break;
2709 case 'f':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002710 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002711 fix_partition_table_order();
2712 break;
2713 case 'g':
Denis Vlasenko834410a2006-11-29 12:00:28 +00002714#if ENABLE_FEATURE_SGI_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002715 create_sgilabel();
2716#endif
2717 break;
2718 case 'h':
Denys Vlasenkod958e902010-04-06 02:32:26 +02002719 user_heads = g_heads = read_int(1, g_heads, 256, 0, "Number of heads");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002720 update_units();
2721 break;
2722 case 'i':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002723 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002724 sun_set_ilfact();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002725 break;
2726 case 'o':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002727 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002728 sun_set_rspeed();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002729 break;
2730 case 'p':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002731 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002732 list_table(1);
2733 else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002734 x_list_table(0);
2735 break;
2736 case 'q':
Denis Vlasenko4437d192008-04-17 00:12:10 +00002737 if (ENABLE_FEATURE_CLEAN_UP)
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002738 close_dev_fd();
Denis Vlasenko4daad902007-09-27 10:20:47 +00002739 bb_putchar('\n');
Bernhard Reutner-Fischer636a1f82008-05-19 09:29:47 +00002740 exit(EXIT_SUCCESS);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002741 case 'r':
2742 return;
2743 case 's':
Denys Vlasenkod958e902010-04-06 02:32:26 +02002744 user_sectors = g_sectors = read_int(1, g_sectors, 63, 0, "Number of sectors");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002745 if (dos_compatible_flag) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002746 sector_offset = g_sectors;
Denis Vlasenkobd852072007-03-19 14:43:38 +00002747 printf("Warning: setting sector offset for DOS "
2748 "compatiblity\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002749 }
2750 update_units();
2751 break;
2752 case 'v':
2753 verify();
2754 break;
2755 case 'w':
2756 write_table(); /* does not return */
2757 break;
2758 case 'y':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002759 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002760 sun_set_pcylcount();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002761 break;
2762 default:
2763 xmenu();
2764 }
2765 }
2766}
2767#endif /* ADVANCED mode */
2768
2769static int
Rob Landleyb73451d2006-02-24 16:29:00 +00002770is_ide_cdrom_or_tape(const char *device)
2771{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002772 FILE *procf;
2773 char buf[100];
2774 struct stat statbuf;
2775 int is_ide = 0;
2776
2777 /* No device was given explicitly, and we are trying some
2778 likely things. But opening /dev/hdc may produce errors like
2779 "hdc: tray open or drive not ready"
2780 if it happens to be a CD-ROM drive. It even happens that
2781 the process hangs on the attempt to read a music CD.
2782 So try to be careful. This only works since 2.1.73. */
2783
2784 if (strncmp("/dev/hd", device, 7))
2785 return 0;
2786
2787 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
Denis Vlasenko5415c852008-07-21 23:05:26 +00002788 procf = fopen_for_read(buf);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002789 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2790 is_ide = (!strncmp(buf, "cdrom", 5) ||
2791 !strncmp(buf, "tape", 4));
2792 else
2793 /* Now when this proc file does not exist, skip the
2794 device when it is read-only. */
2795 if (stat(device, &statbuf) == 0)
2796 is_ide = ((statbuf.st_mode & 0222) == 0);
2797
2798 if (procf)
2799 fclose(procf);
2800 return is_ide;
2801}
2802
Rob Landley5527b912006-02-25 03:46:10 +00002803
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002804static void
Denis Vlasenko4437d192008-04-17 00:12:10 +00002805open_list_and_close(const char *device, int user_specified)
Rob Landleyb73451d2006-02-24 16:29:00 +00002806{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002807 int gb;
2808
2809 disk_device = device;
2810 if (setjmp(listingbuf))
2811 return;
2812 if (!user_specified)
2813 if (is_ide_cdrom_or_tape(device))
2814 return;
Denis Vlasenko4437d192008-04-17 00:12:10 +00002815
2816 /* Open disk_device, save file descriptor to dev_fd */
2817 errno = 0;
2818 gb = get_boot(TRY_ONLY);
2819 if (gb > 0) { /* I/O error */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002820 /* Ignore other errors, since we try IDE
2821 and SCSI hard disks which may not be
2822 installed on the system. */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002823 if (user_specified || errno == EACCES)
2824 bb_perror_msg("can't open '%s'", device);
2825 return;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002826 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00002827
2828 if (gb < 0) { /* no DOS signature */
2829 list_disk_geometry();
2830 if (LABEL_IS_AIX)
2831 goto ret;
2832#if ENABLE_FEATURE_OSF_LABEL
2833 if (bsd_trydev(device) < 0)
2834#endif
2835 printf("Disk %s doesn't contain a valid "
2836 "partition table\n", device);
2837 } else {
2838 list_table(0);
2839#if ENABLE_FEATURE_FDISK_WRITABLE
2840 if (!LABEL_IS_SUN && g_partitions > 4) {
2841 delete_partition(ext_index);
2842 }
2843#endif
2844 }
2845 ret:
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002846 close_dev_fd();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002847}
2848
2849/* for fdisk -l: try all things in /proc/partitions
2850 that look like a partition name (do not end in a digit) */
2851static void
Denis Vlasenko4437d192008-04-17 00:12:10 +00002852list_devs_in_proc_partititons(void)
Rob Landleyb73451d2006-02-24 16:29:00 +00002853{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002854 FILE *procpt;
2855 char line[100], ptname[100], devname[120], *s;
2856 int ma, mi, sz;
2857
Denis Vlasenkoddec5af2006-10-26 23:25:17 +00002858 procpt = fopen_or_warn("/proc/partitions", "r");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002859
2860 while (fgets(line, sizeof(line), procpt)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002861 if (sscanf(line, " %u %u %u %[^\n ]",
Rob Landleyb73451d2006-02-24 16:29:00 +00002862 &ma, &mi, &sz, ptname) != 4)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002863 continue;
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002864 for (s = ptname; *s; s++)
Denys Vlasenko8f65b0c2010-07-06 18:46:02 +02002865 continue;
Denys Vlasenkobf1d3472010-02-24 08:13:30 +01002866 /* note: excluding '0': e.g. mmcblk0 is not a partition name! */
2867 if (s[-1] >= '1' && s[-1] <= '9')
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002868 continue;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002869 sprintf(devname, "/dev/%s", ptname);
Denis Vlasenko4437d192008-04-17 00:12:10 +00002870 open_list_and_close(devname, 0);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002871 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002872#if ENABLE_FEATURE_CLEAN_UP
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002873 fclose(procpt);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002874#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002875}
2876
Denis Vlasenko834410a2006-11-29 12:00:28 +00002877#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002878static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002879unknown_command(int c)
2880{
Denis Vlasenkobd852072007-03-19 14:43:38 +00002881 printf("%c: unknown command\n", c);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002882}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002883#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002884
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00002885int fdisk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002886int fdisk_main(int argc UNUSED_PARAM, char **argv)
Rob Landleyb73451d2006-02-24 16:29:00 +00002887{
Denis Vlasenko834410a2006-11-29 12:00:28 +00002888 unsigned opt;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002889 /*
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002890 * fdisk -v
2891 * fdisk -l [-b sectorsize] [-u] device ...
2892 * fdisk -s [partition] ...
2893 * fdisk [-b sectorsize] [-u] device
2894 *
2895 * Options -C, -H, -S set the geometry.
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002896 */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002897 INIT_G();
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +00002898
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002899 close_dev_fd(); /* needed: fd 3 must not stay closed */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002900
Denis Vlasenko04e11c92008-02-10 19:44:20 +00002901 opt_complementary = "b+:C+:H+:S+"; /* numeric params */
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002902 opt = getopt32(argv, "b:C:H:lS:u" IF_FEATURE_FDISK_BLKSIZE("s"),
Denis Vlasenko04e11c92008-02-10 19:44:20 +00002903 &sector_size, &user_cylinders, &user_heads, &user_sectors);
Denis Vlasenko834410a2006-11-29 12:00:28 +00002904 argv += optind;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002905 if (opt & OPT_b) {
Denis Vlasenko834410a2006-11-29 12:00:28 +00002906 /* Ugly: this sector size is really per device,
Denys Vlasenkod958e902010-04-06 02:32:26 +02002907 * so cannot be combined with multiple disks,
2908 * and the same goes for the C/H/S options.
2909 */
2910 if (sector_size < 512
2911 || sector_size > 0x10000
2912 || (sector_size & (sector_size-1)) /* not power of 2 */
2913 ) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002914 bb_show_usage();
Denys Vlasenkod958e902010-04-06 02:32:26 +02002915 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002916 sector_offset = 2;
2917 user_set_sector_size = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002918 }
Denis Vlasenko04e11c92008-02-10 19:44:20 +00002919 if (user_heads <= 0 || user_heads >= 256)
2920 user_heads = 0;
2921 if (user_sectors <= 0 || user_sectors >= 64)
2922 user_sectors = 0;
2923 if (opt & OPT_u)
2924 display_in_cyl_units = 0; // -u
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002925
Denis Vlasenko834410a2006-11-29 12:00:28 +00002926#if ENABLE_FEATURE_FDISK_WRITABLE
2927 if (opt & OPT_l) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002928 nowarn = 1;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002929#endif
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002930 if (*argv) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002931 listing = 1;
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002932 do {
Denis Vlasenko4437d192008-04-17 00:12:10 +00002933 open_list_and_close(*argv, 1);
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002934 } while (*++argv);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002935 } else {
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002936 /* we don't have device names, */
2937 /* use /proc/partitions instead */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002938 list_devs_in_proc_partititons();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002939 }
2940 return 0;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002941#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002942 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002943#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002944
Denis Vlasenko834410a2006-11-29 12:00:28 +00002945#if ENABLE_FEATURE_FDISK_BLKSIZE
2946 if (opt & OPT_s) {
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002947 int j;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002948
2949 nowarn = 1;
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002950 if (!argv[0])
Manuel Novoa III cad53642003-03-19 09:13:01 +00002951 bb_show_usage();
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002952 for (j = 0; argv[j]; j++) {
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002953 unsigned long long size;
2954 fd = xopen(argv[j], O_RDONLY);
Denis Vlasenko4437d192008-04-17 00:12:10 +00002955 size = bb_BLKGETSIZE_sectors(fd) / 2;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002956 close(fd);
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002957 if (argv[1])
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002958 printf("%llu\n", size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002959 else
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002960 printf("%s: %llu\n", argv[j], size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002961 }
2962 return 0;
2963 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002964#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002965
Denis Vlasenko834410a2006-11-29 12:00:28 +00002966#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002967 if (!argv[0] || argv[1])
Manuel Novoa III cad53642003-03-19 09:13:01 +00002968 bb_show_usage();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002969
Denis Vlasenko834410a2006-11-29 12:00:28 +00002970 disk_device = argv[0];
Denis Vlasenko4437d192008-04-17 00:12:10 +00002971 get_boot(OPEN_MAIN);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002972
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002973 if (LABEL_IS_OSF) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002974 /* OSF label, and no DOS label */
Denis Vlasenkobd852072007-03-19 14:43:38 +00002975 printf("Detected an OSF/1 disklabel on %s, entering "
2976 "disklabel mode\n", disk_device);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +00002977 bsd_select();
Rob Landley5527b912006-02-25 03:46:10 +00002978 /*Why do we do this? It seems to be counter-intuitive*/
Denis Vlasenko4437d192008-04-17 00:12:10 +00002979 current_label_type = LABEL_DOS;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002980 /* If we return we may want to make an empty DOS label? */
2981 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002982
2983 while (1) {
Denis Vlasenko3bba5452006-12-30 17:57:03 +00002984 int c;
Denis Vlasenko4daad902007-09-27 10:20:47 +00002985 bb_putchar('\n');
Denys Vlasenkod958e902010-04-06 02:32:26 +02002986 c = 0x20 | read_nonempty("Command (m for help): ");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002987 switch (c) {
2988 case 'a':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002989 if (LABEL_IS_DOS)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002990 toggle_active(get_partition(1, g_partitions));
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002991 else if (LABEL_IS_SUN)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002992 toggle_sunflags(get_partition(1, g_partitions),
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002993 0x01);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002994 else if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002995 sgi_set_bootpartition(
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002996 get_partition(1, g_partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002997 else
2998 unknown_command(c);
2999 break;
3000 case 'b':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003001 if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00003002 printf("\nThe current boot file is: %s\n",
Rob Landleyb73451d2006-02-24 16:29:00 +00003003 sgi_get_bootfile());
Denis Vlasenkobd852072007-03-19 14:43:38 +00003004 if (read_maybe_empty("Please enter the name of the "
3005 "new boot file: ") == '\n')
3006 printf("Boot file unchanged\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003007 else
3008 sgi_set_bootfile(line_ptr);
Denis Vlasenko834410a2006-11-29 12:00:28 +00003009 }
3010#if ENABLE_FEATURE_OSF_LABEL
3011 else
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +00003012 bsd_select();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003013#endif
3014 break;
3015 case 'c':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003016 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003017 toggle_dos_compatibility_flag();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003018 else if (LABEL_IS_SUN)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003019 toggle_sunflags(get_partition(1, g_partitions),
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003020 0x10);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003021 else if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003022 sgi_set_swappartition(
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003023 get_partition(1, g_partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003024 else
3025 unknown_command(c);
3026 break;
3027 case 'd':
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00003028 {
Eric Andersen040f4402003-07-30 08:40:37 +00003029 int j;
Eric Andersen040f4402003-07-30 08:40:37 +00003030 /* If sgi_label then don't use get_existing_partition,
3031 let the user select a partition, since
3032 get_existing_partition() only works for Linux-like
3033 partition tables */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003034 if (!LABEL_IS_SGI) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003035 j = get_existing_partition(1, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00003036 } else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003037 j = get_partition(1, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00003038 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00003039 if (j >= 0)
3040 delete_partition(j);
3041 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003042 break;
3043 case 'i':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003044 if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003045 create_sgiinfo();
3046 else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003047 unknown_command(c);
3048 case 'l':
3049 list_types(get_sys_types());
3050 break;
3051 case 'm':
3052 menu();
3053 break;
3054 case 'n':
3055 new_partition();
3056 break;
3057 case 'o':
3058 create_doslabel();
3059 break;
3060 case 'p':
3061 list_table(0);
3062 break;
3063 case 'q':
Denis Vlasenkoc033d512008-04-17 01:52:28 +00003064 if (ENABLE_FEATURE_CLEAN_UP)
3065 close_dev_fd();
Denis Vlasenko4daad902007-09-27 10:20:47 +00003066 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003067 return 0;
3068 case 's':
Denis Vlasenko834410a2006-11-29 12:00:28 +00003069#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003070 create_sunlabel();
3071#endif
3072 break;
3073 case 't':
3074 change_sysid();
3075 break;
3076 case 'u':
3077 change_units();
3078 break;
3079 case 'v':
3080 verify();
3081 break;
3082 case 'w':
3083 write_table(); /* does not return */
3084 break;
Denis Vlasenko834410a2006-11-29 12:00:28 +00003085#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003086 case 'x':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003087 if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00003088 printf("\n\tSorry, no experts menu for SGI "
3089 "partition tables available\n\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003090 } else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003091 xselect();
3092 break;
3093#endif
3094 default:
3095 unknown_command(c);
3096 menu();
3097 }
3098 }
3099 return 0;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003100#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003101}