blob: ce4c24fdc100dc89f4873ec63e86b29c58c91b0f [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"
Pere Orga5bc8c002011-04-11 03:29:49 +020021//usage: "\n -u Start and End are in sectors (instead of cylinders)"
22//usage: "\n -l Show partition table for each DISK, then exit"
23//usage: IF_FEATURE_FDISK_BLKSIZE(
24//usage: "\n -s Show partition sizes in kb for each DISK, then exit"
25//usage: )
26//usage: "\n -b 2048 (for certain MO disks) use 2048-byte sectors"
27//usage: "\n -C CYLINDERS Set number of cylinders/heads/sectors"
28//usage: "\n -H HEADS"
29//usage: "\n -S SECTORS"
30
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +000031#ifndef _LARGEFILE64_SOURCE
32/* For lseek64 */
Denys Vlasenkoaf3fd142009-09-22 23:16:39 +020033# define _LARGEFILE64_SOURCE
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +000034#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000035#include <assert.h> /* assert */
Denys Vlasenkoda49f582009-07-08 02:58:38 +020036#include <sys/mount.h>
37#if !defined(BLKSSZGET)
38# define BLKSSZGET _IO(0x12, 104)
39#endif
Denys Vlasenkoaf3fd142009-09-22 23:16:39 +020040#if !defined(BLKGETSIZE64)
41# define BLKGETSIZE64 _IOR(0x12,114,size_t)
42#endif
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000043#include "libbb.h"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000044
Denys Vlasenko5ea1de22010-04-06 02:31:43 +020045#if BB_LITTLE_ENDIAN
46# define inline_if_little_endian ALWAYS_INLINE
47#else
48# define inline_if_little_endian /* nothing */
49#endif
50
51
Denis Vlasenko834410a2006-11-29 12:00:28 +000052/* Looks like someone forgot to add this to config system */
53#ifndef ENABLE_FEATURE_FDISK_BLKSIZE
54# define ENABLE_FEATURE_FDISK_BLKSIZE 0
Denis Vlasenko5e34ff22009-04-21 11:09:40 +000055# define IF_FEATURE_FDISK_BLKSIZE(a)
Denis Vlasenko834410a2006-11-29 12:00:28 +000056#endif
57
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +000058#define DEFAULT_SECTOR_SIZE 512
59#define DEFAULT_SECTOR_SIZE_STR "512"
60#define MAX_SECTOR_SIZE 2048
61#define SECTOR_SIZE 512 /* still used in osf/sgi/sun code */
62#define MAXIMUM_PARTS 60
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000063
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +000064#define ACTIVE_FLAG 0x80
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000065
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +000066#define EXTENDED 0x05
67#define WIN98_EXTENDED 0x0f
68#define LINUX_PARTITION 0x81
69#define LINUX_SWAP 0x82
70#define LINUX_NATIVE 0x83
71#define LINUX_EXTENDED 0x85
72#define LINUX_LVM 0x8e
73#define LINUX_RAID 0xfd
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000074
Denis Vlasenkoc033d512008-04-17 01:52:28 +000075
76enum {
77 OPT_b = 1 << 0,
78 OPT_C = 1 << 1,
79 OPT_H = 1 << 2,
80 OPT_l = 1 << 3,
81 OPT_S = 1 << 4,
82 OPT_u = 1 << 5,
83 OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
84};
85
86
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +000087typedef unsigned long long ullong;
Denys Vlasenkoddf78502009-09-16 03:03:13 +020088/* Used for sector numbers. Partition formats we know
89 * do not support more than 2^32 sectors
90 */
91typedef uint32_t sector_t;
92#if UINT_MAX == 4294967295
93# define SECT_FMT ""
94#elif ULONG_MAX == 4294967295
95# define SECT_FMT "l"
96#else
97# error Cant detect sizeof(uint32_t)
98#endif
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +000099
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000100struct hd_geometry {
Rob Landleyb73451d2006-02-24 16:29:00 +0000101 unsigned char heads;
102 unsigned char sectors;
103 unsigned short cylinders;
104 unsigned long start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000105};
106
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000107#define HDIO_GETGEO 0x0301 /* get device geometry */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000108
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000109static const char msg_building_new_label[] ALIGN1 =
Denis Vlasenkobd852072007-03-19 14:43:38 +0000110"Building a new %s. Changes will remain in memory only,\n"
111"until you decide to write them. After that the previous content\n"
112"won't be recoverable.\n\n";
113
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000114static const char msg_part_already_defined[] ALIGN1 =
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200115"Partition %u is already defined, delete it before re-adding\n";
Denis Vlasenkobd852072007-03-19 14:43:38 +0000116
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000117
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000118struct partition {
119 unsigned char boot_ind; /* 0x80 - active */
120 unsigned char head; /* starting head */
121 unsigned char sector; /* starting sector */
122 unsigned char cyl; /* starting cylinder */
Denis Vlasenko9764d692008-07-09 21:20:50 +0000123 unsigned char sys_ind; /* what partition type */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000124 unsigned char end_head; /* end head */
125 unsigned char end_sector; /* end sector */
126 unsigned char end_cyl; /* end cylinder */
127 unsigned char start4[4]; /* starting sector counting from 0 */
128 unsigned char size4[4]; /* nr of sectors in partition */
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000129} PACKED;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000130
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200131/*
132 * per partition table entry data
133 *
134 * The four primary partitions have the same sectorbuffer (MBRbuffer)
135 * and have NULL ext_pointer.
136 * Each logical partition table entry has two pointers, one for the
137 * partition and one link to the next one.
138 */
139struct pte {
140 struct partition *part_table; /* points into sectorbuffer */
141 struct partition *ext_pointer; /* points into sectorbuffer */
142 sector_t offset_from_dev_start; /* disk sector number */
143 char *sectorbuffer; /* disk sector contents */
144#if ENABLE_FEATURE_FDISK_WRITABLE
145 char changed; /* boolean */
146#endif
147};
148
Denys Vlasenkoea8b2522010-06-02 12:57:26 +0200149#define unable_to_open "can't open '%s'"
150#define unable_to_read "can't read from %s"
151#define unable_to_seek "can't seek on %s"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000152
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000153enum label_type {
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200154 LABEL_DOS, LABEL_SUN, LABEL_SGI, LABEL_AIX, LABEL_OSF, LABEL_GPT
Rob Landley5527b912006-02-25 03:46:10 +0000155};
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000156
Denis Vlasenko4437d192008-04-17 00:12:10 +0000157#define LABEL_IS_DOS (LABEL_DOS == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000158
Denis Vlasenko834410a2006-11-29 12:00:28 +0000159#if ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko4437d192008-04-17 00:12:10 +0000160#define LABEL_IS_SUN (LABEL_SUN == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000161#define STATIC_SUN static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000162#else
163#define LABEL_IS_SUN 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000164#define STATIC_SUN extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000165#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000166
Denis Vlasenko834410a2006-11-29 12:00:28 +0000167#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenko4437d192008-04-17 00:12:10 +0000168#define LABEL_IS_SGI (LABEL_SGI == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000169#define STATIC_SGI static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000170#else
171#define LABEL_IS_SGI 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000172#define STATIC_SGI extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000173#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000174
Denis Vlasenko834410a2006-11-29 12:00:28 +0000175#if ENABLE_FEATURE_AIX_LABEL
Denis Vlasenko4437d192008-04-17 00:12:10 +0000176#define LABEL_IS_AIX (LABEL_AIX == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000177#define STATIC_AIX static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000178#else
179#define LABEL_IS_AIX 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000180#define STATIC_AIX extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000181#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000182
Denis Vlasenko834410a2006-11-29 12:00:28 +0000183#if ENABLE_FEATURE_OSF_LABEL
Denis Vlasenko4437d192008-04-17 00:12:10 +0000184#define LABEL_IS_OSF (LABEL_OSF == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000185#define STATIC_OSF static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000186#else
187#define LABEL_IS_OSF 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000188#define STATIC_OSF extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000189#endif
Rob Landley5527b912006-02-25 03:46:10 +0000190
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200191#if ENABLE_FEATURE_GPT_LABEL
192#define LABEL_IS_GPT (LABEL_GPT == current_label_type)
193#define STATIC_GPT static
194#else
195#define LABEL_IS_GPT 0
196#define STATIC_GPT extern
197#endif
198
Denis Vlasenko4437d192008-04-17 00:12:10 +0000199enum action { OPEN_MAIN, TRY_ONLY, CREATE_EMPTY_DOS, CREATE_EMPTY_SUN };
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000200
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000201static void update_units(void);
Denis Vlasenko834410a2006-11-29 12:00:28 +0000202#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000203static void change_units(void);
Denys Vlasenkob347df92011-08-09 22:49:15 +0200204static void reread_partition_table(int leave);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000205static void delete_partition(int i);
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200206static unsigned get_partition(int warn, unsigned max);
Denis Vlasenkobd852072007-03-19 14:43:38 +0000207static void list_types(const char *const *sys);
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200208static 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 +0000209#endif
210static const char *partition_type(unsigned char type);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000211static void get_geometry(void);
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200212static void read_pte(struct pte *pe, sector_t offset);
Denis Vlasenko85c24712008-03-17 09:04:04 +0000213#if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000214static int get_boot(enum action what);
Denis Vlasenko85c24712008-03-17 09:04:04 +0000215#else
216static int get_boot(void);
217#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000218
219#define PLURAL 0
220#define SINGULAR 1
221
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200222static sector_t get_start_sect(const struct partition *p);
223static sector_t get_nr_sects(const struct partition *p);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000224
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000225/* DOS partition types */
226
227static const char *const i386_sys_types[] = {
228 "\x00" "Empty",
229 "\x01" "FAT12",
230 "\x04" "FAT16 <32M",
231 "\x05" "Extended", /* DOS 3.3+ extended partition */
232 "\x06" "FAT16", /* DOS 16-bit >=32M */
233 "\x07" "HPFS/NTFS", /* OS/2 IFS, eg, HPFS or NTFS or QNX */
234 "\x0a" "OS/2 Boot Manager",/* OS/2 Boot Manager */
235 "\x0b" "Win95 FAT32",
236 "\x0c" "Win95 FAT32 (LBA)",/* LBA really is 'Extended Int 13h' */
237 "\x0e" "Win95 FAT16 (LBA)",
238 "\x0f" "Win95 Ext'd (LBA)",
239 "\x11" "Hidden FAT12",
240 "\x12" "Compaq diagnostics",
241 "\x14" "Hidden FAT16 <32M",
242 "\x16" "Hidden FAT16",
243 "\x17" "Hidden HPFS/NTFS",
244 "\x1b" "Hidden Win95 FAT32",
245 "\x1c" "Hidden W95 FAT32 (LBA)",
246 "\x1e" "Hidden W95 FAT16 (LBA)",
247 "\x3c" "Part.Magic recovery",
248 "\x41" "PPC PReP Boot",
249 "\x42" "SFS",
250 "\x63" "GNU HURD or SysV", /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
251 "\x80" "Old Minix", /* Minix 1.4a and earlier */
252 "\x81" "Minix / old Linux",/* Minix 1.4b and later */
253 "\x82" "Linux swap", /* also Solaris */
254 "\x83" "Linux",
255 "\x84" "OS/2 hidden C: drive",
256 "\x85" "Linux extended",
257 "\x86" "NTFS volume set",
258 "\x87" "NTFS volume set",
259 "\x8e" "Linux LVM",
260 "\x9f" "BSD/OS", /* BSDI */
261 "\xa0" "Thinkpad hibernation",
262 "\xa5" "FreeBSD", /* various BSD flavours */
263 "\xa6" "OpenBSD",
264 "\xa8" "Darwin UFS",
265 "\xa9" "NetBSD",
266 "\xab" "Darwin boot",
267 "\xb7" "BSDI fs",
268 "\xb8" "BSDI swap",
269 "\xbe" "Solaris boot",
270 "\xeb" "BeOS fs",
271 "\xee" "EFI GPT", /* Intel EFI GUID Partition Table */
272 "\xef" "EFI (FAT-12/16/32)", /* Intel EFI System Partition */
273 "\xf0" "Linux/PA-RISC boot", /* Linux/PA-RISC boot loader */
274 "\xf2" "DOS secondary", /* DOS 3.3+ secondary */
275 "\xfd" "Linux raid autodetect", /* New (2.2.x) raid partition with
276 autodetect using persistent
277 superblock */
278#if 0 /* ENABLE_WEIRD_PARTITION_TYPES */
279 "\x02" "XENIX root",
280 "\x03" "XENIX usr",
281 "\x08" "AIX", /* AIX boot (AIX -- PS/2 port) or SplitDrive */
282 "\x09" "AIX bootable", /* AIX data or Coherent */
283 "\x10" "OPUS",
284 "\x18" "AST SmartSleep",
285 "\x24" "NEC DOS",
286 "\x39" "Plan 9",
287 "\x40" "Venix 80286",
288 "\x4d" "QNX4.x",
289 "\x4e" "QNX4.x 2nd part",
290 "\x4f" "QNX4.x 3rd part",
291 "\x50" "OnTrack DM",
292 "\x51" "OnTrack DM6 Aux1", /* (or Novell) */
293 "\x52" "CP/M", /* CP/M or Microport SysV/AT */
294 "\x53" "OnTrack DM6 Aux3",
295 "\x54" "OnTrackDM6",
296 "\x55" "EZ-Drive",
297 "\x56" "Golden Bow",
298 "\x5c" "Priam Edisk",
299 "\x61" "SpeedStor",
300 "\x64" "Novell Netware 286",
301 "\x65" "Novell Netware 386",
302 "\x70" "DiskSecure Multi-Boot",
303 "\x75" "PC/IX",
304 "\x93" "Amoeba",
305 "\x94" "Amoeba BBT", /* (bad block table) */
306 "\xa7" "NeXTSTEP",
307 "\xbb" "Boot Wizard hidden",
308 "\xc1" "DRDOS/sec (FAT-12)",
309 "\xc4" "DRDOS/sec (FAT-16 < 32M)",
310 "\xc6" "DRDOS/sec (FAT-16)",
311 "\xc7" "Syrinx",
312 "\xda" "Non-FS data",
313 "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or
314 Concurrent DOS or CTOS */
315 "\xde" "Dell Utility", /* Dell PowerEdge Server utilities */
316 "\xdf" "BootIt", /* BootIt EMBRM */
317 "\xe1" "DOS access", /* DOS access or SpeedStor 12-bit FAT
318 extended partition */
319 "\xe3" "DOS R/O", /* DOS R/O or SpeedStor */
320 "\xe4" "SpeedStor", /* SpeedStor 16-bit FAT extended
321 partition < 1024 cyl. */
322 "\xf1" "SpeedStor",
323 "\xf4" "SpeedStor", /* SpeedStor large partition */
324 "\xfe" "LANstep", /* SpeedStor >1024 cyl. or LANstep */
325 "\xff" "BBT", /* Xenix Bad Block Table */
326#endif
327 NULL
328};
329
Denis Vlasenko4437d192008-04-17 00:12:10 +0000330enum {
331 dev_fd = 3 /* the disk */
332};
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000333
334/* Globals */
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000335struct globals {
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000336 char *line_ptr;
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000337
338 const char *disk_device;
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000339 int g_partitions; // = 4; /* maximum partition + 1 */
340 unsigned units_per_sector; // = 1;
341 unsigned sector_size; // = DEFAULT_SECTOR_SIZE;
342 unsigned user_set_sector_size;
343 unsigned sector_offset; // = 1;
344 unsigned g_heads, g_sectors, g_cylinders;
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000345 smallint /* enum label_type */ current_label_type;
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000346 smallint display_in_cyl_units; // = 1;
347#if ENABLE_FEATURE_OSF_LABEL
348 smallint possibly_osf_label;
349#endif
350
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000351 smallint listing; /* no aborts for fdisk -l */
352 smallint dos_compatible_flag; // = 1;
353#if ENABLE_FEATURE_FDISK_WRITABLE
354 //int dos_changed;
355 smallint nowarn; /* no warnings for fdisk -l/-s */
356#endif
357 int ext_index; /* the prime extended partition */
358 unsigned user_cylinders, user_heads, user_sectors;
359 unsigned pt_heads, pt_sectors;
360 unsigned kern_heads, kern_sectors;
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200361 sector_t extended_offset; /* offset of link pointers */
362 sector_t total_number_of_sectors;
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000363
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000364 jmp_buf listingbuf;
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000365 char line_buffer[80];
366 char partname_buffer[80];
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000367 /* Raw disk label. For DOS-type partition tables the MBR,
368 * with descriptions of the primary partitions. */
369 char MBRbuffer[MAX_SECTOR_SIZE];
370 /* Partition tables */
371 struct pte ptes[MAXIMUM_PARTS];
372};
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000373#define G (*ptr_to_globals)
Denis Vlasenko270d5d72008-06-29 05:16:45 +0000374#define line_ptr (G.line_ptr )
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000375#define disk_device (G.disk_device )
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000376#define g_partitions (G.g_partitions )
377#define units_per_sector (G.units_per_sector )
378#define sector_size (G.sector_size )
379#define user_set_sector_size (G.user_set_sector_size)
380#define sector_offset (G.sector_offset )
381#define g_heads (G.g_heads )
382#define g_sectors (G.g_sectors )
383#define g_cylinders (G.g_cylinders )
384#define current_label_type (G.current_label_type )
385#define display_in_cyl_units (G.display_in_cyl_units)
386#define possibly_osf_label (G.possibly_osf_label )
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000387#define listing (G.listing )
388#define dos_compatible_flag (G.dos_compatible_flag )
389#define nowarn (G.nowarn )
390#define ext_index (G.ext_index )
391#define user_cylinders (G.user_cylinders )
392#define user_heads (G.user_heads )
393#define user_sectors (G.user_sectors )
394#define pt_heads (G.pt_heads )
395#define pt_sectors (G.pt_sectors )
396#define kern_heads (G.kern_heads )
397#define kern_sectors (G.kern_sectors )
398#define extended_offset (G.extended_offset )
399#define total_number_of_sectors (G.total_number_of_sectors)
Denis Vlasenko270d5d72008-06-29 05:16:45 +0000400#define listingbuf (G.listingbuf )
401#define line_buffer (G.line_buffer )
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000402#define partname_buffer (G.partname_buffer)
Denis Vlasenko270d5d72008-06-29 05:16:45 +0000403#define MBRbuffer (G.MBRbuffer )
404#define ptes (G.ptes )
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000405#define INIT_G() do { \
Denis Vlasenko574f2f42008-02-27 18:41:59 +0000406 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000407 sector_size = DEFAULT_SECTOR_SIZE; \
408 sector_offset = 1; \
409 g_partitions = 4; \
410 display_in_cyl_units = 1; \
411 units_per_sector = 1; \
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000412 dos_compatible_flag = 1; \
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000413} while (0)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000414
Denis Vlasenkobd852072007-03-19 14:43:38 +0000415
Denis Vlasenkocdf62772008-03-17 08:42:43 +0000416/* TODO: move to libbb? */
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200417/* TODO: return unsigned long long, FEATURE_FDISK_BLKSIZE _can_ handle
418 * disks > 2^32 sectors
419 */
420static sector_t bb_BLKGETSIZE_sectors(int fd)
Denis Vlasenkocdf62772008-03-17 08:42:43 +0000421{
422 uint64_t v64;
423 unsigned long longsectors;
424
425 if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
Denis Vlasenko270d5d72008-06-29 05:16:45 +0000426 /* Got bytes, convert to 512 byte sectors */
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200427 v64 >>= 9;
428 if (v64 != (sector_t)v64) {
429 ret_trunc:
430 /* Not only DOS, but all other partition tables
431 * we support can't record more than 32 bit
432 * sector counts or offsets
433 */
434 bb_error_msg("device has more than 2^32 sectors, can't use all of them");
435 v64 = (uint32_t)-1L;
436 }
437 return v64;
Denis Vlasenkocdf62772008-03-17 08:42:43 +0000438 }
439 /* Needs temp of type long */
Denys Vlasenkod958e902010-04-06 02:32:26 +0200440 if (ioctl(fd, BLKGETSIZE, &longsectors)) {
441 /* Perhaps this is a disk image */
442 off_t sz = lseek(fd, 0, SEEK_END);
Denis Vlasenkocdf62772008-03-17 08:42:43 +0000443 longsectors = 0;
Denys Vlasenkod958e902010-04-06 02:32:26 +0200444 if (sz > 0)
445 longsectors = (uoff_t)sz / sector_size;
446 lseek(fd, 0, SEEK_SET);
447 }
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200448 if (sizeof(long) > sizeof(sector_t)
449 && longsectors != (sector_t)longsectors
450 ) {
451 goto ret_trunc;
452 }
Denis Vlasenkocdf62772008-03-17 08:42:43 +0000453 return longsectors;
454}
455
456
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000457#define IS_EXTENDED(i) \
458 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
459
460#define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
461
462#define scround(x) (((x)+units_per_sector-1)/units_per_sector)
463
464#define pt_offset(b, n) \
465 ((struct partition *)((b) + 0x1be + (n) * sizeof(struct partition)))
466
467#define sector(s) ((s) & 0x3f)
468
469#define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
470
471#define hsc2sector(h,s,c) \
472 (sector(s) - 1 + sectors * ((h) + heads * cylinder(s,c)))
473
Denis Vlasenkoc033d512008-04-17 01:52:28 +0000474static void
475close_dev_fd(void)
476{
477 /* Not really closing, but making sure it is open, and to harmless place */
478 xmove_fd(xopen(bb_dev_null, O_RDONLY), dev_fd);
479}
480
Denis Vlasenkobd852072007-03-19 14:43:38 +0000481/*
Denis Vlasenko270d5d72008-06-29 05:16:45 +0000482 * Return partition name - uses static storage
Denis Vlasenkobd852072007-03-19 14:43:38 +0000483 */
484static const char *
485partname(const char *dev, int pno, int lth)
486{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000487 const char *p;
488 int w, wp;
489 int bufsiz;
490 char *bufp;
491
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000492 bufp = partname_buffer;
493 bufsiz = sizeof(partname_buffer);
Denis Vlasenkobd852072007-03-19 14:43:38 +0000494
495 w = strlen(dev);
496 p = "";
497
498 if (isdigit(dev[w-1]))
499 p = "p";
500
501 /* devfs kludge - note: fdisk partition names are not supposed
502 to equal kernel names, so there is no reason to do this */
503 if (strcmp(dev + w - 4, "disc") == 0) {
504 w -= 4;
505 p = "part";
506 }
507
508 wp = strlen(p);
509
510 if (lth) {
511 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200512 lth-wp-2, w, dev, p, pno);
Denis Vlasenkobd852072007-03-19 14:43:38 +0000513 } else {
514 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
515 }
516 return bufp;
517}
518
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000519static ALWAYS_INLINE struct partition *
Rob Landleyb73451d2006-02-24 16:29:00 +0000520get_part_table(int i)
521{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000522 return ptes[i].part_table;
523}
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000524
525static const char *
Rob Landleyb73451d2006-02-24 16:29:00 +0000526str_units(int n)
527{ /* n==1: use singular */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000528 if (n == 1)
Denis Vlasenkobd852072007-03-19 14:43:38 +0000529 return display_in_cyl_units ? "cylinder" : "sector";
530 return display_in_cyl_units ? "cylinders" : "sectors";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000531}
532
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000533static int
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000534valid_part_table_flag(const char *mbuffer)
535{
Denis Vlasenko834410a2006-11-29 12:00:28 +0000536 return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000537}
538
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200539static void fdisk_fatal(const char *why)
540{
541 if (listing) {
542 close_dev_fd();
543 longjmp(listingbuf, 1);
544 }
545 bb_error_msg_and_die(why, disk_device);
546}
547
548static void
549seek_sector(sector_t secno)
550{
551#if ENABLE_FDISK_SUPPORT_LARGE_DISKS
552 off64_t off = (off64_t)secno * sector_size;
553 if (lseek64(dev_fd, off, SEEK_SET) == (off64_t) -1)
554 fdisk_fatal(unable_to_seek);
555#else
556 uint64_t off = (uint64_t)secno * sector_size;
557 if (off > MAXINT(off_t)
558 || lseek(dev_fd, (off_t)off, SEEK_SET) == (off_t) -1
559 ) {
560 fdisk_fatal(unable_to_seek);
561 }
562#endif
563}
564
Denis Vlasenko834410a2006-11-29 12:00:28 +0000565#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200566/* Read line; return 0 or first printable char */
567static int
568read_line(const char *prompt)
569{
570 int sz;
571
Denys Vlasenko66c5b122011-02-08 05:07:02 +0100572 sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer), /*timeout*/ -1);
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200573 if (sz <= 0)
574 exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
575
576 if (line_buffer[sz-1] == '\n')
577 line_buffer[--sz] = '\0';
578
579 line_ptr = line_buffer;
580 while (*line_ptr != '\0' && (unsigned char)*line_ptr <= ' ')
581 line_ptr++;
582 return *line_ptr;
583}
584
585static void
586set_all_unchanged(void)
587{
588 int i;
589
590 for (i = 0; i < MAXIMUM_PARTS; i++)
591 ptes[i].changed = 0;
592}
593
594static ALWAYS_INLINE void
595set_changed(int i)
596{
597 ptes[i].changed = 1;
598}
599
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000600static ALWAYS_INLINE void
Denis Vlasenko834410a2006-11-29 12:00:28 +0000601write_part_table_flag(char *b)
602{
603 b[510] = 0x55;
604 b[511] = 0xaa;
605}
606
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000607static char
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000608read_nonempty(const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000609{
Denis Vlasenko9764d692008-07-09 21:20:50 +0000610 while (!read_line(mesg))
611 continue;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000612 return *line_ptr;
613}
614
615static char
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000616read_maybe_empty(const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000617{
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000618 if (!read_line(mesg)) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000619 line_ptr = line_buffer;
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000620 line_ptr[0] = '\n';
621 line_ptr[1] = '\0';
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000622 }
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000623 return line_ptr[0];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000624}
625
626static int
Denis Vlasenkobd852072007-03-19 14:43:38 +0000627read_hex(const char *const *sys)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000628{
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000629 unsigned long v;
Rob Landleyb73451d2006-02-24 16:29:00 +0000630 while (1) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000631 read_nonempty("Hex code (type L to list codes): ");
Denys Vlasenkod958e902010-04-06 02:32:26 +0200632 if ((line_ptr[0] | 0x20) == 'l') {
Rob Landleyb73451d2006-02-24 16:29:00 +0000633 list_types(sys);
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000634 continue;
Rob Landleyb73451d2006-02-24 16:29:00 +0000635 }
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000636 v = bb_strtoul(line_ptr, NULL, 16);
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200637 if (v <= 0xff)
638 return v;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000639 }
640}
641
Denis Vlasenko9764d692008-07-09 21:20:50 +0000642static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200643write_sector(sector_t secno, const void *buf)
Denis Vlasenko9764d692008-07-09 21:20:50 +0000644{
645 seek_sector(secno);
646 xwrite(dev_fd, buf, sector_size);
647}
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200648#endif /* FEATURE_FDISK_WRITABLE */
Denis Vlasenko9764d692008-07-09 21:20:50 +0000649
650
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000651#include "fdisk_aix.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000652
Denys Vlasenko36659fd2010-02-05 14:40:23 +0100653struct sun_partition {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000654 unsigned char info[128]; /* Informative text string */
655 unsigned char spare0[14];
656 struct sun_info {
657 unsigned char spare1;
658 unsigned char id;
659 unsigned char spare2;
660 unsigned char flags;
661 } infos[8];
662 unsigned char spare1[246]; /* Boot information etc. */
663 unsigned short rspeed; /* Disk rotational speed */
664 unsigned short pcylcount; /* Physical cylinder count */
665 unsigned short sparecyl; /* extra sects per cylinder */
666 unsigned char spare2[4]; /* More magic... */
667 unsigned short ilfact; /* Interleave factor */
668 unsigned short ncyl; /* Data cylinder count */
669 unsigned short nacyl; /* Alt. cylinder count */
670 unsigned short ntrks; /* Tracks per cylinder */
671 unsigned short nsect; /* Sectors per track */
672 unsigned char spare3[4]; /* Even more magic... */
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000673 struct sun_partinfo {
Eric Andersenacd244a2002-12-11 03:49:33 +0000674 uint32_t start_cylinder;
675 uint32_t num_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000676 } partitions[8];
677 unsigned short magic; /* Magic number */
678 unsigned short csum; /* Label xor'd checksum */
Denys Vlasenko36659fd2010-02-05 14:40:23 +0100679} FIX_ALIASING;
680typedef struct sun_partition sun_partition;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000681#define sunlabel ((sun_partition *)MBRbuffer)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000682STATIC_OSF void bsd_select(void);
683STATIC_OSF void xbsd_print_disklabel(int);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000684#include "fdisk_osf.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000685
Denys Vlasenkod7559c22010-10-30 02:40:08 +0200686STATIC_GPT void gpt_list_table(int xtra);
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200687#include "fdisk_gpt.c"
688
Denis Vlasenko28703012006-12-19 20:32:02 +0000689#if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000690static uint16_t
Denis Vlasenko28703012006-12-19 20:32:02 +0000691fdisk_swap16(uint16_t x)
Rob Landleyb73451d2006-02-24 16:29:00 +0000692{
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000693 return (x << 8) | (x >> 8);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000694}
695
Rob Landley88621d72006-08-29 19:41:06 +0000696static uint32_t
Denis Vlasenko28703012006-12-19 20:32:02 +0000697fdisk_swap32(uint32_t x)
Rob Landleyb73451d2006-02-24 16:29:00 +0000698{
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000699 return (x << 24) |
700 ((x & 0xFF00) << 8) |
701 ((x & 0xFF0000) >> 8) |
702 (x >> 24);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000703}
704#endif
705
Denis Vlasenkobd852072007-03-19 14:43:38 +0000706STATIC_SGI const char *const sgi_sys_types[];
Denis Vlasenko834410a2006-11-29 12:00:28 +0000707STATIC_SGI unsigned sgi_get_num_sectors(int i);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000708STATIC_SGI int sgi_get_sysid(int i);
709STATIC_SGI void sgi_delete_partition(int i);
710STATIC_SGI void sgi_change_sysid(int i, int sys);
711STATIC_SGI void sgi_list_table(int xtra);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000712#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000713STATIC_SGI void sgi_set_xcyl(void);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000714#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000715STATIC_SGI int verify_sgi(int verbose);
716STATIC_SGI void sgi_add_partition(int n, int sys);
717STATIC_SGI void sgi_set_swappartition(int i);
718STATIC_SGI const char *sgi_get_bootfile(void);
719STATIC_SGI void sgi_set_bootfile(const char* aFile);
720STATIC_SGI void create_sgiinfo(void);
721STATIC_SGI void sgi_write_table(void);
722STATIC_SGI void sgi_set_bootpartition(int i);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000723#include "fdisk_sgi.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000724
Denis Vlasenkobd852072007-03-19 14:43:38 +0000725STATIC_SUN const char *const sun_sys_types[];
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000726STATIC_SUN void sun_delete_partition(int i);
727STATIC_SUN void sun_change_sysid(int i, int sys);
728STATIC_SUN void sun_list_table(int xtra);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000729STATIC_SUN void add_sun_partition(int n, int sys);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000730#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000731STATIC_SUN void sun_set_alt_cyl(void);
732STATIC_SUN void sun_set_ncyl(int cyl);
733STATIC_SUN void sun_set_xcyl(void);
734STATIC_SUN void sun_set_ilfact(void);
735STATIC_SUN void sun_set_rspeed(void);
736STATIC_SUN void sun_set_pcylcount(void);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000737#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000738STATIC_SUN void toggle_sunflags(int i, unsigned char mask);
739STATIC_SUN void verify_sun(void);
740STATIC_SUN void sun_write_table(void);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000741#include "fdisk_sun.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000742
Denis Vlasenko9764d692008-07-09 21:20:50 +0000743
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200744static inline_if_little_endian unsigned
Rob Landleyb73451d2006-02-24 16:29:00 +0000745read4_little_endian(const unsigned char *cp)
746{
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200747 uint32_t v;
748 move_from_unaligned32(v, cp);
749 return SWAP_LE32(v);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000750}
751
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200752static sector_t
Rob Landleyb73451d2006-02-24 16:29:00 +0000753get_start_sect(const struct partition *p)
754{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000755 return read4_little_endian(p->start4);
756}
757
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200758static sector_t
759get_nr_sects(const struct partition *p)
760{
761 return read4_little_endian(p->size4);
762}
763
Denis Vlasenko834410a2006-11-29 12:00:28 +0000764#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200765/* start_sect and nr_sects are stored little endian on all machines */
766/* moreover, they are not aligned correctly */
767static inline_if_little_endian void
768store4_little_endian(unsigned char *cp, unsigned val)
769{
770 uint32_t v = SWAP_LE32(val);
771 move_to_unaligned32(cp, v);
772}
773
774static void
775set_start_sect(struct partition *p, unsigned start_sect)
776{
777 store4_little_endian(p->start4, start_sect);
778}
779
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000780static void
Denis Vlasenko28703012006-12-19 20:32:02 +0000781set_nr_sects(struct partition *p, unsigned nr_sects)
Rob Landleyb73451d2006-02-24 16:29:00 +0000782{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000783 store4_little_endian(p->size4, nr_sects);
784}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000785#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000786
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000787/* Allocate a buffer and read a partition table sector */
788static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200789read_pte(struct pte *pe, sector_t offset)
Rob Landleyb73451d2006-02-24 16:29:00 +0000790{
Denys Vlasenkod958e902010-04-06 02:32:26 +0200791 pe->offset_from_dev_start = offset;
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000792 pe->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000793 seek_sector(offset);
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000794 /* xread would make us abort - bad for fdisk -l */
Tanguy Pruvot8a6c2c22012-04-28 00:24:09 +0200795 if ((unsigned) full_read(dev_fd, pe->sectorbuffer, sector_size) != sector_size)
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000796 fdisk_fatal(unable_to_read);
Denis Vlasenko834410a2006-11-29 12:00:28 +0000797#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000798 pe->changed = 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000799#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000800 pe->part_table = pe->ext_pointer = NULL;
801}
802
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200803static sector_t
Denys Vlasenkod958e902010-04-06 02:32:26 +0200804get_partition_start_from_dev_start(const struct pte *pe)
Rob Landleyb73451d2006-02-24 16:29:00 +0000805{
Denys Vlasenkod958e902010-04-06 02:32:26 +0200806 return pe->offset_from_dev_start + get_start_sect(pe->part_table);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000807}
808
Denis Vlasenko834410a2006-11-29 12:00:28 +0000809#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000810/*
811 * Avoid warning about DOS partitions when no DOS partition was changed.
812 * Here a heuristic "is probably dos partition".
813 * We might also do the opposite and warn in all cases except
814 * for "is probably nondos partition".
815 */
Denis Vlasenko89398812008-01-25 20:18:46 +0000816#ifdef UNUSED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000817static int
Rob Landleyb73451d2006-02-24 16:29:00 +0000818is_dos_partition(int t)
819{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000820 return (t == 1 || t == 4 || t == 6 ||
821 t == 0x0b || t == 0x0c || t == 0x0e ||
822 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
823 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
824 t == 0xc1 || t == 0xc4 || t == 0xc6);
825}
Denis Vlasenko89398812008-01-25 20:18:46 +0000826#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000827
828static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000829menu(void)
830{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000831 puts("Command Action");
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000832 if (LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000833 puts("a\ttoggle a read only flag"); /* sun */
834 puts("b\tedit bsd disklabel");
835 puts("c\ttoggle the mountable flag"); /* sun */
836 puts("d\tdelete a partition");
837 puts("l\tlist known partition types");
838 puts("n\tadd a new partition");
839 puts("o\tcreate a new empty DOS partition table");
840 puts("p\tprint the partition table");
841 puts("q\tquit without saving changes");
842 puts("s\tcreate a new empty Sun disklabel"); /* sun */
843 puts("t\tchange a partition's system id");
844 puts("u\tchange display/entry units");
845 puts("v\tverify the partition table");
846 puts("w\twrite table to disk and exit");
Denis Vlasenko834410a2006-11-29 12:00:28 +0000847#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkobd852072007-03-19 14:43:38 +0000848 puts("x\textra functionality (experts only)");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000849#endif
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000850 } else if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000851 puts("a\tselect bootable partition"); /* sgi flavour */
852 puts("b\tedit bootfile entry"); /* sgi */
853 puts("c\tselect sgi swap partition"); /* sgi flavour */
854 puts("d\tdelete a partition");
855 puts("l\tlist known partition types");
856 puts("n\tadd a new partition");
857 puts("o\tcreate a new empty DOS partition table");
858 puts("p\tprint the partition table");
859 puts("q\tquit without saving changes");
860 puts("s\tcreate a new empty Sun disklabel"); /* sun */
861 puts("t\tchange a partition's system id");
862 puts("u\tchange display/entry units");
863 puts("v\tverify the partition table");
864 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000865 } else if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000866 puts("o\tcreate a new empty DOS partition table");
867 puts("q\tquit without saving changes");
868 puts("s\tcreate a new empty Sun disklabel"); /* sun */
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200869 } else if (LABEL_IS_GPT) {
870 puts("o\tcreate a new empty DOS partition table");
871 puts("p\tprint the partition table");
872 puts("q\tquit without saving changes");
873 puts("s\tcreate a new empty Sun disklabel"); /* sun */
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000874 } else {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000875 puts("a\ttoggle a bootable flag");
876 puts("b\tedit bsd disklabel");
877 puts("c\ttoggle the dos compatibility flag");
878 puts("d\tdelete a partition");
879 puts("l\tlist known partition types");
880 puts("n\tadd a new partition");
881 puts("o\tcreate a new empty DOS partition table");
882 puts("p\tprint the partition table");
883 puts("q\tquit without saving changes");
884 puts("s\tcreate a new empty Sun disklabel"); /* sun */
885 puts("t\tchange a partition's system id");
886 puts("u\tchange display/entry units");
887 puts("v\tverify the partition table");
888 puts("w\twrite table to disk and exit");
Denis Vlasenko834410a2006-11-29 12:00:28 +0000889#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkobd852072007-03-19 14:43:38 +0000890 puts("x\textra functionality (experts only)");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000891#endif
892 }
893}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000894#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000895
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000896
Denis Vlasenko834410a2006-11-29 12:00:28 +0000897#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000898static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000899xmenu(void)
900{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000901 puts("Command Action");
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000902 if (LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000903 puts("a\tchange number of alternate cylinders"); /*sun*/
904 puts("c\tchange number of cylinders");
905 puts("d\tprint the raw data in the partition table");
906 puts("e\tchange number of extra sectors per cylinder");/*sun*/
907 puts("h\tchange number of heads");
908 puts("i\tchange interleave factor"); /*sun*/
909 puts("o\tchange rotation speed (rpm)"); /*sun*/
910 puts("p\tprint the partition table");
911 puts("q\tquit without saving changes");
912 puts("r\treturn to main menu");
913 puts("s\tchange number of sectors/track");
914 puts("v\tverify the partition table");
915 puts("w\twrite table to disk and exit");
916 puts("y\tchange number of physical cylinders"); /*sun*/
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000917 } else if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000918 puts("b\tmove beginning of data in a partition"); /* !sun */
919 puts("c\tchange number of cylinders");
920 puts("d\tprint the raw data in the partition table");
921 puts("e\tlist extended partitions"); /* !sun */
922 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
923 puts("h\tchange number of heads");
924 puts("p\tprint the partition table");
925 puts("q\tquit without saving changes");
926 puts("r\treturn to main menu");
927 puts("s\tchange number of sectors/track");
928 puts("v\tverify the partition table");
929 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000930 } else if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000931 puts("b\tmove beginning of data in a partition"); /* !sun */
932 puts("c\tchange number of cylinders");
933 puts("d\tprint the raw data in the partition table");
934 puts("e\tlist extended partitions"); /* !sun */
935 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
936 puts("h\tchange number of heads");
937 puts("p\tprint the partition table");
938 puts("q\tquit without saving changes");
939 puts("r\treturn to main menu");
940 puts("s\tchange number of sectors/track");
941 puts("v\tverify the partition table");
942 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000943 } else {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000944 puts("b\tmove beginning of data in a partition"); /* !sun */
945 puts("c\tchange number of cylinders");
946 puts("d\tprint the raw data in the partition table");
947 puts("e\tlist extended partitions"); /* !sun */
948 puts("f\tfix partition order"); /* !sun, !aix, !sgi */
Denis Vlasenko834410a2006-11-29 12:00:28 +0000949#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenkobd852072007-03-19 14:43:38 +0000950 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000951#endif
Denis Vlasenkobd852072007-03-19 14:43:38 +0000952 puts("h\tchange number of heads");
953 puts("p\tprint the partition table");
954 puts("q\tquit without saving changes");
955 puts("r\treturn to main menu");
956 puts("s\tchange number of sectors/track");
957 puts("v\tverify the partition table");
958 puts("w\twrite table to disk and exit");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000959 }
960}
961#endif /* ADVANCED mode */
962
Denis Vlasenko834410a2006-11-29 12:00:28 +0000963#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenkobd852072007-03-19 14:43:38 +0000964static const char *const *
Rob Landleyb73451d2006-02-24 16:29:00 +0000965get_sys_types(void)
966{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000967 return (
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000968 LABEL_IS_SUN ? sun_sys_types :
969 LABEL_IS_SGI ? sgi_sys_types :
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000970 i386_sys_types);
971}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000972#else
973#define get_sys_types() i386_sys_types
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200974#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000975
Denis Vlasenkobd852072007-03-19 14:43:38 +0000976static const char *
977partition_type(unsigned char type)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000978{
979 int i;
Denis Vlasenkobd852072007-03-19 14:43:38 +0000980 const char *const *types = get_sys_types();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000981
Denis Vlasenkobd852072007-03-19 14:43:38 +0000982 for (i = 0; types[i]; i++)
983 if ((unsigned char)types[i][0] == type)
984 return types[i] + 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000985
Denis Vlasenkobd852072007-03-19 14:43:38 +0000986 return "Unknown";
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000987}
988
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200989static int
990is_cleared_partition(const struct partition *p)
991{
992 /* We consider partition "cleared" only if it has only zeros */
993 const char *cp = (const char *)p;
994 int cnt = sizeof(*p);
995 char bits = 0;
996 while (--cnt >= 0)
997 bits |= *cp++;
998 return (bits == 0);
999}
1000
1001static void
1002clear_partition(struct partition *p)
1003{
1004 if (p)
1005 memset(p, 0, sizeof(*p));
1006}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001007
Denis Vlasenko834410a2006-11-29 12:00:28 +00001008#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001009static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001010get_sysid(int i)
1011{
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001012 return LABEL_IS_SUN ? sunlabel->infos[i].id :
1013 (LABEL_IS_SGI ? sgi_get_sysid(i) :
1014 ptes[i].part_table->sys_ind);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001015}
1016
Denis Vlasenkobd852072007-03-19 14:43:38 +00001017static void
1018list_types(const char *const *sys)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001019{
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00001020 enum { COLS = 3 };
1021
1022 unsigned last[COLS];
1023 unsigned done, next, size;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001024 int i;
1025
Denis Vlasenko9764d692008-07-09 21:20:50 +00001026 for (size = 0; sys[size]; size++)
1027 continue;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001028
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00001029 done = 0;
1030 for (i = COLS-1; i >= 0; i--) {
1031 done += (size + i - done) / (i + 1);
1032 last[COLS-1 - i] = done;
1033 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001034
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00001035 i = done = next = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001036 do {
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00001037 printf("%c%2x %-22.22s", i ? ' ' : '\n',
Denis Vlasenkobd852072007-03-19 14:43:38 +00001038 (unsigned char)sys[next][0],
1039 sys[next] + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001040 next = last[i++] + done;
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00001041 if (i >= COLS || next >= last[i]) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001042 i = 0;
1043 next = ++done;
1044 }
1045 } while (done < last[0]);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001046 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001047}
1048
Denys Vlasenkod958e902010-04-06 02:32:26 +02001049#define set_hsc(h, s, c, sector) do \
1050{ \
1051 s = sector % g_sectors + 1; \
1052 sector /= g_sectors; \
1053 h = sector % g_heads; \
1054 sector /= g_heads; \
1055 c = sector & 0xff; \
1056 s |= (sector >> 2) & 0xc0; \
1057} while (0)
1058
1059static void set_hsc_start_end(struct partition *p, sector_t start, sector_t stop)
1060{
1061 if (dos_compatible_flag && (start / (g_sectors * g_heads) > 1023))
1062 start = g_heads * g_sectors * 1024 - 1;
1063 set_hsc(p->head, p->sector, p->cyl, start);
1064
1065 if (dos_compatible_flag && (stop / (g_sectors * g_heads) > 1023))
1066 stop = g_heads * g_sectors * 1024 - 1;
1067 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
1068}
1069
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001070static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001071set_partition(int i, int doext, sector_t start, sector_t stop, int sysid)
Rob Landleyb73451d2006-02-24 16:29:00 +00001072{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001073 struct partition *p;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001074 sector_t offset;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001075
1076 if (doext) {
1077 p = ptes[i].ext_pointer;
1078 offset = extended_offset;
1079 } else {
1080 p = ptes[i].part_table;
Denys Vlasenkod958e902010-04-06 02:32:26 +02001081 offset = ptes[i].offset_from_dev_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001082 }
1083 p->boot_ind = 0;
1084 p->sys_ind = sysid;
1085 set_start_sect(p, start - offset);
1086 set_nr_sects(p, stop - start + 1);
Denys Vlasenkod958e902010-04-06 02:32:26 +02001087 set_hsc_start_end(p, start, stop);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001088 ptes[i].changed = 1;
1089}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001090#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001091
1092static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001093warn_geometry(void)
1094{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001095 if (g_heads && g_sectors && g_cylinders)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001096 return 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001097
Denis Vlasenkobd852072007-03-19 14:43:38 +00001098 printf("Unknown value(s) for:");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001099 if (!g_heads)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001100 printf(" heads");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001101 if (!g_sectors)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001102 printf(" sectors");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001103 if (!g_cylinders)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001104 printf(" cylinders");
1105 printf(
Denis Vlasenko834410a2006-11-29 12:00:28 +00001106#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenkobd852072007-03-19 14:43:38 +00001107 " (settable in the extra functions menu)"
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001108#endif
Denis Vlasenkobd852072007-03-19 14:43:38 +00001109 "\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001110 return 1;
1111}
1112
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +00001113static void
1114update_units(void)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001115{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001116 int cyl_units = g_heads * g_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001117
1118 if (display_in_cyl_units && cyl_units)
1119 units_per_sector = cyl_units;
1120 else
1121 units_per_sector = 1; /* in sectors */
1122}
1123
Denis Vlasenko834410a2006-11-29 12:00:28 +00001124#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001125static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001126warn_cylinders(void)
1127{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001128 if (LABEL_IS_DOS && g_cylinders > 1024 && !nowarn)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001129 printf("\n"
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001130"The number of cylinders for this disk is set to %u.\n"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001131"There is nothing wrong with that, but this is larger than 1024,\n"
1132"and could in certain setups cause problems with:\n"
1133"1) software that runs at boot time (e.g., old versions of LILO)\n"
1134"2) booting and partitioning software from other OSs\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001135" (e.g., DOS FDISK, OS/2 FDISK)\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001136 g_cylinders);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001137}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001138#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001139
1140static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001141read_extended(int ext)
1142{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001143 int i;
1144 struct pte *pex;
1145 struct partition *p, *q;
1146
1147 ext_index = ext;
1148 pex = &ptes[ext];
1149 pex->ext_pointer = pex->part_table;
1150
1151 p = pex->part_table;
1152 if (!get_start_sect(p)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001153 printf("Bad offset in primary extended partition\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001154 return;
1155 }
1156
Rob Landleyb73451d2006-02-24 16:29:00 +00001157 while (IS_EXTENDED(p->sys_ind)) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001158 struct pte *pe = &ptes[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001159
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001160 if (g_partitions >= MAXIMUM_PARTS) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001161 /* This is not a Linux restriction, but
1162 this program uses arrays of size MAXIMUM_PARTS.
Denis Vlasenko89f0b342006-11-18 22:04:09 +00001163 Do not try to 'improve' this test. */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001164 struct pte *pre = &ptes[g_partitions - 1];
Denis Vlasenko834410a2006-11-29 12:00:28 +00001165#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001166 printf("Warning: deleting partitions after %u\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001167 g_partitions);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001168 pre->changed = 1;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001169#endif
1170 clear_partition(pre->ext_pointer);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001171 return;
1172 }
1173
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001174 read_pte(pe, extended_offset + get_start_sect(p));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001175
1176 if (!extended_offset)
1177 extended_offset = get_start_sect(p);
1178
1179 q = p = pt_offset(pe->sectorbuffer, 0);
1180 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001181 if (IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001182 if (pe->ext_pointer)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001183 printf("Warning: extra link "
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001184 "pointer in partition table"
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001185 " %u\n", g_partitions + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001186 else
1187 pe->ext_pointer = p;
1188 } else if (p->sys_ind) {
1189 if (pe->part_table)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001190 printf("Warning: ignoring extra "
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001191 "data in partition table"
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001192 " %u\n", g_partitions + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001193 else
1194 pe->part_table = p;
1195 }
1196 }
1197
1198 /* very strange code here... */
1199 if (!pe->part_table) {
1200 if (q != pe->ext_pointer)
1201 pe->part_table = q;
1202 else
1203 pe->part_table = q + 1;
1204 }
1205 if (!pe->ext_pointer) {
1206 if (q != pe->part_table)
1207 pe->ext_pointer = q;
1208 else
1209 pe->ext_pointer = q + 1;
1210 }
1211
1212 p = pe->ext_pointer;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001213 g_partitions++;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001214 }
1215
Denis Vlasenko834410a2006-11-29 12:00:28 +00001216#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001217 /* remove empty links */
1218 remove:
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001219 for (i = 4; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001220 struct pte *pe = &ptes[i];
1221
Denis Vlasenkobd852072007-03-19 14:43:38 +00001222 if (!get_nr_sects(pe->part_table)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001223 && (g_partitions > 5 || ptes[4].part_table->sys_ind)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001224 ) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001225 printf("Omitting empty partition (%u)\n", i+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001226 delete_partition(i);
1227 goto remove; /* numbering changed */
1228 }
1229 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001230#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001231}
1232
Denis Vlasenko834410a2006-11-29 12:00:28 +00001233#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001234static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001235create_doslabel(void)
1236{
Denis Vlasenkobd852072007-03-19 14:43:38 +00001237 printf(msg_building_new_label, "DOS disklabel");
Rob Landley5527b912006-02-25 03:46:10 +00001238
Denis Vlasenko4437d192008-04-17 00:12:10 +00001239 current_label_type = LABEL_DOS;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001240#if ENABLE_FEATURE_OSF_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001241 possibly_osf_label = 0;
1242#endif
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001243 g_partitions = 4;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001244
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001245 memset(&MBRbuffer[510 - 4*16], 0, 4*16);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001246 write_part_table_flag(MBRbuffer);
1247 extended_offset = 0;
1248 set_all_unchanged();
1249 set_changed(0);
Denis Vlasenko4437d192008-04-17 00:12:10 +00001250 get_boot(CREATE_EMPTY_DOS);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001251}
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001252#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001253
1254static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001255get_sectorsize(void)
1256{
Rob Landley736e5252006-02-25 03:36:00 +00001257 if (!user_set_sector_size) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001258 int arg;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001259 if (ioctl(dev_fd, BLKSSZGET, &arg) == 0)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001260 sector_size = arg;
1261 if (sector_size != DEFAULT_SECTOR_SIZE)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001262 printf("Note: sector size is %u "
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +00001263 "(not " DEFAULT_SECTOR_SIZE_STR ")\n",
1264 sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001265 }
1266}
1267
Rob Landley88621d72006-08-29 19:41:06 +00001268static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001269get_kernel_geometry(void)
1270{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001271 struct hd_geometry geometry;
1272
Denis Vlasenko4437d192008-04-17 00:12:10 +00001273 if (!ioctl(dev_fd, HDIO_GETGEO, &geometry)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001274 kern_heads = geometry.heads;
1275 kern_sectors = geometry.sectors;
1276 /* never use geometry.cylinders - it is truncated */
1277 }
1278}
1279
1280static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001281get_partition_table_geometry(void)
1282{
"Vladimir N. Oleynik"a972c872005-12-02 10:06:04 +00001283 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001284 struct partition *p;
1285 int i, h, s, hh, ss;
1286 int first = 1;
1287 int bad = 0;
1288
Eric Andersen3496fdc2006-01-30 23:09:20 +00001289 if (!(valid_part_table_flag((char*)bufp)))
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001290 return;
1291
1292 hh = ss = 0;
Rob Landleyb73451d2006-02-24 16:29:00 +00001293 for (i = 0; i < 4; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001294 p = pt_offset(bufp, i);
1295 if (p->sys_ind != 0) {
1296 h = p->end_head + 1;
1297 s = (p->end_sector & 077);
1298 if (first) {
1299 hh = h;
1300 ss = s;
1301 first = 0;
1302 } else if (hh != h || ss != s)
1303 bad = 1;
1304 }
1305 }
1306
1307 if (!first && !bad) {
1308 pt_heads = hh;
1309 pt_sectors = ss;
1310 }
1311}
1312
Rob Landleyb73451d2006-02-24 16:29:00 +00001313static void
1314get_geometry(void)
1315{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001316 int sec_fac;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001317
1318 get_sectorsize();
1319 sec_fac = sector_size / 512;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001320#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001321 guess_device_type();
1322#endif
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001323 g_heads = g_cylinders = g_sectors = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001324 kern_heads = kern_sectors = 0;
1325 pt_heads = pt_sectors = 0;
1326
1327 get_kernel_geometry();
1328 get_partition_table_geometry();
1329
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001330 g_heads = user_heads ? user_heads :
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001331 pt_heads ? pt_heads :
1332 kern_heads ? kern_heads : 255;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001333 g_sectors = user_sectors ? user_sectors :
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001334 pt_sectors ? pt_sectors :
1335 kern_sectors ? kern_sectors : 63;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001336 total_number_of_sectors = bb_BLKGETSIZE_sectors(dev_fd);
Eric Andersen040f4402003-07-30 08:40:37 +00001337
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001338 sector_offset = 1;
1339 if (dos_compatible_flag)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001340 sector_offset = g_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001341
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001342 g_cylinders = total_number_of_sectors / (g_heads * g_sectors * sec_fac);
1343 if (!g_cylinders)
1344 g_cylinders = user_cylinders;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001345}
1346
1347/*
Denis Vlasenko4437d192008-04-17 00:12:10 +00001348 * Opens disk_device and optionally reads MBR.
Kevin Cernekeeccb07042010-10-25 02:00:24 +02001349 * If what == OPEN_MAIN:
1350 * Open device, read MBR. Abort program on short read. Create empty
1351 * disklabel if the on-disk structure is invalid (WRITABLE mode).
1352 * If what == TRY_ONLY:
1353 * Open device, read MBR. Return an error if anything is out of place.
1354 * Do not create an empty disklabel. This is used for the "list"
1355 * operations: "fdisk -l /dev/sda" and "fdisk -l" (all devices).
1356 * If what == CREATE_EMPTY_*:
1357 * This means that get_boot() was called recursively from create_*label().
1358 * Do not re-open the device; just set up the ptes array and print
1359 * geometry warnings.
1360 *
Denis Vlasenko4437d192008-04-17 00:12:10 +00001361 * Returns:
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001362 * -1: no 0xaa55 flag present (possibly entire disk BSD)
1363 * 0: found or created label
1364 * 1: I/O error
1365 */
Denis Vlasenko85c24712008-03-17 09:04:04 +00001366#if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE
1367static int get_boot(enum action what)
1368#else
1369static int get_boot(void)
1370#define get_boot(what) get_boot()
1371#endif
Rob Landleyb73451d2006-02-24 16:29:00 +00001372{
Denis Vlasenko4437d192008-04-17 00:12:10 +00001373 int i, fd;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001374
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001375 g_partitions = 4;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001376 for (i = 0; i < 4; i++) {
1377 struct pte *pe = &ptes[i];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001378 pe->part_table = pt_offset(MBRbuffer, i);
1379 pe->ext_pointer = NULL;
Denys Vlasenkod958e902010-04-06 02:32:26 +02001380 pe->offset_from_dev_start = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001381 pe->sectorbuffer = MBRbuffer;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001382#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko4437d192008-04-17 00:12:10 +00001383 pe->changed = (what == CREATE_EMPTY_DOS);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001384#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001385 }
1386
Denis Vlasenko834410a2006-11-29 12:00:28 +00001387#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko4437d192008-04-17 00:12:10 +00001388// ALERT! highly idiotic design!
1389// We end up here when we call get_boot() recursively
1390// via get_boot() [table is bad] -> create_doslabel() -> get_boot(CREATE_EMPTY_DOS).
1391// or get_boot() [table is bad] -> create_sunlabel() -> get_boot(CREATE_EMPTY_SUN).
1392// (just factor out re-init of ptes[0,1,2,3] in a separate fn instead?)
1393// So skip opening device _again_...
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001394 if (what == CREATE_EMPTY_DOS IF_FEATURE_SUN_LABEL(|| what == CREATE_EMPTY_SUN))
Denis Vlasenko4437d192008-04-17 00:12:10 +00001395 goto created_table;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001396
Denis Vlasenko4437d192008-04-17 00:12:10 +00001397 fd = open(disk_device, (option_mask32 & OPT_l) ? O_RDONLY : O_RDWR);
1398
Denis Vlasenkobd852072007-03-19 14:43:38 +00001399 if (fd < 0) {
1400 fd = open(disk_device, O_RDONLY);
1401 if (fd < 0) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001402 if (what == TRY_ONLY)
Rob Landleyb73451d2006-02-24 16:29:00 +00001403 return 1;
1404 fdisk_fatal(unable_to_open);
Denis Vlasenko4437d192008-04-17 00:12:10 +00001405 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00001406 printf("'%s' is opened for read only\n", disk_device);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001407 }
Denis Vlasenkoc033d512008-04-17 01:52:28 +00001408 xmove_fd(fd, dev_fd);
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +00001409 if (512 != full_read(dev_fd, MBRbuffer, 512)) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001410 if (what == TRY_ONLY) {
Denis Vlasenkoc033d512008-04-17 01:52:28 +00001411 close_dev_fd();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001412 return 1;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001413 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001414 fdisk_fatal(unable_to_read);
1415 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001416#else
Denis Vlasenkobd852072007-03-19 14:43:38 +00001417 fd = open(disk_device, O_RDONLY);
1418 if (fd < 0)
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001419 return 1;
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +00001420 if (512 != full_read(fd, MBRbuffer, 512)) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001421 close(fd);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001422 return 1;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001423 }
1424 xmove_fd(fd, dev_fd);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001425#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001426
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001427 get_geometry();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001428 update_units();
1429
Denis Vlasenko834410a2006-11-29 12:00:28 +00001430#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001431 if (check_sun_label())
1432 return 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001433#endif
Denis Vlasenko834410a2006-11-29 12:00:28 +00001434#if ENABLE_FEATURE_SGI_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001435 if (check_sgi_label())
1436 return 0;
1437#endif
Denis Vlasenko834410a2006-11-29 12:00:28 +00001438#if ENABLE_FEATURE_AIX_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001439 if (check_aix_label())
1440 return 0;
1441#endif
Kevin Cernekeeccb07042010-10-25 02:00:24 +02001442#if ENABLE_FEATURE_GPT_LABEL
1443 if (check_gpt_label())
1444 return 0;
1445#endif
Denis Vlasenko834410a2006-11-29 12:00:28 +00001446#if ENABLE_FEATURE_OSF_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001447 if (check_osf_label()) {
1448 possibly_osf_label = 1;
1449 if (!valid_part_table_flag(MBRbuffer)) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001450 current_label_type = LABEL_OSF;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001451 return 0;
1452 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001453 printf("This disk has both DOS and BSD magic.\n"
1454 "Give the 'b' command to go to BSD mode.\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001455 }
1456#endif
1457
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001458#if !ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko4437d192008-04-17 00:12:10 +00001459 if (!valid_part_table_flag(MBRbuffer))
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001460 return -1;
1461#else
Denis Vlasenko4437d192008-04-17 00:12:10 +00001462 if (!valid_part_table_flag(MBRbuffer)) {
1463 if (what == OPEN_MAIN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001464 printf("Device contains neither a valid DOS "
Kevin Cernekeeccb07042010-10-25 02:00:24 +02001465 "partition table, nor Sun, SGI, OSF or GPT "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001466 "disklabel\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001467#ifdef __sparc__
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001468 IF_FEATURE_SUN_LABEL(create_sunlabel();)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001469#else
1470 create_doslabel();
1471#endif
1472 return 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001473 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00001474 /* TRY_ONLY: */
1475 return -1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001476 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00001477 created_table:
1478#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001479
Denis Vlasenko4437d192008-04-17 00:12:10 +00001480
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001481 IF_FEATURE_FDISK_WRITABLE(warn_cylinders();)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001482 warn_geometry();
1483
1484 for (i = 0; i < 4; i++) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001485 if (IS_EXTENDED(ptes[i].part_table->sys_ind)) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001486 if (g_partitions != 4)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001487 printf("Ignoring extra extended "
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001488 "partition %u\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001489 else
1490 read_extended(i);
1491 }
1492 }
1493
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001494 for (i = 3; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001495 struct pte *pe = &ptes[i];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001496 if (!valid_part_table_flag(pe->sectorbuffer)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001497 printf("Warning: invalid flag 0x%02x,0x%02x of partition "
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001498 "table %u will be corrected by w(rite)\n",
Denis Vlasenko834410a2006-11-29 12:00:28 +00001499 pe->sectorbuffer[510],
1500 pe->sectorbuffer[511],
1501 i + 1);
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001502 IF_FEATURE_FDISK_WRITABLE(pe->changed = 1;)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001503 }
1504 }
1505
1506 return 0;
1507}
1508
Denis Vlasenko834410a2006-11-29 12:00:28 +00001509#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001510/*
1511 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
1512 * If the user hits Enter, DFLT is returned.
1513 * Answers like +10 are interpreted as offsets from BASE.
1514 *
1515 * There is no default if DFLT is not between LOW and HIGH.
1516 */
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001517static sector_t
1518read_int(sector_t low, sector_t dflt, sector_t high, sector_t base, const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001519{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001520 sector_t value;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001521 int default_ok = 1;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001522 const char *fmt = "%s (%u-%u, default %u): ";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001523
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001524 if (dflt < low || dflt > high) {
1525 fmt = "%s (%u-%u): ";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001526 default_ok = 0;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001527 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001528
1529 while (1) {
1530 int use_default = default_ok;
1531
1532 /* ask question and read answer */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001533 do {
1534 printf(fmt, mesg, low, high, dflt);
1535 read_maybe_empty("");
1536 } while (*line_ptr != '\n' && !isdigit(*line_ptr)
1537 && *line_ptr != '-' && *line_ptr != '+');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001538
Eric Andersen84bdea82004-05-19 10:49:17 +00001539 if (*line_ptr == '+' || *line_ptr == '-') {
Rob Landleyb73451d2006-02-24 16:29:00 +00001540 int minus = (*line_ptr == '-');
1541 int absolute = 0;
Eric Andersenc48d49a2003-07-03 10:02:32 +00001542
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001543 value = atoi(line_ptr + 1);
Eric Andersenc48d49a2003-07-03 10:02:32 +00001544
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001545 /* (1) if 2nd char is digit, use_default = 0.
1546 * (2) move line_ptr to first non-digit. */
Rob Landleyb73451d2006-02-24 16:29:00 +00001547 while (isdigit(*++line_ptr))
1548 use_default = 0;
Eric Andersen84bdea82004-05-19 10:49:17 +00001549
Rob Landleyb73451d2006-02-24 16:29:00 +00001550 switch (*line_ptr) {
1551 case 'c':
1552 case 'C':
1553 if (!display_in_cyl_units)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001554 value *= g_heads * g_sectors;
Rob Landleyb73451d2006-02-24 16:29:00 +00001555 break;
1556 case 'K':
1557 absolute = 1024;
1558 break;
1559 case 'k':
1560 absolute = 1000;
1561 break;
1562 case 'm':
1563 case 'M':
1564 absolute = 1000000;
1565 break;
1566 case 'g':
1567 case 'G':
1568 absolute = 1000000000;
1569 break;
1570 default:
1571 break;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001572 }
Rob Landleyb73451d2006-02-24 16:29:00 +00001573 if (absolute) {
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001574 ullong bytes;
Rob Landleyb73451d2006-02-24 16:29:00 +00001575 unsigned long unit;
1576
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001577 bytes = (ullong) value * absolute;
Rob Landleyb73451d2006-02-24 16:29:00 +00001578 unit = sector_size * units_per_sector;
1579 bytes += unit/2; /* round */
1580 bytes /= unit;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001581 value = bytes;
Rob Landleyb73451d2006-02-24 16:29:00 +00001582 }
1583 if (minus)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001584 value = -value;
1585 value += base;
Eric Andersen84bdea82004-05-19 10:49:17 +00001586 } else {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001587 value = atoi(line_ptr);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001588 while (isdigit(*line_ptr)) {
1589 line_ptr++;
1590 use_default = 0;
1591 }
1592 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001593 if (use_default) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001594 value = dflt;
1595 printf("Using default value %u\n", value);
Denis Vlasenkobd852072007-03-19 14:43:38 +00001596 }
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001597 if (value >= low && value <= high)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001598 break;
Denis Vlasenkobd852072007-03-19 14:43:38 +00001599 printf("Value is out of range\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001600 }
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001601 return value;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001602}
1603
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001604static unsigned
1605get_partition(int warn, unsigned max)
Rob Landleyb73451d2006-02-24 16:29:00 +00001606{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001607 struct pte *pe;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001608 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001609
Denis Vlasenkobd852072007-03-19 14:43:38 +00001610 i = read_int(1, 0, max, 0, "Partition number") - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001611 pe = &ptes[i];
1612
1613 if (warn) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001614 if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind)
1615 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
1616 || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
1617 ) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001618 printf("Warning: partition %u has empty type\n", i+1);
Rob Landley5527b912006-02-25 03:46:10 +00001619 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001620 }
1621 return i;
1622}
1623
1624static int
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001625get_existing_partition(int warn, unsigned max)
Rob Landleyb73451d2006-02-24 16:29:00 +00001626{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001627 int pno = -1;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001628 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001629
1630 for (i = 0; i < max; i++) {
1631 struct pte *pe = &ptes[i];
1632 struct partition *p = pe->part_table;
1633
1634 if (p && !is_cleared_partition(p)) {
1635 if (pno >= 0)
1636 goto not_unique;
1637 pno = i;
1638 }
1639 }
1640 if (pno >= 0) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001641 printf("Selected partition %u\n", pno+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001642 return pno;
1643 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001644 printf("No partition is defined yet!\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001645 return -1;
1646
1647 not_unique:
1648 return get_partition(warn, max);
1649}
1650
1651static int
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001652get_nonexisting_partition(int warn, unsigned max)
Rob Landleyb73451d2006-02-24 16:29:00 +00001653{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001654 int pno = -1;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001655 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001656
1657 for (i = 0; i < max; i++) {
1658 struct pte *pe = &ptes[i];
1659 struct partition *p = pe->part_table;
1660
1661 if (p && is_cleared_partition(p)) {
1662 if (pno >= 0)
1663 goto not_unique;
1664 pno = i;
1665 }
1666 }
1667 if (pno >= 0) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001668 printf("Selected partition %u\n", pno+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001669 return pno;
1670 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001671 printf("All primary partitions have been defined already!\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001672 return -1;
1673
1674 not_unique:
1675 return get_partition(warn, max);
1676}
1677
1678
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001679static void
1680change_units(void)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001681{
1682 display_in_cyl_units = !display_in_cyl_units;
1683 update_units();
Denis Vlasenkobd852072007-03-19 14:43:38 +00001684 printf("Changing display/entry units to %s\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001685 str_units(PLURAL));
1686}
1687
1688static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001689toggle_active(int i)
1690{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001691 struct pte *pe = &ptes[i];
1692 struct partition *p = pe->part_table;
1693
Rob Landleyb73451d2006-02-24 16:29:00 +00001694 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001695 printf("WARNING: Partition %u is an extended partition\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001696 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1697 pe->changed = 1;
1698}
1699
1700static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001701toggle_dos_compatibility_flag(void)
1702{
Denis Vlasenkocdf62772008-03-17 08:42:43 +00001703 dos_compatible_flag = 1 - dos_compatible_flag;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001704 if (dos_compatible_flag) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001705 sector_offset = g_sectors;
Denis Vlasenkobd852072007-03-19 14:43:38 +00001706 printf("DOS Compatibility flag is set\n");
1707 } else {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001708 sector_offset = 1;
Denis Vlasenkobd852072007-03-19 14:43:38 +00001709 printf("DOS Compatibility flag is not set\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001710 }
1711}
1712
1713static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001714delete_partition(int i)
1715{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001716 struct pte *pe = &ptes[i];
1717 struct partition *p = pe->part_table;
1718 struct partition *q = pe->ext_pointer;
1719
1720/* Note that for the fifth partition (i == 4) we don't actually
1721 * decrement partitions.
1722 */
1723
1724 if (warn_geometry())
1725 return; /* C/H/S not set */
1726 pe->changed = 1;
1727
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001728 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001729 sun_delete_partition(i);
1730 return;
1731 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001732 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001733 sgi_delete_partition(i);
1734 return;
1735 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001736
1737 if (i < 4) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001738 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001739 g_partitions = 4;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001740 ptes[ext_index].ext_pointer = NULL;
1741 extended_offset = 0;
1742 }
1743 clear_partition(p);
1744 return;
1745 }
1746
1747 if (!q->sys_ind && i > 4) {
1748 /* the last one in the chain - just delete */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001749 --g_partitions;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001750 --i;
1751 clear_partition(ptes[i].ext_pointer);
1752 ptes[i].changed = 1;
1753 } else {
1754 /* not the last one - further ones will be moved down */
1755 if (i > 4) {
1756 /* delete this link in the chain */
1757 p = ptes[i-1].ext_pointer;
1758 *p = *q;
1759 set_start_sect(p, get_start_sect(q));
1760 set_nr_sects(p, get_nr_sects(q));
1761 ptes[i-1].changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001762 } else if (g_partitions > 5) { /* 5 will be moved to 4 */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001763 /* the first logical in a longer chain */
1764 pe = &ptes[5];
1765
1766 if (pe->part_table) /* prevent SEGFAULT */
1767 set_start_sect(pe->part_table,
Denys Vlasenkod958e902010-04-06 02:32:26 +02001768 get_partition_start_from_dev_start(pe) -
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001769 extended_offset);
Denys Vlasenkod958e902010-04-06 02:32:26 +02001770 pe->offset_from_dev_start = extended_offset;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001771 pe->changed = 1;
1772 }
1773
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001774 if (g_partitions > 5) {
1775 g_partitions--;
1776 while (i < g_partitions) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001777 ptes[i] = ptes[i+1];
1778 i++;
1779 }
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001780 } else {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001781 /* the only logical: clear only */
1782 clear_partition(ptes[i].part_table);
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001783 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001784 }
1785}
1786
1787static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001788change_sysid(void)
1789{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001790 int i, sys, origsys;
1791 struct partition *p;
1792
Eric Andersen040f4402003-07-30 08:40:37 +00001793 /* If sgi_label then don't use get_existing_partition,
1794 let the user select a partition, since get_existing_partition()
1795 only works for Linux like partition tables. */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001796 if (!LABEL_IS_SGI) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001797 i = get_existing_partition(0, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00001798 } else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001799 i = get_partition(0, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00001800 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001801 if (i == -1)
1802 return;
1803 p = ptes[i].part_table;
1804 origsys = sys = get_sysid(i);
1805
1806 /* if changing types T to 0 is allowed, then
1807 the reverse change must be allowed, too */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001808 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001809 printf("Partition %u does not exist yet!\n", i + 1);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001810 return;
1811 }
1812 while (1) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001813 sys = read_hex(get_sys_types());
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001814
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001815 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001816 printf("Type 0 means free space to many systems\n"
Rob Landleyb73451d2006-02-24 16:29:00 +00001817 "(but not to Linux). Having partitions of\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001818 "type 0 is probably unwise.\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001819 /* break; */
1820 }
1821
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001822 if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001823 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001824 printf("You cannot change a partition into"
1825 " an extended one or vice versa\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001826 break;
1827 }
1828 }
1829
1830 if (sys < 256) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001831#if ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001832 if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001833 printf("Consider leaving partition 3 "
Rob Landleyb73451d2006-02-24 16:29:00 +00001834 "as Whole disk (5),\n"
1835 "as SunOS/Solaris expects it and "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001836 "even Linux likes it\n\n");
1837#endif
1838#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001839 if (LABEL_IS_SGI &&
Rob Landley5527b912006-02-25 03:46:10 +00001840 (
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001841 (i == 10 && sys != SGI_ENTIRE_DISK) ||
Rob Landley5527b912006-02-25 03:46:10 +00001842 (i == 8 && sys != 0)
1843 )
Denis Vlasenkobd852072007-03-19 14:43:38 +00001844 ) {
1845 printf("Consider leaving partition 9 "
Rob Landleyb73451d2006-02-24 16:29:00 +00001846 "as volume header (0),\nand "
1847 "partition 11 as entire volume (6)"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001848 "as IRIX expects it\n\n");
Rob Landley5527b912006-02-25 03:46:10 +00001849 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001850#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001851 if (sys == origsys)
1852 break;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001853 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001854 sun_change_sysid(i, sys);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001855 } else if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001856 sgi_change_sysid(i, sys);
1857 } else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001858 p->sys_ind = sys;
Rob Landley5527b912006-02-25 03:46:10 +00001859
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001860 printf("Changed system type of partition %u "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001861 "to %x (%s)\n", i + 1, sys,
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001862 partition_type(sys));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001863 ptes[i].changed = 1;
Denis Vlasenkoa5549c92008-01-24 22:49:15 +00001864 //if (is_dos_partition(origsys) || is_dos_partition(sys))
1865 // dos_changed = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001866 break;
1867 }
1868 }
1869}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001870#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001871
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001872
Denis Vlasenko28703012006-12-19 20:32:02 +00001873/* check_consistency() and linear2chs() added Sat Mar 6 12:28:16 1993,
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001874 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1875 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1876 * Lubkin Oct. 1991). */
1877
Rob Landleyb73451d2006-02-24 16:29:00 +00001878static void
Denis Vlasenko28703012006-12-19 20:32:02 +00001879linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
Rob Landleyb73451d2006-02-24 16:29:00 +00001880{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001881 int spc = g_heads * g_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001882
1883 *c = ls / spc;
1884 ls = ls % spc;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001885 *h = ls / g_sectors;
1886 *s = ls % g_sectors + 1; /* sectors count from 1 */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001887}
1888
Rob Landleyb73451d2006-02-24 16:29:00 +00001889static void
1890check_consistency(const struct partition *p, int partition)
1891{
Denis Vlasenko834410a2006-11-29 12:00:28 +00001892 unsigned pbc, pbh, pbs; /* physical beginning c, h, s */
1893 unsigned pec, peh, pes; /* physical ending c, h, s */
1894 unsigned lbc, lbh, lbs; /* logical beginning c, h, s */
1895 unsigned lec, leh, les; /* logical ending c, h, s */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001896
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001897 if (!g_heads || !g_sectors || (partition >= 4))
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001898 return; /* do not check extended partitions */
1899
1900/* physical beginning c, h, s */
1901 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
1902 pbh = p->head;
1903 pbs = p->sector & 0x3f;
1904
1905/* physical ending c, h, s */
1906 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
1907 peh = p->end_head;
1908 pes = p->end_sector & 0x3f;
1909
1910/* compute logical beginning (c, h, s) */
Denis Vlasenko28703012006-12-19 20:32:02 +00001911 linear2chs(get_start_sect(p), &lbc, &lbh, &lbs);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001912
1913/* compute logical ending (c, h, s) */
Denis Vlasenko28703012006-12-19 20:32:02 +00001914 linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001915
1916/* Same physical / logical beginning? */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001917 if (g_cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001918 printf("Partition %u has different physical/logical "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001919 "beginnings (non-Linux?):\n", partition + 1);
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001920 printf(" phys=(%u, %u, %u) ", pbc, pbh, pbs);
1921 printf("logical=(%u, %u, %u)\n", lbc, lbh, lbs);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001922 }
1923
1924/* Same physical / logical ending? */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001925 if (g_cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001926 printf("Partition %u has different physical/logical "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001927 "endings:\n", partition + 1);
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001928 printf(" phys=(%u, %u, %u) ", pec, peh, pes);
1929 printf("logical=(%u, %u, %u)\n", lec, leh, les);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001930 }
1931
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001932/* Ending on cylinder boundary? */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001933 if (peh != (g_heads - 1) || pes != g_sectors) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001934 printf("Partition %u does not end on cylinder boundary\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001935 partition + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001936 }
1937}
1938
1939static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001940list_disk_geometry(void)
1941{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001942 ullong bytes = ((ullong)total_number_of_sectors << 9);
1943 long megabytes = bytes / 1000000;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001944
1945 if (megabytes < 10000)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001946 printf("\nDisk %s: %lu MB, %llu bytes\n",
1947 disk_device, megabytes, bytes);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001948 else
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001949 printf("\nDisk %s: %lu.%lu GB, %llu bytes\n",
1950 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
1951 printf("%u heads, %u sectors/track, %u cylinders",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001952 g_heads, g_sectors, g_cylinders);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001953 if (units_per_sector == 1)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001954 printf(", total %"SECT_FMT"u sectors",
1955 total_number_of_sectors / (sector_size/512));
1956 printf("\nUnits = %s of %u * %u = %u bytes\n\n",
1957 str_units(PLURAL),
1958 units_per_sector, sector_size, units_per_sector * sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001959}
1960
1961/*
1962 * Check whether partition entries are ordered by their starting positions.
1963 * Return 0 if OK. Return i if partition i should have been earlier.
1964 * Two separate checks: primary and logical partitions.
1965 */
1966static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001967wrong_p_order(int *prev)
1968{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001969 const struct pte *pe;
1970 const struct partition *p;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001971 sector_t last_p_start_pos = 0, p_start_pos;
Tanguy Pruvot8a6c2c22012-04-28 00:24:09 +02001972 int i, last_i = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001973
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001974 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001975 if (i == 4) {
1976 last_i = 4;
1977 last_p_start_pos = 0;
1978 }
1979 pe = &ptes[i];
Denis Vlasenko6bef3d12007-11-06 03:05:54 +00001980 p = pe->part_table;
1981 if (p->sys_ind) {
Denys Vlasenkod958e902010-04-06 02:32:26 +02001982 p_start_pos = get_partition_start_from_dev_start(pe);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001983
1984 if (last_p_start_pos > p_start_pos) {
1985 if (prev)
1986 *prev = last_i;
1987 return i;
1988 }
1989
1990 last_p_start_pos = p_start_pos;
1991 last_i = i;
1992 }
1993 }
1994 return 0;
1995}
1996
Denis Vlasenko834410a2006-11-29 12:00:28 +00001997#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001998/*
1999 * Fix the chain of logicals.
2000 * extended_offset is unchanged, the set of sectors used is unchanged
2001 * The chain is sorted so that sectors increase, and so that
2002 * starting sectors increase.
2003 *
2004 * After this it may still be that cfdisk doesnt like the table.
2005 * (This is because cfdisk considers expanded parts, from link to
2006 * end of partition, and these may still overlap.)
2007 * Now
2008 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
2009 * may help.
2010 */
2011static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002012fix_chain_of_logicals(void)
2013{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002014 int j, oj, ojj, sj, sjj;
2015 struct partition *pj,*pjj,tmp;
2016
2017 /* Stage 1: sort sectors but leave sector of part 4 */
2018 /* (Its sector is the global extended_offset.) */
2019 stage1:
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002020 for (j = 5; j < g_partitions - 1; j++) {
Denys Vlasenkod958e902010-04-06 02:32:26 +02002021 oj = ptes[j].offset_from_dev_start;
2022 ojj = ptes[j+1].offset_from_dev_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002023 if (oj > ojj) {
Denys Vlasenkod958e902010-04-06 02:32:26 +02002024 ptes[j].offset_from_dev_start = ojj;
2025 ptes[j+1].offset_from_dev_start = oj;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002026 pj = ptes[j].part_table;
2027 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
2028 pjj = ptes[j+1].part_table;
2029 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
2030 set_start_sect(ptes[j-1].ext_pointer,
Rob Landleyb73451d2006-02-24 16:29:00 +00002031 ojj-extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002032 set_start_sect(ptes[j].ext_pointer,
Rob Landleyb73451d2006-02-24 16:29:00 +00002033 oj-extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002034 goto stage1;
2035 }
2036 }
2037
2038 /* Stage 2: sort starting sectors */
2039 stage2:
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002040 for (j = 4; j < g_partitions - 1; j++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002041 pj = ptes[j].part_table;
2042 pjj = ptes[j+1].part_table;
2043 sj = get_start_sect(pj);
2044 sjj = get_start_sect(pjj);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002045 oj = ptes[j].offset_from_dev_start;
2046 ojj = ptes[j+1].offset_from_dev_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002047 if (oj+sj > ojj+sjj) {
2048 tmp = *pj;
2049 *pj = *pjj;
2050 *pjj = tmp;
2051 set_start_sect(pj, ojj+sjj-oj);
2052 set_start_sect(pjj, oj+sj-ojj);
2053 goto stage2;
2054 }
2055 }
2056
2057 /* Probably something was changed */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002058 for (j = 4; j < g_partitions; j++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002059 ptes[j].changed = 1;
2060}
2061
2062
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002063static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002064fix_partition_table_order(void)
2065{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002066 struct pte *pei, *pek;
2067 int i,k;
2068
2069 if (!wrong_p_order(NULL)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002070 printf("Ordering is already correct\n\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002071 return;
2072 }
2073
2074 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
2075 /* partition i should have come earlier, move it */
2076 /* We have to move data in the MBR */
2077 struct partition *pi, *pk, *pe, pbuf;
2078 pei = &ptes[i];
2079 pek = &ptes[k];
2080
2081 pe = pei->ext_pointer;
2082 pei->ext_pointer = pek->ext_pointer;
2083 pek->ext_pointer = pe;
2084
2085 pi = pei->part_table;
2086 pk = pek->part_table;
2087
2088 memmove(&pbuf, pi, sizeof(struct partition));
2089 memmove(pi, pk, sizeof(struct partition));
2090 memmove(pk, &pbuf, sizeof(struct partition));
2091
2092 pei->changed = pek->changed = 1;
2093 }
2094
2095 if (i)
2096 fix_chain_of_logicals();
2097
2098 printf("Done.\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002099}
2100#endif
2101
2102static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002103list_table(int xtra)
2104{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002105 const struct partition *p;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002106 int i, w;
2107
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002108 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002109 sun_list_table(xtra);
2110 return;
2111 }
Kevin Cernekeeccb07042010-10-25 02:00:24 +02002112 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002113 sgi_list_table(xtra);
2114 return;
2115 }
Kevin Cernekeeccb07042010-10-25 02:00:24 +02002116 if (LABEL_IS_GPT) {
2117 gpt_list_table(xtra);
2118 return;
2119 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002120
2121 list_disk_geometry();
2122
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002123 if (LABEL_IS_OSF) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002124 xbsd_print_disklabel(xtra);
2125 return;
2126 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002127
2128 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
2129 but if the device name ends in a digit, say /dev/foo1,
2130 then the partition is called /dev/foo1p3. */
2131 w = strlen(disk_device);
2132 if (w && isdigit(disk_device[w-1]))
2133 w++;
2134 if (w < 5)
2135 w = 5;
2136
Denis Vlasenkobd852072007-03-19 14:43:38 +00002137 // 1 12345678901 12345678901 12345678901 12
2138 printf("%*s Boot Start End Blocks Id System\n",
2139 w+1, "Device");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002140
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002141 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002142 const struct pte *pe = &ptes[i];
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002143 sector_t psects;
2144 sector_t pblocks;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002145 unsigned podd;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002146
2147 p = pe->part_table;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002148 if (!p || is_cleared_partition(p))
2149 continue;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002150
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002151 psects = get_nr_sects(p);
2152 pblocks = psects;
2153 podd = 0;
2154
2155 if (sector_size < 1024) {
2156 pblocks /= (1024 / sector_size);
2157 podd = psects % (1024 / sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002158 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002159 if (sector_size > 1024)
2160 pblocks *= (sector_size / 1024);
2161
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002162 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 +00002163 partname(disk_device, i+1, w+2),
2164 !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
2165 ? '*' : '?',
Denys Vlasenkod958e902010-04-06 02:32:26 +02002166 cround(get_partition_start_from_dev_start(pe)), /* start */
2167 cround(get_partition_start_from_dev_start(pe) + psects /* end */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002168 - (psects ? 1 : 0)),
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002169 pblocks, podd ? '+' : ' ', /* odd flag on end */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002170 p->sys_ind, /* type id */
2171 partition_type(p->sys_ind)); /* type name */
2172
2173 check_consistency(p, i);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002174 }
2175
2176 /* Is partition table in disk order? It need not be, but... */
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002177 /* partition table entries are not checked for correct order
2178 * if this is a sgi, sun or aix labeled disk... */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002179 if (LABEL_IS_DOS && wrong_p_order(NULL)) {
Rob Landley5527b912006-02-25 03:46:10 +00002180 /* FIXME */
Denis Vlasenkobd852072007-03-19 14:43:38 +00002181 printf("\nPartition table entries are not in disk order\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002182 }
2183}
2184
Denis Vlasenko834410a2006-11-29 12:00:28 +00002185#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002186static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002187x_list_table(int extend)
2188{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002189 const struct pte *pe;
2190 const struct partition *p;
2191 int i;
2192
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002193 printf("\nDisk %s: %u heads, %u sectors, %u cylinders\n\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002194 disk_device, g_heads, g_sectors, g_cylinders);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002195 printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002196 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002197 pe = &ptes[i];
2198 p = (extend ? pe->ext_pointer : pe->part_table);
2199 if (p != NULL) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002200 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 +00002201 i + 1, p->boot_ind, p->head,
2202 sector(p->sector),
2203 cylinder(p->sector, p->cyl), p->end_head,
2204 sector(p->end_sector),
2205 cylinder(p->end_sector, p->end_cyl),
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002206 get_start_sect(p), get_nr_sects(p),
2207 p->sys_ind);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002208 if (p->sys_ind)
2209 check_consistency(p, i);
2210 }
2211 }
2212}
2213#endif
2214
Denis Vlasenko834410a2006-11-29 12:00:28 +00002215#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002216static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002217fill_bounds(sector_t *first, sector_t *last)
Rob Landleyb73451d2006-02-24 16:29:00 +00002218{
Tanguy Pruvot8a6c2c22012-04-28 00:24:09 +02002219 int i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002220 const struct pte *pe = &ptes[0];
2221 const struct partition *p;
2222
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002223 for (i = 0; i < g_partitions; pe++,i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002224 p = pe->part_table;
Rob Landleyb73451d2006-02-24 16:29:00 +00002225 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002226 first[i] = 0xffffffff;
2227 last[i] = 0;
2228 } else {
Denys Vlasenkod958e902010-04-06 02:32:26 +02002229 first[i] = get_partition_start_from_dev_start(pe);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002230 last[i] = first[i] + get_nr_sects(p) - 1;
2231 }
2232 }
2233}
2234
2235static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002236check(int n, unsigned h, unsigned s, unsigned c, sector_t start)
Rob Landleyb73451d2006-02-24 16:29:00 +00002237{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002238 sector_t total, real_s, real_c;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002239
2240 real_s = sector(s) - 1;
2241 real_c = cylinder(s, c);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002242 total = (real_c * g_sectors + real_s) * g_heads + h;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002243 if (!total)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002244 printf("Partition %u contains sector 0\n", n);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002245 if (h >= g_heads)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002246 printf("Partition %u: head %u greater than maximum %u\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002247 n, h + 1, g_heads);
2248 if (real_s >= g_sectors)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002249 printf("Partition %u: sector %u greater than "
2250 "maximum %u\n", n, s, g_sectors);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002251 if (real_c >= g_cylinders)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002252 printf("Partition %u: cylinder %"SECT_FMT"u greater than "
2253 "maximum %u\n", n, real_c + 1, g_cylinders);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002254 if (g_cylinders <= 1024 && start != total)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002255 printf("Partition %u: previous sectors %"SECT_FMT"u disagrees with "
2256 "total %"SECT_FMT"u\n", n, start, total);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002257}
2258
2259static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002260verify(void)
2261{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002262 int i, j;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002263 sector_t total = 1;
2264 sector_t first[g_partitions], last[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002265 struct partition *p;
2266
2267 if (warn_geometry())
2268 return;
2269
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002270 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002271 verify_sun();
2272 return;
2273 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002274 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002275 verify_sgi(1);
2276 return;
2277 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002278
2279 fill_bounds(first, last);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002280 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002281 struct pte *pe = &ptes[i];
2282
2283 p = pe->part_table;
Rob Landleyb73451d2006-02-24 16:29:00 +00002284 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002285 check_consistency(p, i);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002286 if (get_partition_start_from_dev_start(pe) < first[i])
Denis Vlasenkobd852072007-03-19 14:43:38 +00002287 printf("Warning: bad start-of-data in "
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002288 "partition %u\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002289 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
2290 last[i]);
2291 total += last[i] + 1 - first[i];
Denis Vlasenkobd852072007-03-19 14:43:38 +00002292 for (j = 0; j < i; j++) {
2293 if ((first[i] >= first[j] && first[i] <= last[j])
2294 || ((last[i] <= last[j] && last[i] >= first[j]))) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002295 printf("Warning: partition %u overlaps "
2296 "partition %u\n", j + 1, i + 1);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002297 total += first[i] >= first[j] ?
2298 first[i] : first[j];
2299 total -= last[i] <= last[j] ?
2300 last[i] : last[j];
2301 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002302 }
2303 }
2304 }
2305
2306 if (extended_offset) {
2307 struct pte *pex = &ptes[ext_index];
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002308 sector_t e_last = get_start_sect(pex->part_table) +
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002309 get_nr_sects(pex->part_table) - 1;
2310
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002311 for (i = 4; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002312 total++;
2313 p = ptes[i].part_table;
2314 if (!p->sys_ind) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002315 if (i != 4 || i + 1 < g_partitions)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002316 printf("Warning: partition %u "
Denis Vlasenkobd852072007-03-19 14:43:38 +00002317 "is empty\n", i + 1);
2318 } else if (first[i] < extended_offset || last[i] > e_last) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002319 printf("Logical partition %u not entirely in "
2320 "partition %u\n", i + 1, ext_index + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002321 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002322 }
2323 }
2324
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002325 if (total > g_heads * g_sectors * g_cylinders)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002326 printf("Total allocated sectors %u greater than the maximum "
2327 "%u\n", total, g_heads * g_sectors * g_cylinders);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002328 else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002329 total = g_heads * g_sectors * g_cylinders - total;
Denis Vlasenkobd852072007-03-19 14:43:38 +00002330 if (total != 0)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002331 printf("%"SECT_FMT"u unallocated sectors\n", total);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002332 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002333}
2334
2335static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002336add_partition(int n, int sys)
2337{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002338 char mesg[256]; /* 48 does not suffice in Japanese */
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002339 int i, num_read = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002340 struct partition *p = ptes[n].part_table;
2341 struct partition *q = ptes[ext_index].part_table;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002342 sector_t limit, temp;
2343 sector_t start, stop = 0;
2344 sector_t first[g_partitions], last[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002345
2346 if (p && p->sys_ind) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002347 printf(msg_part_already_defined, n + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002348 return;
2349 }
2350 fill_bounds(first, last);
2351 if (n < 4) {
2352 start = sector_offset;
Eric Andersen040f4402003-07-30 08:40:37 +00002353 if (display_in_cyl_units || !total_number_of_sectors)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002354 limit = (sector_t) g_heads * g_sectors * g_cylinders - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002355 else
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002356 limit = total_number_of_sectors - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002357 if (extended_offset) {
2358 first[ext_index] = extended_offset;
2359 last[ext_index] = get_start_sect(q) +
2360 get_nr_sects(q) - 1;
2361 }
2362 } else {
2363 start = extended_offset + sector_offset;
2364 limit = get_start_sect(q) + get_nr_sects(q) - 1;
2365 }
2366 if (display_in_cyl_units)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002367 for (i = 0; i < g_partitions; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002368 first[i] = (cround(first[i]) - 1) * units_per_sector;
2369
Denis Vlasenkobd852072007-03-19 14:43:38 +00002370 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002371 do {
2372 temp = start;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002373 for (i = 0; i < g_partitions; i++) {
Tanguy Pruvot8a6c2c22012-04-28 00:24:09 +02002374 sector_t lastplusoff;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002375
Denys Vlasenkod958e902010-04-06 02:32:26 +02002376 if (start == ptes[i].offset_from_dev_start)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002377 start += sector_offset;
Rob Landleyb73451d2006-02-24 16:29:00 +00002378 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002379 if (start >= first[i] && start <= lastplusoff)
2380 start = lastplusoff + 1;
2381 }
2382 if (start > limit)
2383 break;
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002384 if (start >= temp+units_per_sector && num_read) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002385 printf("Sector %"SECT_FMT"u is already allocated\n", temp);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002386 temp = start;
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002387 num_read = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002388 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002389 if (!num_read && start == temp) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002390 sector_t saved_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002391
2392 saved_start = start;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002393 start = read_int(cround(saved_start), cround(saved_start), cround(limit), 0, mesg);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002394 if (display_in_cyl_units) {
2395 start = (start - 1) * units_per_sector;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002396 if (start < saved_start)
2397 start = saved_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002398 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002399 num_read = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002400 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002401 } while (start != temp || !num_read);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002402 if (n > 4) { /* NOT for fifth partition */
2403 struct pte *pe = &ptes[n];
2404
Denys Vlasenkod958e902010-04-06 02:32:26 +02002405 pe->offset_from_dev_start = start - sector_offset;
2406 if (pe->offset_from_dev_start == extended_offset) { /* must be corrected */
2407 pe->offset_from_dev_start++;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002408 if (sector_offset == 1)
2409 start++;
2410 }
2411 }
2412
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002413 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002414 struct pte *pe = &ptes[i];
2415
Denys Vlasenkod958e902010-04-06 02:32:26 +02002416 if (start < pe->offset_from_dev_start && limit >= pe->offset_from_dev_start)
2417 limit = pe->offset_from_dev_start - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002418 if (start < first[i] && limit >= first[i])
2419 limit = first[i] - 1;
2420 }
2421 if (start > limit) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002422 printf("No free sectors available\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002423 if (n > 4)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002424 g_partitions--;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002425 return;
2426 }
2427 if (cround(start) == cround(limit)) {
2428 stop = limit;
2429 } else {
2430 snprintf(mesg, sizeof(mesg),
Denis Vlasenkobd852072007-03-19 14:43:38 +00002431 "Last %s or +size or +sizeM or +sizeK",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002432 str_units(SINGULAR));
Denys Vlasenkod958e902010-04-06 02:32:26 +02002433 stop = read_int(cround(start), cround(limit), cround(limit), cround(start), mesg);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002434 if (display_in_cyl_units) {
2435 stop = stop * units_per_sector - 1;
2436 if (stop >limit)
2437 stop = limit;
2438 }
2439 }
2440
2441 set_partition(n, 0, start, stop, sys);
2442 if (n > 4)
Denys Vlasenkod958e902010-04-06 02:32:26 +02002443 set_partition(n - 1, 1, ptes[n].offset_from_dev_start, stop, EXTENDED);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002444
Rob Landleyb73451d2006-02-24 16:29:00 +00002445 if (IS_EXTENDED(sys)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002446 struct pte *pe4 = &ptes[4];
2447 struct pte *pen = &ptes[n];
2448
2449 ext_index = n;
2450 pen->ext_pointer = p;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002451 pe4->offset_from_dev_start = extended_offset = start;
Rob Landley081e3842006-08-03 20:07:35 +00002452 pe4->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002453 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2454 pe4->ext_pointer = pe4->part_table + 1;
2455 pe4->changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002456 g_partitions = 5;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002457 }
2458}
2459
2460static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002461add_logical(void)
2462{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002463 if (g_partitions > 5 || ptes[4].part_table->sys_ind) {
2464 struct pte *pe = &ptes[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002465
Rob Landley081e3842006-08-03 20:07:35 +00002466 pe->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002467 pe->part_table = pt_offset(pe->sectorbuffer, 0);
2468 pe->ext_pointer = pe->part_table + 1;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002469 pe->offset_from_dev_start = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002470 pe->changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002471 g_partitions++;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002472 }
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002473 add_partition(g_partitions - 1, LINUX_NATIVE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002474}
2475
2476static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002477new_partition(void)
2478{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002479 int i, free_primary = 0;
2480
2481 if (warn_geometry())
2482 return;
2483
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002484 if (LABEL_IS_SUN) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002485 add_sun_partition(get_partition(0, g_partitions), LINUX_NATIVE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002486 return;
2487 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002488 if (LABEL_IS_SGI) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002489 sgi_add_partition(get_partition(0, g_partitions), LINUX_NATIVE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002490 return;
2491 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002492 if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002493 printf("Sorry - this fdisk cannot handle AIX disk labels.\n"
2494"If you want to add DOS-type partitions, create a new empty DOS partition\n"
2495"table first (use 'o'). This will destroy the present disk contents.\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002496 return;
2497 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002498
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002499 for (i = 0; i < 4; i++)
2500 free_primary += !ptes[i].part_table->sys_ind;
Eric Andersenc48d49a2003-07-03 10:02:32 +00002501
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002502 if (!free_primary && g_partitions >= MAXIMUM_PARTS) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002503 printf("The maximum number of partitions has been created\n");
Eric Andersen84bdea82004-05-19 10:49:17 +00002504 return;
Rob Landleyb73451d2006-02-24 16:29:00 +00002505 }
Eric Andersenc48d49a2003-07-03 10:02:32 +00002506
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002507 if (!free_primary) {
2508 if (extended_offset)
2509 add_logical();
2510 else
Denis Vlasenkobd852072007-03-19 14:43:38 +00002511 printf("You must delete some partition and add "
2512 "an extended partition first\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002513 } else {
Denis Vlasenkodfce08f2007-03-19 14:45:10 +00002514 char c, line[80];
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00002515 snprintf(line, sizeof(line),
2516 "Command action\n"
2517 " %s\n"
2518 " p primary partition (1-4)\n",
2519 (extended_offset ?
2520 "l logical (5 or over)" : "e extended"));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002521 while (1) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002522 c = read_nonempty(line);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002523 if ((c | 0x20) == 'p') {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002524 i = get_nonexisting_partition(0, 4);
2525 if (i >= 0)
2526 add_partition(i, LINUX_NATIVE);
2527 return;
2528 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002529 if (c == 'l' && extended_offset) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002530 add_logical();
2531 return;
2532 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002533 if (c == 'e' && !extended_offset) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002534 i = get_nonexisting_partition(0, 4);
2535 if (i >= 0)
2536 add_partition(i, EXTENDED);
2537 return;
2538 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002539 printf("Invalid partition number "
2540 "for type '%c'\n", c);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002541 }
2542 }
2543}
2544
2545static void
Denys Vlasenkob347df92011-08-09 22:49:15 +02002546reread_partition_table(int leave)
2547{
2548 int i;
2549
2550 printf("Calling ioctl() to re-read partition table\n");
2551 sync();
2552 /* Users with slow external USB disks on a 320MHz ARM system (year 2011)
2553 * report that sleep is needed, otherwise BLKRRPART may fail with -EIO:
2554 */
2555 sleep(1);
2556 i = ioctl_or_perror(dev_fd, BLKRRPART, NULL,
2557 "WARNING: rereading partition table "
2558 "failed, kernel still uses old table");
2559#if 0
2560 if (dos_changed)
2561 printf(
2562 "\nWARNING: If you have created or modified any DOS 6.x\n"
2563 "partitions, please see the fdisk manual page for additional\n"
2564 "information\n");
2565#endif
2566
2567 if (leave) {
2568 if (ENABLE_FEATURE_CLEAN_UP)
2569 close_dev_fd();
2570 exit(i != 0);
2571 }
2572}
2573
2574static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002575write_table(void)
2576{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002577 int i;
2578
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002579 if (LABEL_IS_DOS) {
Rob Landleyb73451d2006-02-24 16:29:00 +00002580 for (i = 0; i < 3; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002581 if (ptes[i].changed)
2582 ptes[3].changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002583 for (i = 3; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002584 struct pte *pe = &ptes[i];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002585 if (pe->changed) {
2586 write_part_table_flag(pe->sectorbuffer);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002587 write_sector(pe->offset_from_dev_start, pe->sectorbuffer);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002588 }
2589 }
2590 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002591 else if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002592 /* no test on change? the printf below might be mistaken */
2593 sgi_write_table();
2594 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002595 else if (LABEL_IS_SUN) {
Denys Vlasenko80856b32011-07-13 09:06:32 +02002596 for (i = 0; i < 8; i++) {
2597 if (ptes[i].changed) {
2598 sun_write_table();
2599 break;
2600 }
2601 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002602 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002603
Denys Vlasenkob347df92011-08-09 22:49:15 +02002604 printf("The partition table has been altered.\n");
2605 reread_partition_table(1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002606}
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{
maxwen27116ba2015-08-14 21:41:28 +02002614 unsigned i;
2615 int l;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002616
2617 for (i = 0, l = 0; i < sector_size; i++, l++) {
2618 if (l == 0)
2619 printf("0x%03X:", i);
2620 printf(" %02X", (unsigned char) pbuffer[i]);
2621 if (l == MAX_PER_LINE - 1) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002622 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002623 l = -1;
2624 }
2625 }
2626 if (l > 0)
Denis Vlasenko4daad902007-09-27 10:20:47 +00002627 bb_putchar('\n');
2628 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002629}
2630
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002631static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002632print_raw(void)
2633{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002634 int i;
2635
Denis Vlasenkobd852072007-03-19 14:43:38 +00002636 printf("Device: %s\n", disk_device);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002637 if (LABEL_IS_SGI || LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002638 print_buffer(MBRbuffer);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002639 else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002640 for (i = 3; i < g_partitions; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002641 print_buffer(ptes[i].sectorbuffer);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002642 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002643}
2644
2645static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002646move_begin(unsigned i)
Rob Landleyb73451d2006-02-24 16:29:00 +00002647{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002648 struct pte *pe = &ptes[i];
2649 struct partition *p = pe->part_table;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002650 sector_t new, first, nr_sects;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002651
2652 if (warn_geometry())
2653 return;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002654 nr_sects = get_nr_sects(p);
2655 if (!p->sys_ind || !nr_sects || IS_EXTENDED(p->sys_ind)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002656 printf("Partition %u has no data area\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002657 return;
2658 }
Denys Vlasenkofcad7682010-04-06 16:56:33 +02002659 first = get_partition_start_from_dev_start(pe); /* == pe->offset_from_dev_start + get_start_sect(p) */
Denys Vlasenkod958e902010-04-06 02:32:26 +02002660 new = read_int(0 /*was:first*/, first, first + nr_sects - 1, first, "New beginning of data");
2661 if (new != first) {
2662 sector_t new_relative = new - pe->offset_from_dev_start;
2663 nr_sects += (get_start_sect(p) - new_relative);
2664 set_start_sect(p, new_relative);
2665 set_nr_sects(p, nr_sects);
2666 read_nonempty("Recalculate C/H/S values? (Y/N): ");
2667 if ((line_ptr[0] | 0x20) == 'y')
2668 set_hsc_start_end(p, new, new + nr_sects - 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002669 pe->changed = 1;
2670 }
2671}
2672
2673static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002674xselect(void)
2675{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002676 char c;
2677
Rob Landleyb73451d2006-02-24 16:29:00 +00002678 while (1) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002679 bb_putchar('\n');
Denys Vlasenkod958e902010-04-06 02:32:26 +02002680 c = 0x20 | read_nonempty("Expert command (m for help): ");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002681 switch (c) {
2682 case 'a':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002683 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002684 sun_set_alt_cyl();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002685 break;
2686 case 'b':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002687 if (LABEL_IS_DOS)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002688 move_begin(get_partition(0, g_partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002689 break;
2690 case 'c':
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002691 user_cylinders = g_cylinders =
2692 read_int(1, g_cylinders, 1048576, 0,
Denis Vlasenkobd852072007-03-19 14:43:38 +00002693 "Number of cylinders");
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002694 if (LABEL_IS_SUN)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002695 sun_set_ncyl(g_cylinders);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002696 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002697 warn_cylinders();
2698 break;
2699 case 'd':
2700 print_raw();
2701 break;
2702 case 'e':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002703 if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002704 sgi_set_xcyl();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002705 else if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002706 sun_set_xcyl();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002707 else if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002708 x_list_table(1);
2709 break;
2710 case 'f':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002711 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002712 fix_partition_table_order();
2713 break;
2714 case 'g':
Denis Vlasenko834410a2006-11-29 12:00:28 +00002715#if ENABLE_FEATURE_SGI_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002716 create_sgilabel();
2717#endif
2718 break;
2719 case 'h':
Denys Vlasenkod958e902010-04-06 02:32:26 +02002720 user_heads = g_heads = read_int(1, g_heads, 256, 0, "Number of heads");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002721 update_units();
2722 break;
2723 case 'i':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002724 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002725 sun_set_ilfact();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002726 break;
2727 case 'o':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002728 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002729 sun_set_rspeed();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002730 break;
2731 case 'p':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002732 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002733 list_table(1);
2734 else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002735 x_list_table(0);
2736 break;
2737 case 'q':
Denis Vlasenko4437d192008-04-17 00:12:10 +00002738 if (ENABLE_FEATURE_CLEAN_UP)
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002739 close_dev_fd();
Denis Vlasenko4daad902007-09-27 10:20:47 +00002740 bb_putchar('\n');
Bernhard Reutner-Fischer636a1f82008-05-19 09:29:47 +00002741 exit(EXIT_SUCCESS);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002742 case 'r':
2743 return;
2744 case 's':
Denys Vlasenkod958e902010-04-06 02:32:26 +02002745 user_sectors = g_sectors = read_int(1, g_sectors, 63, 0, "Number of sectors");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002746 if (dos_compatible_flag) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002747 sector_offset = g_sectors;
Denis Vlasenkobd852072007-03-19 14:43:38 +00002748 printf("Warning: setting sector offset for DOS "
2749 "compatiblity\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002750 }
2751 update_units();
2752 break;
2753 case 'v':
2754 verify();
2755 break;
2756 case 'w':
2757 write_table(); /* does not return */
2758 break;
2759 case 'y':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002760 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002761 sun_set_pcylcount();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002762 break;
2763 default:
2764 xmenu();
2765 }
2766 }
2767}
2768#endif /* ADVANCED mode */
2769
2770static int
Rob Landleyb73451d2006-02-24 16:29:00 +00002771is_ide_cdrom_or_tape(const char *device)
2772{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002773 FILE *procf;
2774 char buf[100];
2775 struct stat statbuf;
2776 int is_ide = 0;
2777
2778 /* No device was given explicitly, and we are trying some
2779 likely things. But opening /dev/hdc may produce errors like
2780 "hdc: tray open or drive not ready"
2781 if it happens to be a CD-ROM drive. It even happens that
2782 the process hangs on the attempt to read a music CD.
2783 So try to be careful. This only works since 2.1.73. */
2784
2785 if (strncmp("/dev/hd", device, 7))
2786 return 0;
2787
2788 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
Denis Vlasenko5415c852008-07-21 23:05:26 +00002789 procf = fopen_for_read(buf);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002790 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2791 is_ide = (!strncmp(buf, "cdrom", 5) ||
2792 !strncmp(buf, "tape", 4));
2793 else
2794 /* Now when this proc file does not exist, skip the
2795 device when it is read-only. */
2796 if (stat(device, &statbuf) == 0)
2797 is_ide = ((statbuf.st_mode & 0222) == 0);
2798
2799 if (procf)
2800 fclose(procf);
2801 return is_ide;
2802}
2803
Rob Landley5527b912006-02-25 03:46:10 +00002804
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002805static void
Denis Vlasenko4437d192008-04-17 00:12:10 +00002806open_list_and_close(const char *device, int user_specified)
Rob Landleyb73451d2006-02-24 16:29:00 +00002807{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002808 int gb;
2809
2810 disk_device = device;
2811 if (setjmp(listingbuf))
2812 return;
2813 if (!user_specified)
2814 if (is_ide_cdrom_or_tape(device))
2815 return;
Denis Vlasenko4437d192008-04-17 00:12:10 +00002816
2817 /* Open disk_device, save file descriptor to dev_fd */
2818 errno = 0;
2819 gb = get_boot(TRY_ONLY);
2820 if (gb > 0) { /* I/O error */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002821 /* Ignore other errors, since we try IDE
2822 and SCSI hard disks which may not be
2823 installed on the system. */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002824 if (user_specified || errno == EACCES)
2825 bb_perror_msg("can't open '%s'", device);
2826 return;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002827 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00002828
2829 if (gb < 0) { /* no DOS signature */
2830 list_disk_geometry();
2831 if (LABEL_IS_AIX)
2832 goto ret;
2833#if ENABLE_FEATURE_OSF_LABEL
2834 if (bsd_trydev(device) < 0)
2835#endif
2836 printf("Disk %s doesn't contain a valid "
2837 "partition table\n", device);
2838 } else {
2839 list_table(0);
2840#if ENABLE_FEATURE_FDISK_WRITABLE
2841 if (!LABEL_IS_SUN && g_partitions > 4) {
2842 delete_partition(ext_index);
2843 }
2844#endif
2845 }
2846 ret:
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002847 close_dev_fd();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002848}
2849
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002850/* Is it a whole disk? The digit check is still useful
2851 for Xen devices for example. */
2852static int is_whole_disk(const char *disk)
2853{
2854 unsigned len;
2855 int fd = open(disk, O_RDONLY);
2856
2857 if (fd != -1) {
2858 struct hd_geometry geometry;
2859 int err = ioctl(fd, HDIO_GETGEO, &geometry);
2860 close(fd);
2861 if (!err)
2862 return (geometry.start == 0);
2863 }
2864
2865 /* Treat "nameN" as a partition name, not whole disk */
2866 /* note: mmcblk0 should work from the geometry check above */
2867 len = strlen(disk);
2868 if (len != 0 && isdigit(disk[len - 1]))
2869 return 0;
2870
2871 return 1;
2872}
2873
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002874/* for fdisk -l: try all things in /proc/partitions
2875 that look like a partition name (do not end in a digit) */
2876static void
Denis Vlasenko4437d192008-04-17 00:12:10 +00002877list_devs_in_proc_partititons(void)
Rob Landleyb73451d2006-02-24 16:29:00 +00002878{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002879 FILE *procpt;
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002880 char line[100], ptname[100], devname[120];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002881 int ma, mi, sz;
2882
Denis Vlasenkoddec5af2006-10-26 23:25:17 +00002883 procpt = fopen_or_warn("/proc/partitions", "r");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002884
2885 while (fgets(line, sizeof(line), procpt)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002886 if (sscanf(line, " %u %u %u %[^\n ]",
Rob Landleyb73451d2006-02-24 16:29:00 +00002887 &ma, &mi, &sz, ptname) != 4)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002888 continue;
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002889
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002890 sprintf(devname, "/dev/%s", ptname);
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002891 if (is_whole_disk(devname))
2892 open_list_and_close(devname, 0);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002893 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002894#if ENABLE_FEATURE_CLEAN_UP
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002895 fclose(procpt);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002896#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002897}
2898
Denis Vlasenko834410a2006-11-29 12:00:28 +00002899#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002900static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002901unknown_command(int c)
2902{
Denis Vlasenkobd852072007-03-19 14:43:38 +00002903 printf("%c: unknown command\n", c);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002904}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002905#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002906
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00002907int fdisk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002908int fdisk_main(int argc UNUSED_PARAM, char **argv)
Rob Landleyb73451d2006-02-24 16:29:00 +00002909{
Denis Vlasenko834410a2006-11-29 12:00:28 +00002910 unsigned opt;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002911 /*
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002912 * fdisk -v
2913 * fdisk -l [-b sectorsize] [-u] device ...
2914 * fdisk -s [partition] ...
2915 * fdisk [-b sectorsize] [-u] device
2916 *
2917 * Options -C, -H, -S set the geometry.
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002918 */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002919 INIT_G();
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +00002920
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002921 close_dev_fd(); /* needed: fd 3 must not stay closed */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002922
Denis Vlasenko04e11c92008-02-10 19:44:20 +00002923 opt_complementary = "b+:C+:H+:S+"; /* numeric params */
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002924 opt = getopt32(argv, "b:C:H:lS:u" IF_FEATURE_FDISK_BLKSIZE("s"),
Denis Vlasenko04e11c92008-02-10 19:44:20 +00002925 &sector_size, &user_cylinders, &user_heads, &user_sectors);
Denis Vlasenko834410a2006-11-29 12:00:28 +00002926 argv += optind;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002927 if (opt & OPT_b) {
Denis Vlasenko834410a2006-11-29 12:00:28 +00002928 /* Ugly: this sector size is really per device,
Denys Vlasenkod958e902010-04-06 02:32:26 +02002929 * so cannot be combined with multiple disks,
2930 * and the same goes for the C/H/S options.
2931 */
2932 if (sector_size < 512
2933 || sector_size > 0x10000
2934 || (sector_size & (sector_size-1)) /* not power of 2 */
2935 ) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002936 bb_show_usage();
Denys Vlasenkod958e902010-04-06 02:32:26 +02002937 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002938 sector_offset = 2;
2939 user_set_sector_size = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002940 }
Denis Vlasenko04e11c92008-02-10 19:44:20 +00002941 if (user_heads <= 0 || user_heads >= 256)
2942 user_heads = 0;
2943 if (user_sectors <= 0 || user_sectors >= 64)
2944 user_sectors = 0;
2945 if (opt & OPT_u)
2946 display_in_cyl_units = 0; // -u
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002947
Denis Vlasenko834410a2006-11-29 12:00:28 +00002948#if ENABLE_FEATURE_FDISK_WRITABLE
2949 if (opt & OPT_l) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002950 nowarn = 1;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002951#endif
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002952 if (*argv) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002953 listing = 1;
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002954 do {
Denis Vlasenko4437d192008-04-17 00:12:10 +00002955 open_list_and_close(*argv, 1);
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002956 } while (*++argv);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002957 } else {
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002958 /* we don't have device names, */
2959 /* use /proc/partitions instead */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002960 list_devs_in_proc_partititons();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002961 }
2962 return 0;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002963#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002964 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002965#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002966
Denis Vlasenko834410a2006-11-29 12:00:28 +00002967#if ENABLE_FEATURE_FDISK_BLKSIZE
2968 if (opt & OPT_s) {
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002969 int j;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002970
2971 nowarn = 1;
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002972 if (!argv[0])
Manuel Novoa III cad53642003-03-19 09:13:01 +00002973 bb_show_usage();
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002974 for (j = 0; argv[j]; j++) {
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002975 unsigned long long size;
2976 fd = xopen(argv[j], O_RDONLY);
Denis Vlasenko4437d192008-04-17 00:12:10 +00002977 size = bb_BLKGETSIZE_sectors(fd) / 2;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002978 close(fd);
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002979 if (argv[1])
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002980 printf("%llu\n", size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002981 else
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002982 printf("%s: %llu\n", argv[j], size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002983 }
2984 return 0;
2985 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002986#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002987
Denis Vlasenko834410a2006-11-29 12:00:28 +00002988#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002989 if (!argv[0] || argv[1])
Manuel Novoa III cad53642003-03-19 09:13:01 +00002990 bb_show_usage();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002991
Denis Vlasenko834410a2006-11-29 12:00:28 +00002992 disk_device = argv[0];
Denis Vlasenko4437d192008-04-17 00:12:10 +00002993 get_boot(OPEN_MAIN);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002994
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002995 if (LABEL_IS_OSF) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002996 /* OSF label, and no DOS label */
Denis Vlasenkobd852072007-03-19 14:43:38 +00002997 printf("Detected an OSF/1 disklabel on %s, entering "
2998 "disklabel mode\n", disk_device);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +00002999 bsd_select();
Rob Landley5527b912006-02-25 03:46:10 +00003000 /*Why do we do this? It seems to be counter-intuitive*/
Denis Vlasenko4437d192008-04-17 00:12:10 +00003001 current_label_type = LABEL_DOS;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003002 /* If we return we may want to make an empty DOS label? */
3003 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003004
3005 while (1) {
Denis Vlasenko3bba5452006-12-30 17:57:03 +00003006 int c;
Denis Vlasenko4daad902007-09-27 10:20:47 +00003007 bb_putchar('\n');
Denys Vlasenkod958e902010-04-06 02:32:26 +02003008 c = 0x20 | read_nonempty("Command (m for help): ");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003009 switch (c) {
3010 case 'a':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003011 if (LABEL_IS_DOS)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003012 toggle_active(get_partition(1, g_partitions));
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003013 else if (LABEL_IS_SUN)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003014 toggle_sunflags(get_partition(1, g_partitions),
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003015 0x01);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003016 else if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003017 sgi_set_bootpartition(
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003018 get_partition(1, g_partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003019 else
3020 unknown_command(c);
3021 break;
3022 case 'b':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003023 if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00003024 printf("\nThe current boot file is: %s\n",
Rob Landleyb73451d2006-02-24 16:29:00 +00003025 sgi_get_bootfile());
Denis Vlasenkobd852072007-03-19 14:43:38 +00003026 if (read_maybe_empty("Please enter the name of the "
Tanguy Pruvot823694d2012-11-18 13:20:29 +01003027 "new boot file: ") == '\n')
Denis Vlasenkobd852072007-03-19 14:43:38 +00003028 printf("Boot file unchanged\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003029 else
3030 sgi_set_bootfile(line_ptr);
Denis Vlasenko834410a2006-11-29 12:00:28 +00003031 }
3032#if ENABLE_FEATURE_OSF_LABEL
3033 else
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +00003034 bsd_select();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003035#endif
3036 break;
3037 case 'c':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003038 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003039 toggle_dos_compatibility_flag();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003040 else if (LABEL_IS_SUN)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003041 toggle_sunflags(get_partition(1, g_partitions),
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003042 0x10);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003043 else if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003044 sgi_set_swappartition(
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003045 get_partition(1, g_partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003046 else
3047 unknown_command(c);
3048 break;
3049 case 'd':
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00003050 {
Eric Andersen040f4402003-07-30 08:40:37 +00003051 int j;
Eric Andersen040f4402003-07-30 08:40:37 +00003052 /* If sgi_label then don't use get_existing_partition,
3053 let the user select a partition, since
3054 get_existing_partition() only works for Linux-like
3055 partition tables */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003056 if (!LABEL_IS_SGI) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003057 j = get_existing_partition(1, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00003058 } else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003059 j = get_partition(1, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00003060 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00003061 if (j >= 0)
3062 delete_partition(j);
3063 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003064 break;
3065 case 'i':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003066 if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003067 create_sgiinfo();
3068 else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003069 unknown_command(c);
3070 case 'l':
3071 list_types(get_sys_types());
3072 break;
3073 case 'm':
3074 menu();
3075 break;
3076 case 'n':
3077 new_partition();
3078 break;
3079 case 'o':
3080 create_doslabel();
3081 break;
3082 case 'p':
3083 list_table(0);
3084 break;
3085 case 'q':
Denis Vlasenkoc033d512008-04-17 01:52:28 +00003086 if (ENABLE_FEATURE_CLEAN_UP)
3087 close_dev_fd();
Denis Vlasenko4daad902007-09-27 10:20:47 +00003088 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003089 return 0;
3090 case 's':
Denis Vlasenko834410a2006-11-29 12:00:28 +00003091#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003092 create_sunlabel();
3093#endif
3094 break;
3095 case 't':
3096 change_sysid();
3097 break;
3098 case 'u':
3099 change_units();
3100 break;
3101 case 'v':
3102 verify();
3103 break;
3104 case 'w':
Denys Vlasenko80856b32011-07-13 09:06:32 +02003105 write_table(); /* does not return */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003106 break;
Denis Vlasenko834410a2006-11-29 12:00:28 +00003107#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003108 case 'x':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003109 if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00003110 printf("\n\tSorry, no experts menu for SGI "
3111 "partition tables available\n\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003112 } else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003113 xselect();
3114 break;
3115#endif
3116 default:
3117 unknown_command(c);
3118 menu();
3119 }
3120 }
3121 return 0;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003122#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003123}