blob: a048dd93b9cd37e057c23c792af38dea1c9375d6 [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];
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000366 /* Raw disk label. For DOS-type partition tables the MBR,
367 * with descriptions of the primary partitions. */
368 char MBRbuffer[MAX_SECTOR_SIZE];
369 /* Partition tables */
370 struct pte ptes[MAXIMUM_PARTS];
371};
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000372#define G (*ptr_to_globals)
Denis Vlasenko270d5d72008-06-29 05:16:45 +0000373#define line_ptr (G.line_ptr )
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000374#define disk_device (G.disk_device )
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000375#define g_partitions (G.g_partitions )
376#define units_per_sector (G.units_per_sector )
377#define sector_size (G.sector_size )
378#define user_set_sector_size (G.user_set_sector_size)
379#define sector_offset (G.sector_offset )
380#define g_heads (G.g_heads )
381#define g_sectors (G.g_sectors )
382#define g_cylinders (G.g_cylinders )
383#define current_label_type (G.current_label_type )
384#define display_in_cyl_units (G.display_in_cyl_units)
385#define possibly_osf_label (G.possibly_osf_label )
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000386#define listing (G.listing )
387#define dos_compatible_flag (G.dos_compatible_flag )
388#define nowarn (G.nowarn )
389#define ext_index (G.ext_index )
390#define user_cylinders (G.user_cylinders )
391#define user_heads (G.user_heads )
392#define user_sectors (G.user_sectors )
393#define pt_heads (G.pt_heads )
394#define pt_sectors (G.pt_sectors )
395#define kern_heads (G.kern_heads )
396#define kern_sectors (G.kern_sectors )
397#define extended_offset (G.extended_offset )
398#define total_number_of_sectors (G.total_number_of_sectors)
Denis Vlasenko270d5d72008-06-29 05:16:45 +0000399#define listingbuf (G.listingbuf )
400#define line_buffer (G.line_buffer )
Denis Vlasenko270d5d72008-06-29 05:16:45 +0000401#define MBRbuffer (G.MBRbuffer )
402#define ptes (G.ptes )
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000403#define INIT_G() do { \
Denis Vlasenko574f2f42008-02-27 18:41:59 +0000404 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000405 sector_size = DEFAULT_SECTOR_SIZE; \
406 sector_offset = 1; \
407 g_partitions = 4; \
408 display_in_cyl_units = 1; \
409 units_per_sector = 1; \
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000410 dos_compatible_flag = 1; \
Denis Vlasenkof77f3692007-12-16 17:22:33 +0000411} while (0)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000412
Denis Vlasenkobd852072007-03-19 14:43:38 +0000413
Denis Vlasenkocdf62772008-03-17 08:42:43 +0000414/* TODO: move to libbb? */
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200415/* TODO: return unsigned long long, FEATURE_FDISK_BLKSIZE _can_ handle
416 * disks > 2^32 sectors
417 */
418static sector_t bb_BLKGETSIZE_sectors(int fd)
Denis Vlasenkocdf62772008-03-17 08:42:43 +0000419{
420 uint64_t v64;
421 unsigned long longsectors;
422
423 if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
Denis Vlasenko270d5d72008-06-29 05:16:45 +0000424 /* Got bytes, convert to 512 byte sectors */
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200425 v64 >>= 9;
426 if (v64 != (sector_t)v64) {
427 ret_trunc:
428 /* Not only DOS, but all other partition tables
429 * we support can't record more than 32 bit
430 * sector counts or offsets
431 */
432 bb_error_msg("device has more than 2^32 sectors, can't use all of them");
433 v64 = (uint32_t)-1L;
434 }
435 return v64;
Denis Vlasenkocdf62772008-03-17 08:42:43 +0000436 }
437 /* Needs temp of type long */
Denys Vlasenkod958e902010-04-06 02:32:26 +0200438 if (ioctl(fd, BLKGETSIZE, &longsectors)) {
439 /* Perhaps this is a disk image */
440 off_t sz = lseek(fd, 0, SEEK_END);
Denis Vlasenkocdf62772008-03-17 08:42:43 +0000441 longsectors = 0;
Denys Vlasenkod958e902010-04-06 02:32:26 +0200442 if (sz > 0)
443 longsectors = (uoff_t)sz / sector_size;
444 lseek(fd, 0, SEEK_SET);
445 }
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200446 if (sizeof(long) > sizeof(sector_t)
447 && longsectors != (sector_t)longsectors
448 ) {
449 goto ret_trunc;
450 }
Denis Vlasenkocdf62772008-03-17 08:42:43 +0000451 return longsectors;
452}
453
454
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000455#define IS_EXTENDED(i) \
456 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
457
458#define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
459
460#define scround(x) (((x)+units_per_sector-1)/units_per_sector)
461
462#define pt_offset(b, n) \
463 ((struct partition *)((b) + 0x1be + (n) * sizeof(struct partition)))
464
465#define sector(s) ((s) & 0x3f)
466
467#define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
468
Denis Vlasenkoc033d512008-04-17 01:52:28 +0000469static void
470close_dev_fd(void)
471{
472 /* Not really closing, but making sure it is open, and to harmless place */
473 xmove_fd(xopen(bb_dev_null, O_RDONLY), dev_fd);
474}
475
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000476static ALWAYS_INLINE struct partition *
Rob Landleyb73451d2006-02-24 16:29:00 +0000477get_part_table(int i)
478{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000479 return ptes[i].part_table;
480}
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000481
482static const char *
Rob Landleyb73451d2006-02-24 16:29:00 +0000483str_units(int n)
484{ /* n==1: use singular */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000485 if (n == 1)
Denis Vlasenkobd852072007-03-19 14:43:38 +0000486 return display_in_cyl_units ? "cylinder" : "sector";
487 return display_in_cyl_units ? "cylinders" : "sectors";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000488}
489
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000490static int
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000491valid_part_table_flag(const char *mbuffer)
492{
Denis Vlasenko834410a2006-11-29 12:00:28 +0000493 return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000494}
495
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200496static void fdisk_fatal(const char *why)
497{
498 if (listing) {
499 close_dev_fd();
500 longjmp(listingbuf, 1);
501 }
502 bb_error_msg_and_die(why, disk_device);
503}
504
505static void
506seek_sector(sector_t secno)
507{
508#if ENABLE_FDISK_SUPPORT_LARGE_DISKS
509 off64_t off = (off64_t)secno * sector_size;
510 if (lseek64(dev_fd, off, SEEK_SET) == (off64_t) -1)
511 fdisk_fatal(unable_to_seek);
512#else
513 uint64_t off = (uint64_t)secno * sector_size;
514 if (off > MAXINT(off_t)
515 || lseek(dev_fd, (off_t)off, SEEK_SET) == (off_t) -1
516 ) {
517 fdisk_fatal(unable_to_seek);
518 }
519#endif
520}
521
Denis Vlasenko834410a2006-11-29 12:00:28 +0000522#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200523/* Read line; return 0 or first printable char */
524static int
525read_line(const char *prompt)
526{
527 int sz;
528
Denys Vlasenko66c5b122011-02-08 05:07:02 +0100529 sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer), /*timeout*/ -1);
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200530 if (sz <= 0)
531 exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
532
533 if (line_buffer[sz-1] == '\n')
534 line_buffer[--sz] = '\0';
535
536 line_ptr = line_buffer;
537 while (*line_ptr != '\0' && (unsigned char)*line_ptr <= ' ')
538 line_ptr++;
539 return *line_ptr;
540}
541
542static void
543set_all_unchanged(void)
544{
545 int i;
546
547 for (i = 0; i < MAXIMUM_PARTS; i++)
548 ptes[i].changed = 0;
549}
550
551static ALWAYS_INLINE void
552set_changed(int i)
553{
554 ptes[i].changed = 1;
555}
556
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000557static ALWAYS_INLINE void
Denis Vlasenko834410a2006-11-29 12:00:28 +0000558write_part_table_flag(char *b)
559{
560 b[510] = 0x55;
561 b[511] = 0xaa;
562}
563
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000564static char
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000565read_nonempty(const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000566{
Denis Vlasenko9764d692008-07-09 21:20:50 +0000567 while (!read_line(mesg))
568 continue;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000569 return *line_ptr;
570}
571
572static char
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000573read_maybe_empty(const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000574{
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000575 if (!read_line(mesg)) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000576 line_ptr = line_buffer;
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000577 line_ptr[0] = '\n';
578 line_ptr[1] = '\0';
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000579 }
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000580 return line_ptr[0];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000581}
582
583static int
Denis Vlasenkobd852072007-03-19 14:43:38 +0000584read_hex(const char *const *sys)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000585{
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000586 unsigned long v;
Rob Landleyb73451d2006-02-24 16:29:00 +0000587 while (1) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000588 read_nonempty("Hex code (type L to list codes): ");
Denys Vlasenkod958e902010-04-06 02:32:26 +0200589 if ((line_ptr[0] | 0x20) == 'l') {
Rob Landleyb73451d2006-02-24 16:29:00 +0000590 list_types(sys);
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000591 continue;
Rob Landleyb73451d2006-02-24 16:29:00 +0000592 }
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000593 v = bb_strtoul(line_ptr, NULL, 16);
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200594 if (v <= 0xff)
595 return v;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000596 }
597}
598
Denis Vlasenko9764d692008-07-09 21:20:50 +0000599static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200600write_sector(sector_t secno, const void *buf)
Denis Vlasenko9764d692008-07-09 21:20:50 +0000601{
602 seek_sector(secno);
603 xwrite(dev_fd, buf, sector_size);
604}
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200605#endif /* FEATURE_FDISK_WRITABLE */
Denis Vlasenko9764d692008-07-09 21:20:50 +0000606
607
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000608#include "fdisk_aix.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000609
Denys Vlasenko36659fd2010-02-05 14:40:23 +0100610struct sun_partition {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000611 unsigned char info[128]; /* Informative text string */
612 unsigned char spare0[14];
613 struct sun_info {
614 unsigned char spare1;
615 unsigned char id;
616 unsigned char spare2;
617 unsigned char flags;
618 } infos[8];
619 unsigned char spare1[246]; /* Boot information etc. */
620 unsigned short rspeed; /* Disk rotational speed */
621 unsigned short pcylcount; /* Physical cylinder count */
622 unsigned short sparecyl; /* extra sects per cylinder */
623 unsigned char spare2[4]; /* More magic... */
624 unsigned short ilfact; /* Interleave factor */
625 unsigned short ncyl; /* Data cylinder count */
626 unsigned short nacyl; /* Alt. cylinder count */
627 unsigned short ntrks; /* Tracks per cylinder */
628 unsigned short nsect; /* Sectors per track */
629 unsigned char spare3[4]; /* Even more magic... */
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000630 struct sun_partinfo {
Eric Andersenacd244a2002-12-11 03:49:33 +0000631 uint32_t start_cylinder;
632 uint32_t num_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000633 } partitions[8];
634 unsigned short magic; /* Magic number */
635 unsigned short csum; /* Label xor'd checksum */
Denys Vlasenko36659fd2010-02-05 14:40:23 +0100636} FIX_ALIASING;
637typedef struct sun_partition sun_partition;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000638#define sunlabel ((sun_partition *)MBRbuffer)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000639STATIC_OSF void bsd_select(void);
640STATIC_OSF void xbsd_print_disklabel(int);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000641#include "fdisk_osf.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000642
Denys Vlasenkod7559c22010-10-30 02:40:08 +0200643STATIC_GPT void gpt_list_table(int xtra);
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200644#include "fdisk_gpt.c"
645
Denis Vlasenko28703012006-12-19 20:32:02 +0000646#if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000647static uint16_t
Denis Vlasenko28703012006-12-19 20:32:02 +0000648fdisk_swap16(uint16_t x)
Rob Landleyb73451d2006-02-24 16:29:00 +0000649{
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000650 return (x << 8) | (x >> 8);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000651}
652
Rob Landley88621d72006-08-29 19:41:06 +0000653static uint32_t
Denis Vlasenko28703012006-12-19 20:32:02 +0000654fdisk_swap32(uint32_t x)
Rob Landleyb73451d2006-02-24 16:29:00 +0000655{
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000656 return (x << 24) |
657 ((x & 0xFF00) << 8) |
658 ((x & 0xFF0000) >> 8) |
659 (x >> 24);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000660}
661#endif
662
Denis Vlasenkobd852072007-03-19 14:43:38 +0000663STATIC_SGI const char *const sgi_sys_types[];
Denis Vlasenko834410a2006-11-29 12:00:28 +0000664STATIC_SGI unsigned sgi_get_num_sectors(int i);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000665STATIC_SGI int sgi_get_sysid(int i);
666STATIC_SGI void sgi_delete_partition(int i);
667STATIC_SGI void sgi_change_sysid(int i, int sys);
668STATIC_SGI void sgi_list_table(int xtra);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000669#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000670STATIC_SGI void sgi_set_xcyl(void);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000671#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000672STATIC_SGI int verify_sgi(int verbose);
673STATIC_SGI void sgi_add_partition(int n, int sys);
674STATIC_SGI void sgi_set_swappartition(int i);
675STATIC_SGI const char *sgi_get_bootfile(void);
676STATIC_SGI void sgi_set_bootfile(const char* aFile);
677STATIC_SGI void create_sgiinfo(void);
678STATIC_SGI void sgi_write_table(void);
679STATIC_SGI void sgi_set_bootpartition(int i);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000680#include "fdisk_sgi.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000681
Denis Vlasenkobd852072007-03-19 14:43:38 +0000682STATIC_SUN const char *const sun_sys_types[];
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000683STATIC_SUN void sun_delete_partition(int i);
684STATIC_SUN void sun_change_sysid(int i, int sys);
685STATIC_SUN void sun_list_table(int xtra);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000686STATIC_SUN void add_sun_partition(int n, int sys);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000687#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000688STATIC_SUN void sun_set_alt_cyl(void);
689STATIC_SUN void sun_set_ncyl(int cyl);
690STATIC_SUN void sun_set_xcyl(void);
691STATIC_SUN void sun_set_ilfact(void);
692STATIC_SUN void sun_set_rspeed(void);
693STATIC_SUN void sun_set_pcylcount(void);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000694#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000695STATIC_SUN void toggle_sunflags(int i, unsigned char mask);
696STATIC_SUN void verify_sun(void);
697STATIC_SUN void sun_write_table(void);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000698#include "fdisk_sun.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000699
Denis Vlasenko9764d692008-07-09 21:20:50 +0000700
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200701static inline_if_little_endian unsigned
Rob Landleyb73451d2006-02-24 16:29:00 +0000702read4_little_endian(const unsigned char *cp)
703{
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200704 uint32_t v;
705 move_from_unaligned32(v, cp);
706 return SWAP_LE32(v);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000707}
708
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200709static sector_t
Rob Landleyb73451d2006-02-24 16:29:00 +0000710get_start_sect(const struct partition *p)
711{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000712 return read4_little_endian(p->start4);
713}
714
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200715static sector_t
716get_nr_sects(const struct partition *p)
717{
718 return read4_little_endian(p->size4);
719}
720
Denis Vlasenko834410a2006-11-29 12:00:28 +0000721#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200722/* start_sect and nr_sects are stored little endian on all machines */
723/* moreover, they are not aligned correctly */
724static inline_if_little_endian void
725store4_little_endian(unsigned char *cp, unsigned val)
726{
727 uint32_t v = SWAP_LE32(val);
728 move_to_unaligned32(cp, v);
729}
730
731static void
732set_start_sect(struct partition *p, unsigned start_sect)
733{
734 store4_little_endian(p->start4, start_sect);
735}
736
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000737static void
Denis Vlasenko28703012006-12-19 20:32:02 +0000738set_nr_sects(struct partition *p, unsigned nr_sects)
Rob Landleyb73451d2006-02-24 16:29:00 +0000739{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000740 store4_little_endian(p->size4, nr_sects);
741}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000742#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000743
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000744/* Allocate a buffer and read a partition table sector */
745static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200746read_pte(struct pte *pe, sector_t offset)
Rob Landleyb73451d2006-02-24 16:29:00 +0000747{
Denys Vlasenkod958e902010-04-06 02:32:26 +0200748 pe->offset_from_dev_start = offset;
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000749 pe->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000750 seek_sector(offset);
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000751 /* xread would make us abort - bad for fdisk -l */
752 if (full_read(dev_fd, pe->sectorbuffer, sector_size) != sector_size)
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000753 fdisk_fatal(unable_to_read);
Denis Vlasenko834410a2006-11-29 12:00:28 +0000754#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000755 pe->changed = 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000756#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000757 pe->part_table = pe->ext_pointer = NULL;
758}
759
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200760static sector_t
Denys Vlasenkod958e902010-04-06 02:32:26 +0200761get_partition_start_from_dev_start(const struct pte *pe)
Rob Landleyb73451d2006-02-24 16:29:00 +0000762{
Denys Vlasenkod958e902010-04-06 02:32:26 +0200763 return pe->offset_from_dev_start + get_start_sect(pe->part_table);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000764}
765
Denis Vlasenko834410a2006-11-29 12:00:28 +0000766#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000767/*
768 * Avoid warning about DOS partitions when no DOS partition was changed.
769 * Here a heuristic "is probably dos partition".
770 * We might also do the opposite and warn in all cases except
771 * for "is probably nondos partition".
772 */
Denis Vlasenko89398812008-01-25 20:18:46 +0000773#ifdef UNUSED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000774static int
Rob Landleyb73451d2006-02-24 16:29:00 +0000775is_dos_partition(int t)
776{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000777 return (t == 1 || t == 4 || t == 6 ||
778 t == 0x0b || t == 0x0c || t == 0x0e ||
779 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
780 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
781 t == 0xc1 || t == 0xc4 || t == 0xc6);
782}
Denis Vlasenko89398812008-01-25 20:18:46 +0000783#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000784
785static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000786menu(void)
787{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000788 puts("Command Action");
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000789 if (LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000790 puts("a\ttoggle a read only flag"); /* sun */
791 puts("b\tedit bsd disklabel");
792 puts("c\ttoggle the mountable flag"); /* sun */
793 puts("d\tdelete a partition");
794 puts("l\tlist known partition types");
795 puts("n\tadd a new partition");
796 puts("o\tcreate a new empty DOS partition table");
797 puts("p\tprint the partition table");
798 puts("q\tquit without saving changes");
799 puts("s\tcreate a new empty Sun disklabel"); /* sun */
800 puts("t\tchange a partition's system id");
801 puts("u\tchange display/entry units");
802 puts("v\tverify the partition table");
803 puts("w\twrite table to disk and exit");
Denis Vlasenko834410a2006-11-29 12:00:28 +0000804#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkobd852072007-03-19 14:43:38 +0000805 puts("x\textra functionality (experts only)");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000806#endif
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000807 } else if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000808 puts("a\tselect bootable partition"); /* sgi flavour */
809 puts("b\tedit bootfile entry"); /* sgi */
810 puts("c\tselect sgi swap partition"); /* sgi flavour */
811 puts("d\tdelete a partition");
812 puts("l\tlist known partition types");
813 puts("n\tadd a new partition");
814 puts("o\tcreate a new empty DOS partition table");
815 puts("p\tprint the partition table");
816 puts("q\tquit without saving changes");
817 puts("s\tcreate a new empty Sun disklabel"); /* sun */
818 puts("t\tchange a partition's system id");
819 puts("u\tchange display/entry units");
820 puts("v\tverify the partition table");
821 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000822 } else if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000823 puts("o\tcreate a new empty DOS partition table");
824 puts("q\tquit without saving changes");
825 puts("s\tcreate a new empty Sun disklabel"); /* sun */
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200826 } else if (LABEL_IS_GPT) {
827 puts("o\tcreate a new empty DOS partition table");
828 puts("p\tprint the partition table");
829 puts("q\tquit without saving changes");
830 puts("s\tcreate a new empty Sun disklabel"); /* sun */
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000831 } else {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000832 puts("a\ttoggle a bootable flag");
833 puts("b\tedit bsd disklabel");
834 puts("c\ttoggle the dos compatibility flag");
835 puts("d\tdelete a partition");
836 puts("l\tlist known partition types");
837 puts("n\tadd a new partition");
838 puts("o\tcreate a new empty DOS partition table");
839 puts("p\tprint the partition table");
840 puts("q\tquit without saving changes");
841 puts("s\tcreate a new empty Sun disklabel"); /* sun */
842 puts("t\tchange a partition's system id");
843 puts("u\tchange display/entry units");
844 puts("v\tverify the partition table");
845 puts("w\twrite table to disk and exit");
Denis Vlasenko834410a2006-11-29 12:00:28 +0000846#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkobd852072007-03-19 14:43:38 +0000847 puts("x\textra functionality (experts only)");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000848#endif
849 }
850}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000851#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000852
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000853
Denis Vlasenko834410a2006-11-29 12:00:28 +0000854#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000855static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000856xmenu(void)
857{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000858 puts("Command Action");
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000859 if (LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000860 puts("a\tchange number of alternate cylinders"); /*sun*/
861 puts("c\tchange number of cylinders");
862 puts("d\tprint the raw data in the partition table");
863 puts("e\tchange number of extra sectors per cylinder");/*sun*/
864 puts("h\tchange number of heads");
865 puts("i\tchange interleave factor"); /*sun*/
866 puts("o\tchange rotation speed (rpm)"); /*sun*/
867 puts("p\tprint the partition table");
868 puts("q\tquit without saving changes");
869 puts("r\treturn to main menu");
870 puts("s\tchange number of sectors/track");
871 puts("v\tverify the partition table");
872 puts("w\twrite table to disk and exit");
873 puts("y\tchange number of physical cylinders"); /*sun*/
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000874 } else if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000875 puts("b\tmove beginning of data in a partition"); /* !sun */
876 puts("c\tchange number of cylinders");
877 puts("d\tprint the raw data in the partition table");
878 puts("e\tlist extended partitions"); /* !sun */
879 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
880 puts("h\tchange number of heads");
881 puts("p\tprint the partition table");
882 puts("q\tquit without saving changes");
883 puts("r\treturn to main menu");
884 puts("s\tchange number of sectors/track");
885 puts("v\tverify the partition table");
886 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000887 } else if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000888 puts("b\tmove beginning of data in a partition"); /* !sun */
889 puts("c\tchange number of cylinders");
890 puts("d\tprint the raw data in the partition table");
891 puts("e\tlist extended partitions"); /* !sun */
892 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
893 puts("h\tchange number of heads");
894 puts("p\tprint the partition table");
895 puts("q\tquit without saving changes");
896 puts("r\treturn to main menu");
897 puts("s\tchange number of sectors/track");
898 puts("v\tverify the partition table");
899 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000900 } else {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000901 puts("b\tmove beginning of data in a partition"); /* !sun */
902 puts("c\tchange number of cylinders");
903 puts("d\tprint the raw data in the partition table");
904 puts("e\tlist extended partitions"); /* !sun */
905 puts("f\tfix partition order"); /* !sun, !aix, !sgi */
Denis Vlasenko834410a2006-11-29 12:00:28 +0000906#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenkobd852072007-03-19 14:43:38 +0000907 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000908#endif
Denis Vlasenkobd852072007-03-19 14:43:38 +0000909 puts("h\tchange number of heads");
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");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000916 }
917}
918#endif /* ADVANCED mode */
919
Denis Vlasenko834410a2006-11-29 12:00:28 +0000920#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenkobd852072007-03-19 14:43:38 +0000921static const char *const *
Rob Landleyb73451d2006-02-24 16:29:00 +0000922get_sys_types(void)
923{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000924 return (
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000925 LABEL_IS_SUN ? sun_sys_types :
926 LABEL_IS_SGI ? sgi_sys_types :
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000927 i386_sys_types);
928}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000929#else
930#define get_sys_types() i386_sys_types
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200931#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000932
Denis Vlasenkobd852072007-03-19 14:43:38 +0000933static const char *
934partition_type(unsigned char type)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000935{
936 int i;
Denis Vlasenkobd852072007-03-19 14:43:38 +0000937 const char *const *types = get_sys_types();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000938
Denis Vlasenkobd852072007-03-19 14:43:38 +0000939 for (i = 0; types[i]; i++)
940 if ((unsigned char)types[i][0] == type)
941 return types[i] + 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000942
Denis Vlasenkobd852072007-03-19 14:43:38 +0000943 return "Unknown";
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000944}
945
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200946static int
947is_cleared_partition(const struct partition *p)
948{
949 /* We consider partition "cleared" only if it has only zeros */
950 const char *cp = (const char *)p;
951 int cnt = sizeof(*p);
952 char bits = 0;
953 while (--cnt >= 0)
954 bits |= *cp++;
955 return (bits == 0);
956}
957
958static void
959clear_partition(struct partition *p)
960{
961 if (p)
962 memset(p, 0, sizeof(*p));
963}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000964
Denis Vlasenko834410a2006-11-29 12:00:28 +0000965#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000966static int
Rob Landleyb73451d2006-02-24 16:29:00 +0000967get_sysid(int i)
968{
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000969 return LABEL_IS_SUN ? sunlabel->infos[i].id :
970 (LABEL_IS_SGI ? sgi_get_sysid(i) :
971 ptes[i].part_table->sys_ind);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000972}
973
Denis Vlasenkobd852072007-03-19 14:43:38 +0000974static void
975list_types(const char *const *sys)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000976{
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000977 enum { COLS = 3 };
978
979 unsigned last[COLS];
980 unsigned done, next, size;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000981 int i;
982
Denis Vlasenko9764d692008-07-09 21:20:50 +0000983 for (size = 0; sys[size]; size++)
984 continue;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000985
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000986 done = 0;
987 for (i = COLS-1; i >= 0; i--) {
988 done += (size + i - done) / (i + 1);
989 last[COLS-1 - i] = done;
990 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000991
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000992 i = done = next = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000993 do {
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000994 printf("%c%2x %-22.22s", i ? ' ' : '\n',
Denis Vlasenkobd852072007-03-19 14:43:38 +0000995 (unsigned char)sys[next][0],
996 sys[next] + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000997 next = last[i++] + done;
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000998 if (i >= COLS || next >= last[i]) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000999 i = 0;
1000 next = ++done;
1001 }
1002 } while (done < last[0]);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001003 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001004}
1005
Denys Vlasenkod958e902010-04-06 02:32:26 +02001006#define set_hsc(h, s, c, sector) do \
1007{ \
1008 s = sector % g_sectors + 1; \
1009 sector /= g_sectors; \
1010 h = sector % g_heads; \
1011 sector /= g_heads; \
1012 c = sector & 0xff; \
1013 s |= (sector >> 2) & 0xc0; \
1014} while (0)
1015
1016static void set_hsc_start_end(struct partition *p, sector_t start, sector_t stop)
1017{
1018 if (dos_compatible_flag && (start / (g_sectors * g_heads) > 1023))
1019 start = g_heads * g_sectors * 1024 - 1;
1020 set_hsc(p->head, p->sector, p->cyl, start);
1021
1022 if (dos_compatible_flag && (stop / (g_sectors * g_heads) > 1023))
1023 stop = g_heads * g_sectors * 1024 - 1;
1024 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
1025}
1026
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001027static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001028set_partition(int i, int doext, sector_t start, sector_t stop, int sysid)
Rob Landleyb73451d2006-02-24 16:29:00 +00001029{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001030 struct partition *p;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001031 sector_t offset;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001032
1033 if (doext) {
1034 p = ptes[i].ext_pointer;
1035 offset = extended_offset;
1036 } else {
1037 p = ptes[i].part_table;
Denys Vlasenkod958e902010-04-06 02:32:26 +02001038 offset = ptes[i].offset_from_dev_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001039 }
1040 p->boot_ind = 0;
1041 p->sys_ind = sysid;
1042 set_start_sect(p, start - offset);
1043 set_nr_sects(p, stop - start + 1);
Denys Vlasenkod958e902010-04-06 02:32:26 +02001044 set_hsc_start_end(p, start, stop);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001045 ptes[i].changed = 1;
1046}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001047#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001048
1049static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001050warn_geometry(void)
1051{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001052 if (g_heads && g_sectors && g_cylinders)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001053 return 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001054
Denis Vlasenkobd852072007-03-19 14:43:38 +00001055 printf("Unknown value(s) for:");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001056 if (!g_heads)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001057 printf(" heads");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001058 if (!g_sectors)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001059 printf(" sectors");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001060 if (!g_cylinders)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001061 printf(" cylinders");
Denis Vlasenko834410a2006-11-29 12:00:28 +00001062#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001063 puts(" (settable in the extra functions menu)");
1064#else
1065 bb_putchar('\n');
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001066#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001067 return 1;
1068}
1069
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +00001070static void
1071update_units(void)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001072{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001073 int cyl_units = g_heads * g_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001074
1075 if (display_in_cyl_units && cyl_units)
1076 units_per_sector = cyl_units;
1077 else
1078 units_per_sector = 1; /* in sectors */
1079}
1080
Denis Vlasenko834410a2006-11-29 12:00:28 +00001081#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001082static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001083warn_cylinders(void)
1084{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001085 if (LABEL_IS_DOS && g_cylinders > 1024 && !nowarn)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001086 printf("\n"
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001087"The number of cylinders for this disk is set to %u.\n"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001088"There is nothing wrong with that, but this is larger than 1024,\n"
1089"and could in certain setups cause problems with:\n"
1090"1) software that runs at boot time (e.g., old versions of LILO)\n"
1091"2) booting and partitioning software from other OSs\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001092" (e.g., DOS FDISK, OS/2 FDISK)\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001093 g_cylinders);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001094}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001095#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001096
1097static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001098read_extended(int ext)
1099{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001100 int i;
1101 struct pte *pex;
1102 struct partition *p, *q;
1103
1104 ext_index = ext;
1105 pex = &ptes[ext];
1106 pex->ext_pointer = pex->part_table;
1107
1108 p = pex->part_table;
1109 if (!get_start_sect(p)) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001110 puts("Bad offset in primary extended partition");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001111 return;
1112 }
1113
Rob Landleyb73451d2006-02-24 16:29:00 +00001114 while (IS_EXTENDED(p->sys_ind)) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001115 struct pte *pe = &ptes[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001116
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001117 if (g_partitions >= MAXIMUM_PARTS) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001118 /* This is not a Linux restriction, but
1119 this program uses arrays of size MAXIMUM_PARTS.
Denis Vlasenko89f0b342006-11-18 22:04:09 +00001120 Do not try to 'improve' this test. */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001121 struct pte *pre = &ptes[g_partitions - 1];
Denis Vlasenko834410a2006-11-29 12:00:28 +00001122#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001123 printf("Warning: deleting partitions after %u\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001124 g_partitions);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001125 pre->changed = 1;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001126#endif
1127 clear_partition(pre->ext_pointer);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001128 return;
1129 }
1130
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001131 read_pte(pe, extended_offset + get_start_sect(p));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001132
1133 if (!extended_offset)
1134 extended_offset = get_start_sect(p);
1135
1136 q = p = pt_offset(pe->sectorbuffer, 0);
1137 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001138 if (IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001139 if (pe->ext_pointer)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001140 printf("Warning: extra link "
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001141 "pointer in partition table"
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001142 " %u\n", g_partitions + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001143 else
1144 pe->ext_pointer = p;
1145 } else if (p->sys_ind) {
1146 if (pe->part_table)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001147 printf("Warning: ignoring extra "
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001148 "data in partition table"
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001149 " %u\n", g_partitions + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001150 else
1151 pe->part_table = p;
1152 }
1153 }
1154
1155 /* very strange code here... */
1156 if (!pe->part_table) {
1157 if (q != pe->ext_pointer)
1158 pe->part_table = q;
1159 else
1160 pe->part_table = q + 1;
1161 }
1162 if (!pe->ext_pointer) {
1163 if (q != pe->part_table)
1164 pe->ext_pointer = q;
1165 else
1166 pe->ext_pointer = q + 1;
1167 }
1168
1169 p = pe->ext_pointer;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001170 g_partitions++;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001171 }
1172
Denis Vlasenko834410a2006-11-29 12:00:28 +00001173#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001174 /* remove empty links */
1175 remove:
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001176 for (i = 4; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001177 struct pte *pe = &ptes[i];
1178
Denis Vlasenkobd852072007-03-19 14:43:38 +00001179 if (!get_nr_sects(pe->part_table)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001180 && (g_partitions > 5 || ptes[4].part_table->sys_ind)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001181 ) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001182 printf("Omitting empty partition (%u)\n", i+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001183 delete_partition(i);
1184 goto remove; /* numbering changed */
1185 }
1186 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001187#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001188}
1189
Denis Vlasenko834410a2006-11-29 12:00:28 +00001190#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001191static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001192create_doslabel(void)
1193{
Denis Vlasenkobd852072007-03-19 14:43:38 +00001194 printf(msg_building_new_label, "DOS disklabel");
Rob Landley5527b912006-02-25 03:46:10 +00001195
Denis Vlasenko4437d192008-04-17 00:12:10 +00001196 current_label_type = LABEL_DOS;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001197#if ENABLE_FEATURE_OSF_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001198 possibly_osf_label = 0;
1199#endif
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001200 g_partitions = 4;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001201
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001202 memset(&MBRbuffer[510 - 4*16], 0, 4*16);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001203 write_part_table_flag(MBRbuffer);
1204 extended_offset = 0;
1205 set_all_unchanged();
1206 set_changed(0);
Denis Vlasenko4437d192008-04-17 00:12:10 +00001207 get_boot(CREATE_EMPTY_DOS);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001208}
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001209#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001210
1211static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001212get_sectorsize(void)
1213{
Rob Landley736e5252006-02-25 03:36:00 +00001214 if (!user_set_sector_size) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001215 int arg;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001216 if (ioctl(dev_fd, BLKSSZGET, &arg) == 0)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001217 sector_size = arg;
1218 if (sector_size != DEFAULT_SECTOR_SIZE)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001219 printf("Note: sector size is %u "
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +00001220 "(not " DEFAULT_SECTOR_SIZE_STR ")\n",
1221 sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001222 }
1223}
1224
Rob Landley88621d72006-08-29 19:41:06 +00001225static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001226get_kernel_geometry(void)
1227{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001228 struct hd_geometry geometry;
1229
Denis Vlasenko4437d192008-04-17 00:12:10 +00001230 if (!ioctl(dev_fd, HDIO_GETGEO, &geometry)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001231 kern_heads = geometry.heads;
1232 kern_sectors = geometry.sectors;
1233 /* never use geometry.cylinders - it is truncated */
1234 }
1235}
1236
1237static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001238get_partition_table_geometry(void)
1239{
"Vladimir N. Oleynik"a972c872005-12-02 10:06:04 +00001240 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001241 struct partition *p;
1242 int i, h, s, hh, ss;
1243 int first = 1;
1244 int bad = 0;
1245
Eric Andersen3496fdc2006-01-30 23:09:20 +00001246 if (!(valid_part_table_flag((char*)bufp)))
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001247 return;
1248
1249 hh = ss = 0;
Rob Landleyb73451d2006-02-24 16:29:00 +00001250 for (i = 0; i < 4; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001251 p = pt_offset(bufp, i);
1252 if (p->sys_ind != 0) {
1253 h = p->end_head + 1;
1254 s = (p->end_sector & 077);
1255 if (first) {
1256 hh = h;
1257 ss = s;
1258 first = 0;
1259 } else if (hh != h || ss != s)
1260 bad = 1;
1261 }
1262 }
1263
1264 if (!first && !bad) {
1265 pt_heads = hh;
1266 pt_sectors = ss;
1267 }
1268}
1269
Rob Landleyb73451d2006-02-24 16:29:00 +00001270static void
1271get_geometry(void)
1272{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001273 int sec_fac;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001274
1275 get_sectorsize();
1276 sec_fac = sector_size / 512;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001277#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001278 guess_device_type();
1279#endif
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001280 g_heads = g_cylinders = g_sectors = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001281 kern_heads = kern_sectors = 0;
1282 pt_heads = pt_sectors = 0;
1283
1284 get_kernel_geometry();
1285 get_partition_table_geometry();
1286
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001287 g_heads = user_heads ? user_heads :
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001288 pt_heads ? pt_heads :
1289 kern_heads ? kern_heads : 255;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001290 g_sectors = user_sectors ? user_sectors :
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001291 pt_sectors ? pt_sectors :
1292 kern_sectors ? kern_sectors : 63;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001293 total_number_of_sectors = bb_BLKGETSIZE_sectors(dev_fd);
Eric Andersen040f4402003-07-30 08:40:37 +00001294
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001295 sector_offset = 1;
1296 if (dos_compatible_flag)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001297 sector_offset = g_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001298
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001299 g_cylinders = total_number_of_sectors / (g_heads * g_sectors * sec_fac);
1300 if (!g_cylinders)
1301 g_cylinders = user_cylinders;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001302}
1303
1304/*
Denis Vlasenko4437d192008-04-17 00:12:10 +00001305 * Opens disk_device and optionally reads MBR.
Kevin Cernekeeccb07042010-10-25 02:00:24 +02001306 * If what == OPEN_MAIN:
1307 * Open device, read MBR. Abort program on short read. Create empty
1308 * disklabel if the on-disk structure is invalid (WRITABLE mode).
1309 * If what == TRY_ONLY:
1310 * Open device, read MBR. Return an error if anything is out of place.
1311 * Do not create an empty disklabel. This is used for the "list"
1312 * operations: "fdisk -l /dev/sda" and "fdisk -l" (all devices).
1313 * If what == CREATE_EMPTY_*:
1314 * This means that get_boot() was called recursively from create_*label().
1315 * Do not re-open the device; just set up the ptes array and print
1316 * geometry warnings.
1317 *
Denis Vlasenko4437d192008-04-17 00:12:10 +00001318 * Returns:
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001319 * -1: no 0xaa55 flag present (possibly entire disk BSD)
1320 * 0: found or created label
1321 * 1: I/O error
1322 */
Denis Vlasenko85c24712008-03-17 09:04:04 +00001323#if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE
1324static int get_boot(enum action what)
1325#else
1326static int get_boot(void)
1327#define get_boot(what) get_boot()
1328#endif
Rob Landleyb73451d2006-02-24 16:29:00 +00001329{
Denis Vlasenko4437d192008-04-17 00:12:10 +00001330 int i, fd;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001331
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001332 g_partitions = 4;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001333 for (i = 0; i < 4; i++) {
1334 struct pte *pe = &ptes[i];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001335 pe->part_table = pt_offset(MBRbuffer, i);
1336 pe->ext_pointer = NULL;
Denys Vlasenkod958e902010-04-06 02:32:26 +02001337 pe->offset_from_dev_start = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001338 pe->sectorbuffer = MBRbuffer;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001339#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko4437d192008-04-17 00:12:10 +00001340 pe->changed = (what == CREATE_EMPTY_DOS);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001341#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001342 }
1343
Denis Vlasenko834410a2006-11-29 12:00:28 +00001344#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko4437d192008-04-17 00:12:10 +00001345// ALERT! highly idiotic design!
1346// We end up here when we call get_boot() recursively
1347// via get_boot() [table is bad] -> create_doslabel() -> get_boot(CREATE_EMPTY_DOS).
1348// or get_boot() [table is bad] -> create_sunlabel() -> get_boot(CREATE_EMPTY_SUN).
1349// (just factor out re-init of ptes[0,1,2,3] in a separate fn instead?)
1350// So skip opening device _again_...
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001351 if (what == CREATE_EMPTY_DOS IF_FEATURE_SUN_LABEL(|| what == CREATE_EMPTY_SUN))
Denis Vlasenko4437d192008-04-17 00:12:10 +00001352 goto created_table;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001353
Denis Vlasenko4437d192008-04-17 00:12:10 +00001354 fd = open(disk_device, (option_mask32 & OPT_l) ? O_RDONLY : O_RDWR);
1355
Denis Vlasenkobd852072007-03-19 14:43:38 +00001356 if (fd < 0) {
1357 fd = open(disk_device, O_RDONLY);
1358 if (fd < 0) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001359 if (what == TRY_ONLY)
Rob Landleyb73451d2006-02-24 16:29:00 +00001360 return 1;
1361 fdisk_fatal(unable_to_open);
Denis Vlasenko4437d192008-04-17 00:12:10 +00001362 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00001363 printf("'%s' is opened for read only\n", disk_device);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001364 }
Denis Vlasenkoc033d512008-04-17 01:52:28 +00001365 xmove_fd(fd, dev_fd);
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +00001366 if (512 != full_read(dev_fd, MBRbuffer, 512)) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001367 if (what == TRY_ONLY) {
Denis Vlasenkoc033d512008-04-17 01:52:28 +00001368 close_dev_fd();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001369 return 1;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001370 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001371 fdisk_fatal(unable_to_read);
1372 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001373#else
Denis Vlasenkobd852072007-03-19 14:43:38 +00001374 fd = open(disk_device, O_RDONLY);
1375 if (fd < 0)
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001376 return 1;
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +00001377 if (512 != full_read(fd, MBRbuffer, 512)) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001378 close(fd);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001379 return 1;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001380 }
1381 xmove_fd(fd, dev_fd);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001382#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001383
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001384 get_geometry();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001385 update_units();
1386
Denis Vlasenko834410a2006-11-29 12:00:28 +00001387#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001388 if (check_sun_label())
1389 return 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001390#endif
Denis Vlasenko834410a2006-11-29 12:00:28 +00001391#if ENABLE_FEATURE_SGI_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001392 if (check_sgi_label())
1393 return 0;
1394#endif
Denis Vlasenko834410a2006-11-29 12:00:28 +00001395#if ENABLE_FEATURE_AIX_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001396 if (check_aix_label())
1397 return 0;
1398#endif
Kevin Cernekeeccb07042010-10-25 02:00:24 +02001399#if ENABLE_FEATURE_GPT_LABEL
1400 if (check_gpt_label())
1401 return 0;
1402#endif
Denis Vlasenko834410a2006-11-29 12:00:28 +00001403#if ENABLE_FEATURE_OSF_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001404 if (check_osf_label()) {
1405 possibly_osf_label = 1;
1406 if (!valid_part_table_flag(MBRbuffer)) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001407 current_label_type = LABEL_OSF;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001408 return 0;
1409 }
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001410 puts("This disk has both DOS and BSD magic.\n"
1411 "Give the 'b' command to go to BSD mode.");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001412 }
1413#endif
1414
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001415#if !ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko4437d192008-04-17 00:12:10 +00001416 if (!valid_part_table_flag(MBRbuffer))
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001417 return -1;
1418#else
Denis Vlasenko4437d192008-04-17 00:12:10 +00001419 if (!valid_part_table_flag(MBRbuffer)) {
1420 if (what == OPEN_MAIN) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001421 puts("Device contains neither a valid DOS "
1422 "partition table, nor Sun, SGI, OSF or GPT "
1423 "disklabel");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001424#ifdef __sparc__
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001425 IF_FEATURE_SUN_LABEL(create_sunlabel();)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001426#else
1427 create_doslabel();
1428#endif
1429 return 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001430 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00001431 /* TRY_ONLY: */
1432 return -1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001433 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00001434 created_table:
1435#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001436
Denis Vlasenko4437d192008-04-17 00:12:10 +00001437
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001438 IF_FEATURE_FDISK_WRITABLE(warn_cylinders();)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001439 warn_geometry();
1440
1441 for (i = 0; i < 4; i++) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001442 if (IS_EXTENDED(ptes[i].part_table->sys_ind)) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001443 if (g_partitions != 4)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001444 printf("Ignoring extra extended "
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001445 "partition %u\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001446 else
1447 read_extended(i);
1448 }
1449 }
1450
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001451 for (i = 3; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001452 struct pte *pe = &ptes[i];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001453 if (!valid_part_table_flag(pe->sectorbuffer)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001454 printf("Warning: invalid flag 0x%02x,0x%02x of partition "
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001455 "table %u will be corrected by w(rite)\n",
Denis Vlasenko834410a2006-11-29 12:00:28 +00001456 pe->sectorbuffer[510],
1457 pe->sectorbuffer[511],
1458 i + 1);
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001459 IF_FEATURE_FDISK_WRITABLE(pe->changed = 1;)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001460 }
1461 }
1462
1463 return 0;
1464}
1465
Denis Vlasenko834410a2006-11-29 12:00:28 +00001466#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001467/*
1468 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
1469 * If the user hits Enter, DFLT is returned.
1470 * Answers like +10 are interpreted as offsets from BASE.
1471 *
1472 * There is no default if DFLT is not between LOW and HIGH.
1473 */
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001474static sector_t
1475read_int(sector_t low, sector_t dflt, sector_t high, sector_t base, const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001476{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001477 sector_t value;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001478 int default_ok = 1;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001479 const char *fmt = "%s (%u-%u, default %u): ";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001480
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001481 if (dflt < low || dflt > high) {
1482 fmt = "%s (%u-%u): ";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001483 default_ok = 0;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001484 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001485
1486 while (1) {
1487 int use_default = default_ok;
1488
1489 /* ask question and read answer */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001490 do {
1491 printf(fmt, mesg, low, high, dflt);
1492 read_maybe_empty("");
1493 } while (*line_ptr != '\n' && !isdigit(*line_ptr)
1494 && *line_ptr != '-' && *line_ptr != '+');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001495
Eric Andersen84bdea82004-05-19 10:49:17 +00001496 if (*line_ptr == '+' || *line_ptr == '-') {
Rob Landleyb73451d2006-02-24 16:29:00 +00001497 int minus = (*line_ptr == '-');
1498 int absolute = 0;
Eric Andersenc48d49a2003-07-03 10:02:32 +00001499
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001500 value = atoi(line_ptr + 1);
Eric Andersenc48d49a2003-07-03 10:02:32 +00001501
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001502 /* (1) if 2nd char is digit, use_default = 0.
1503 * (2) move line_ptr to first non-digit. */
Rob Landleyb73451d2006-02-24 16:29:00 +00001504 while (isdigit(*++line_ptr))
1505 use_default = 0;
Eric Andersen84bdea82004-05-19 10:49:17 +00001506
Rob Landleyb73451d2006-02-24 16:29:00 +00001507 switch (*line_ptr) {
1508 case 'c':
1509 case 'C':
1510 if (!display_in_cyl_units)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001511 value *= g_heads * g_sectors;
Rob Landleyb73451d2006-02-24 16:29:00 +00001512 break;
1513 case 'K':
1514 absolute = 1024;
1515 break;
1516 case 'k':
1517 absolute = 1000;
1518 break;
1519 case 'm':
1520 case 'M':
1521 absolute = 1000000;
1522 break;
1523 case 'g':
1524 case 'G':
1525 absolute = 1000000000;
1526 break;
1527 default:
1528 break;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001529 }
Rob Landleyb73451d2006-02-24 16:29:00 +00001530 if (absolute) {
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001531 ullong bytes;
Rob Landleyb73451d2006-02-24 16:29:00 +00001532 unsigned long unit;
1533
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001534 bytes = (ullong) value * absolute;
Rob Landleyb73451d2006-02-24 16:29:00 +00001535 unit = sector_size * units_per_sector;
1536 bytes += unit/2; /* round */
1537 bytes /= unit;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001538 value = bytes;
Rob Landleyb73451d2006-02-24 16:29:00 +00001539 }
1540 if (minus)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001541 value = -value;
1542 value += base;
Eric Andersen84bdea82004-05-19 10:49:17 +00001543 } else {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001544 value = atoi(line_ptr);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001545 while (isdigit(*line_ptr)) {
1546 line_ptr++;
1547 use_default = 0;
1548 }
1549 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001550 if (use_default) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001551 value = dflt;
1552 printf("Using default value %u\n", value);
Denis Vlasenkobd852072007-03-19 14:43:38 +00001553 }
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001554 if (value >= low && value <= high)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001555 break;
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001556 puts("Value is out of range");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001557 }
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001558 return value;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001559}
1560
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001561static unsigned
1562get_partition(int warn, unsigned max)
Rob Landleyb73451d2006-02-24 16:29:00 +00001563{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001564 struct pte *pe;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001565 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001566
Denis Vlasenkobd852072007-03-19 14:43:38 +00001567 i = read_int(1, 0, max, 0, "Partition number") - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001568 pe = &ptes[i];
1569
1570 if (warn) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001571 if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind)
1572 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
1573 || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
1574 ) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001575 printf("Warning: partition %u has empty type\n", i+1);
Rob Landley5527b912006-02-25 03:46:10 +00001576 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001577 }
1578 return i;
1579}
1580
1581static int
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001582get_existing_partition(int warn, unsigned max)
Rob Landleyb73451d2006-02-24 16:29:00 +00001583{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001584 int pno = -1;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001585 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001586
1587 for (i = 0; i < max; i++) {
1588 struct pte *pe = &ptes[i];
1589 struct partition *p = pe->part_table;
1590
1591 if (p && !is_cleared_partition(p)) {
1592 if (pno >= 0)
1593 goto not_unique;
1594 pno = i;
1595 }
1596 }
1597 if (pno >= 0) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001598 printf("Selected partition %u\n", pno+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001599 return pno;
1600 }
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001601 puts("No partition is defined yet!");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001602 return -1;
1603
1604 not_unique:
1605 return get_partition(warn, max);
1606}
1607
1608static int
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001609get_nonexisting_partition(int warn, unsigned max)
Rob Landleyb73451d2006-02-24 16:29:00 +00001610{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001611 int pno = -1;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001612 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001613
1614 for (i = 0; i < max; i++) {
1615 struct pte *pe = &ptes[i];
1616 struct partition *p = pe->part_table;
1617
1618 if (p && is_cleared_partition(p)) {
1619 if (pno >= 0)
1620 goto not_unique;
1621 pno = i;
1622 }
1623 }
1624 if (pno >= 0) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001625 printf("Selected partition %u\n", pno+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001626 return pno;
1627 }
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001628 puts("All primary partitions have been defined already!");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001629 return -1;
1630
1631 not_unique:
1632 return get_partition(warn, max);
1633}
1634
1635
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001636static void
1637change_units(void)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001638{
1639 display_in_cyl_units = !display_in_cyl_units;
1640 update_units();
Denis Vlasenkobd852072007-03-19 14:43:38 +00001641 printf("Changing display/entry units to %s\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001642 str_units(PLURAL));
1643}
1644
1645static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001646toggle_active(int i)
1647{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001648 struct pte *pe = &ptes[i];
1649 struct partition *p = pe->part_table;
1650
Rob Landleyb73451d2006-02-24 16:29:00 +00001651 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001652 printf("WARNING: Partition %u is an extended partition\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001653 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1654 pe->changed = 1;
1655}
1656
1657static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001658toggle_dos_compatibility_flag(void)
1659{
Denis Vlasenkocdf62772008-03-17 08:42:43 +00001660 dos_compatible_flag = 1 - dos_compatible_flag;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001661 if (dos_compatible_flag) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001662 sector_offset = g_sectors;
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001663 printf("DOS Compatibility flag is %sset\n", "");
Denis Vlasenkobd852072007-03-19 14:43:38 +00001664 } else {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001665 sector_offset = 1;
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001666 printf("DOS Compatibility flag is %sset\n", "not ");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001667 }
1668}
1669
1670static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001671delete_partition(int i)
1672{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001673 struct pte *pe = &ptes[i];
1674 struct partition *p = pe->part_table;
1675 struct partition *q = pe->ext_pointer;
1676
1677/* Note that for the fifth partition (i == 4) we don't actually
1678 * decrement partitions.
1679 */
1680
1681 if (warn_geometry())
1682 return; /* C/H/S not set */
1683 pe->changed = 1;
1684
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001685 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001686 sun_delete_partition(i);
1687 return;
1688 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001689 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001690 sgi_delete_partition(i);
1691 return;
1692 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001693
1694 if (i < 4) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001695 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001696 g_partitions = 4;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001697 ptes[ext_index].ext_pointer = NULL;
1698 extended_offset = 0;
1699 }
1700 clear_partition(p);
1701 return;
1702 }
1703
1704 if (!q->sys_ind && i > 4) {
1705 /* the last one in the chain - just delete */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001706 --g_partitions;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001707 --i;
1708 clear_partition(ptes[i].ext_pointer);
1709 ptes[i].changed = 1;
1710 } else {
1711 /* not the last one - further ones will be moved down */
1712 if (i > 4) {
1713 /* delete this link in the chain */
1714 p = ptes[i-1].ext_pointer;
1715 *p = *q;
1716 set_start_sect(p, get_start_sect(q));
1717 set_nr_sects(p, get_nr_sects(q));
1718 ptes[i-1].changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001719 } else if (g_partitions > 5) { /* 5 will be moved to 4 */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001720 /* the first logical in a longer chain */
1721 pe = &ptes[5];
1722
1723 if (pe->part_table) /* prevent SEGFAULT */
1724 set_start_sect(pe->part_table,
Denys Vlasenkod958e902010-04-06 02:32:26 +02001725 get_partition_start_from_dev_start(pe) -
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001726 extended_offset);
Denys Vlasenkod958e902010-04-06 02:32:26 +02001727 pe->offset_from_dev_start = extended_offset;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001728 pe->changed = 1;
1729 }
1730
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001731 if (g_partitions > 5) {
1732 g_partitions--;
1733 while (i < g_partitions) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001734 ptes[i] = ptes[i+1];
1735 i++;
1736 }
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001737 } else {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001738 /* the only logical: clear only */
1739 clear_partition(ptes[i].part_table);
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001740 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001741 }
1742}
1743
1744static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001745change_sysid(void)
1746{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001747 int i, sys, origsys;
1748 struct partition *p;
1749
Eric Andersen040f4402003-07-30 08:40:37 +00001750 /* If sgi_label then don't use get_existing_partition,
1751 let the user select a partition, since get_existing_partition()
1752 only works for Linux like partition tables. */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001753 if (!LABEL_IS_SGI) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001754 i = get_existing_partition(0, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00001755 } else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001756 i = get_partition(0, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00001757 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001758 if (i == -1)
1759 return;
1760 p = ptes[i].part_table;
1761 origsys = sys = get_sysid(i);
1762
1763 /* if changing types T to 0 is allowed, then
1764 the reverse change must be allowed, too */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001765 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001766 printf("Partition %u does not exist yet!\n", i + 1);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001767 return;
1768 }
1769 while (1) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001770 sys = read_hex(get_sys_types());
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001771
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001772 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001773 puts("Type 0 means free space to many systems\n"
1774 "(but not to Linux). Having partitions of\n"
1775 "type 0 is probably unwise.");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001776 /* break; */
1777 }
1778
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001779 if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001780 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001781 puts("You cannot change a partition into"
1782 " an extended one or vice versa");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001783 break;
1784 }
1785 }
1786
1787 if (sys < 256) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001788#if ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001789 if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001790 puts("Consider leaving partition 3 "
1791 "as Whole disk (5),\n"
1792 "as SunOS/Solaris expects it and "
1793 "even Linux likes it\n");
Denis Vlasenkobd852072007-03-19 14:43:38 +00001794#endif
1795#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001796 if (LABEL_IS_SGI &&
Rob Landley5527b912006-02-25 03:46:10 +00001797 (
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001798 (i == 10 && sys != SGI_ENTIRE_DISK) ||
Rob Landley5527b912006-02-25 03:46:10 +00001799 (i == 8 && sys != 0)
1800 )
Denis Vlasenkobd852072007-03-19 14:43:38 +00001801 ) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001802 puts("Consider leaving partition 9 "
1803 "as volume header (0),\nand "
1804 "partition 11 as entire volume (6)"
1805 "as IRIX expects it\n");
Rob Landley5527b912006-02-25 03:46:10 +00001806 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001807#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001808 if (sys == origsys)
1809 break;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001810 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001811 sun_change_sysid(i, sys);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001812 } else if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001813 sgi_change_sysid(i, sys);
1814 } else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001815 p->sys_ind = sys;
Rob Landley5527b912006-02-25 03:46:10 +00001816
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001817 printf("Changed system type of partition %u "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001818 "to %x (%s)\n", i + 1, sys,
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001819 partition_type(sys));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001820 ptes[i].changed = 1;
Denis Vlasenkoa5549c92008-01-24 22:49:15 +00001821 //if (is_dos_partition(origsys) || is_dos_partition(sys))
1822 // dos_changed = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001823 break;
1824 }
1825 }
1826}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001827#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001828
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001829
Denis Vlasenko28703012006-12-19 20:32:02 +00001830/* check_consistency() and linear2chs() added Sat Mar 6 12:28:16 1993,
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001831 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1832 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1833 * Lubkin Oct. 1991). */
1834
Rob Landleyb73451d2006-02-24 16:29:00 +00001835static void
Denis Vlasenko28703012006-12-19 20:32:02 +00001836linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
Rob Landleyb73451d2006-02-24 16:29:00 +00001837{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001838 int spc = g_heads * g_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001839
1840 *c = ls / spc;
1841 ls = ls % spc;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001842 *h = ls / g_sectors;
1843 *s = ls % g_sectors + 1; /* sectors count from 1 */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001844}
1845
Rob Landleyb73451d2006-02-24 16:29:00 +00001846static void
1847check_consistency(const struct partition *p, int partition)
1848{
Denis Vlasenko834410a2006-11-29 12:00:28 +00001849 unsigned pbc, pbh, pbs; /* physical beginning c, h, s */
1850 unsigned pec, peh, pes; /* physical ending c, h, s */
1851 unsigned lbc, lbh, lbs; /* logical beginning c, h, s */
1852 unsigned lec, leh, les; /* logical ending c, h, s */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001853
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001854 if (!g_heads || !g_sectors || (partition >= 4))
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001855 return; /* do not check extended partitions */
1856
1857/* physical beginning c, h, s */
Denys Vlasenko607f2b42016-08-23 16:13:33 +02001858 pbc = cylinder(p->sector, p->cyl);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001859 pbh = p->head;
Denys Vlasenko607f2b42016-08-23 16:13:33 +02001860 pbs = sector(p->sector);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001861
1862/* physical ending c, h, s */
Denys Vlasenko607f2b42016-08-23 16:13:33 +02001863 pec = cylinder(p->end_sector, p->end_cyl);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001864 peh = p->end_head;
Denys Vlasenko607f2b42016-08-23 16:13:33 +02001865 pes = sector(p->end_sector);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001866
1867/* compute logical beginning (c, h, s) */
Denis Vlasenko28703012006-12-19 20:32:02 +00001868 linear2chs(get_start_sect(p), &lbc, &lbh, &lbs);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001869
1870/* compute logical ending (c, h, s) */
Denis Vlasenko28703012006-12-19 20:32:02 +00001871 linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001872
1873/* Same physical / logical beginning? */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001874 if (g_cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001875 printf("Partition %u has different physical/logical "
Denys Vlasenko607f2b42016-08-23 16:13:33 +02001876 "start (non-Linux?):\n", partition + 1);
1877 printf(" phys=(%u,%u,%u) ", pbc, pbh, pbs);
1878 printf("logical=(%u,%u,%u)\n", lbc, lbh, lbs);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001879 }
1880
1881/* Same physical / logical ending? */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001882 if (g_cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001883 printf("Partition %u has different physical/logical "
Denys Vlasenko607f2b42016-08-23 16:13:33 +02001884 "end:\n", partition + 1);
1885 printf(" phys=(%u,%u,%u) ", pec, peh, pes);
1886 printf("logical=(%u,%u,%u)\n", lec, leh, les);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001887 }
1888
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001889/* Ending on cylinder boundary? */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001890 if (peh != (g_heads - 1) || pes != g_sectors) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001891 printf("Partition %u does not end on cylinder boundary\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001892 partition + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001893 }
1894}
1895
1896static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001897list_disk_geometry(void)
1898{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001899 ullong bytes = ((ullong)total_number_of_sectors << 9);
Denys Vlasenko29483ff2016-08-23 17:18:45 +02001900 ullong xbytes = bytes / (1024*1024);
1901 char x = 'M';
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001902
Denys Vlasenko29483ff2016-08-23 17:18:45 +02001903 if (xbytes >= 10000) {
1904 xbytes += 512; /* fdisk util-linux 2.28 does this */
1905 xbytes /= 1024;
1906 x = 'G';
1907 }
1908 printf("Disk %s: %llu %cB, %llu bytes, %"SECT_FMT"u sectors\n"
1909 "%u cylinders, %u heads, %u sectors/track\n"
1910 "Units: %s of %u * %u = %u bytes\n\n",
1911 disk_device, xbytes, x,
1912 bytes, total_number_of_sectors,
1913 g_cylinders, g_heads, g_sectors,
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001914 str_units(PLURAL),
Denys Vlasenko29483ff2016-08-23 17:18:45 +02001915 units_per_sector, sector_size, units_per_sector * sector_size
1916 );
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001917}
1918
1919/*
1920 * Check whether partition entries are ordered by their starting positions.
1921 * Return 0 if OK. Return i if partition i should have been earlier.
1922 * Two separate checks: primary and logical partitions.
1923 */
1924static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001925wrong_p_order(int *prev)
1926{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001927 const struct pte *pe;
1928 const struct partition *p;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001929 sector_t last_p_start_pos = 0, p_start_pos;
1930 unsigned i, last_i = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001931
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001932 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001933 if (i == 4) {
1934 last_i = 4;
1935 last_p_start_pos = 0;
1936 }
1937 pe = &ptes[i];
Denis Vlasenko6bef3d12007-11-06 03:05:54 +00001938 p = pe->part_table;
1939 if (p->sys_ind) {
Denys Vlasenkod958e902010-04-06 02:32:26 +02001940 p_start_pos = get_partition_start_from_dev_start(pe);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001941
1942 if (last_p_start_pos > p_start_pos) {
1943 if (prev)
1944 *prev = last_i;
1945 return i;
1946 }
1947
1948 last_p_start_pos = p_start_pos;
1949 last_i = i;
1950 }
1951 }
1952 return 0;
1953}
1954
Denis Vlasenko834410a2006-11-29 12:00:28 +00001955#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001956/*
1957 * Fix the chain of logicals.
1958 * extended_offset is unchanged, the set of sectors used is unchanged
1959 * The chain is sorted so that sectors increase, and so that
1960 * starting sectors increase.
1961 *
1962 * After this it may still be that cfdisk doesnt like the table.
1963 * (This is because cfdisk considers expanded parts, from link to
1964 * end of partition, and these may still overlap.)
1965 * Now
1966 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
1967 * may help.
1968 */
1969static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001970fix_chain_of_logicals(void)
1971{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001972 int j, oj, ojj, sj, sjj;
1973 struct partition *pj,*pjj,tmp;
1974
1975 /* Stage 1: sort sectors but leave sector of part 4 */
1976 /* (Its sector is the global extended_offset.) */
1977 stage1:
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001978 for (j = 5; j < g_partitions - 1; j++) {
Denys Vlasenkod958e902010-04-06 02:32:26 +02001979 oj = ptes[j].offset_from_dev_start;
1980 ojj = ptes[j+1].offset_from_dev_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001981 if (oj > ojj) {
Denys Vlasenkod958e902010-04-06 02:32:26 +02001982 ptes[j].offset_from_dev_start = ojj;
1983 ptes[j+1].offset_from_dev_start = oj;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001984 pj = ptes[j].part_table;
1985 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
1986 pjj = ptes[j+1].part_table;
1987 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
1988 set_start_sect(ptes[j-1].ext_pointer,
Rob Landleyb73451d2006-02-24 16:29:00 +00001989 ojj-extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001990 set_start_sect(ptes[j].ext_pointer,
Rob Landleyb73451d2006-02-24 16:29:00 +00001991 oj-extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001992 goto stage1;
1993 }
1994 }
1995
1996 /* Stage 2: sort starting sectors */
1997 stage2:
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001998 for (j = 4; j < g_partitions - 1; j++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001999 pj = ptes[j].part_table;
2000 pjj = ptes[j+1].part_table;
2001 sj = get_start_sect(pj);
2002 sjj = get_start_sect(pjj);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002003 oj = ptes[j].offset_from_dev_start;
2004 ojj = ptes[j+1].offset_from_dev_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002005 if (oj+sj > ojj+sjj) {
2006 tmp = *pj;
2007 *pj = *pjj;
2008 *pjj = tmp;
2009 set_start_sect(pj, ojj+sjj-oj);
2010 set_start_sect(pjj, oj+sj-ojj);
2011 goto stage2;
2012 }
2013 }
2014
2015 /* Probably something was changed */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002016 for (j = 4; j < g_partitions; j++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002017 ptes[j].changed = 1;
2018}
2019
2020
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002021static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002022fix_partition_table_order(void)
2023{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002024 struct pte *pei, *pek;
2025 int i,k;
2026
2027 if (!wrong_p_order(NULL)) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002028 puts("Ordering is already correct\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002029 return;
2030 }
2031
2032 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
2033 /* partition i should have come earlier, move it */
2034 /* We have to move data in the MBR */
2035 struct partition *pi, *pk, *pe, pbuf;
2036 pei = &ptes[i];
2037 pek = &ptes[k];
2038
2039 pe = pei->ext_pointer;
2040 pei->ext_pointer = pek->ext_pointer;
2041 pek->ext_pointer = pe;
2042
2043 pi = pei->part_table;
2044 pk = pek->part_table;
2045
2046 memmove(&pbuf, pi, sizeof(struct partition));
2047 memmove(pi, pk, sizeof(struct partition));
2048 memmove(pk, &pbuf, sizeof(struct partition));
2049
2050 pei->changed = pek->changed = 1;
2051 }
2052
2053 if (i)
2054 fix_chain_of_logicals();
2055
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002056 puts("Done");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002057}
2058#endif
2059
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002060/* Return partition name */
2061static const char *
2062partname(const char *dev, int pno, int lth)
2063{
2064 const char *p;
2065 int w, wp;
2066 int bufsiz;
2067 char *bufp;
2068
2069 bufp = auto_string(xzalloc(80));
2070 bufsiz = 80;
2071
2072 w = strlen(dev);
2073 p = "";
2074
2075 if (isdigit(dev[w-1]))
2076 p = "p";
2077
2078 /* devfs kludge - note: fdisk partition names are not supposed
2079 to equal kernel names, so there is no reason to do this */
2080 if (strcmp(dev + w - 4, "disc") == 0) {
2081 w -= 4;
2082 p = "part";
2083 }
2084
2085 wp = strlen(p);
2086
2087 if (lth) {
2088 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
2089 lth-wp-2, w, dev, p, pno);
2090 } else {
2091 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
2092 }
2093 return bufp;
2094}
2095
2096static const char *
2097chs_string11(unsigned cyl, unsigned head, unsigned sect)
2098{
2099 char *buf = auto_string(xzalloc(sizeof(int)*3 * 3));
2100 sprintf(buf, "%u,%u,%u", cylinder(sect,cyl), head, sector(sect));
2101 return buf;
2102}
2103
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002104static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002105list_table(int xtra)
2106{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002107 int i, w;
2108
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002109 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002110 sun_list_table(xtra);
2111 return;
2112 }
Kevin Cernekeeccb07042010-10-25 02:00:24 +02002113 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002114 sgi_list_table(xtra);
2115 return;
2116 }
Kevin Cernekeeccb07042010-10-25 02:00:24 +02002117 if (LABEL_IS_GPT) {
2118 gpt_list_table(xtra);
2119 return;
2120 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002121
2122 list_disk_geometry();
2123
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002124 if (LABEL_IS_OSF) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002125 xbsd_print_disklabel(xtra);
2126 return;
2127 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002128
2129 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002130 * but if the device name ends in a digit, say /dev/foo1,
2131 * then the partition is called /dev/foo1p3.
2132 */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002133 w = strlen(disk_device);
2134 if (w && isdigit(disk_device[w-1]))
2135 w++;
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002136 if (w < 7)
2137 w = 7;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002138
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002139 printf("%-*s Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type\n",
2140 w-1, "Device");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002141
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002142 for (i = 0; i < g_partitions; i++) {
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002143 const struct partition *p;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002144 const struct pte *pe = &ptes[i];
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002145 char boot4[4];
2146 char numstr6[6];
2147 sector_t start_sect;
2148 sector_t end_sect;
2149 sector_t nr_sects;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002150
2151 p = pe->part_table;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002152 if (!p || is_cleared_partition(p))
2153 continue;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002154
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002155 sprintf(boot4, "%02x", p->boot_ind);
2156 if ((p->boot_ind & 0x7f) == 0) {
2157 /* 0x80 shown as '*', 0x00 is ' ' */
2158 boot4[0] = p->boot_ind ? '*' : ' ';
2159 boot4[1] = ' ';
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002160 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002161
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002162 start_sect = get_partition_start_from_dev_start(pe);
2163 end_sect = start_sect;
2164 nr_sects = get_nr_sects(p);
2165 if (nr_sects != 0)
2166 end_sect += nr_sects - 1;
2167
2168 smart_ulltoa5((ullong)nr_sects * sector_size,
2169 numstr6, " KMGTPEZY")[0] = '\0';
2170
2171#define SFMT SECT_FMT
2172 // Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type
2173 printf("%s%s %-11s"/**/" %-11s"/**/" %10"SFMT"u %10"SFMT"u %10"SFMT"u %s %2x %s\n",
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002174 partname(disk_device, i+1, w+2),
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002175 boot4,
2176 chs_string11(p->cyl, p->head, p->sector),
2177 chs_string11(p->end_cyl, p->end_head, p->end_sector),
2178 start_sect,
2179 end_sect,
2180 nr_sects,
2181 numstr6,
2182 p->sys_ind,
2183 partition_type(p->sys_ind)
2184 );
2185#undef SFMT
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002186 check_consistency(p, i);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002187 }
2188
2189 /* Is partition table in disk order? It need not be, but... */
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002190 /* partition table entries are not checked for correct order
2191 * if this is a sgi, sun or aix labeled disk... */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002192 if (LABEL_IS_DOS && wrong_p_order(NULL)) {
Rob Landley5527b912006-02-25 03:46:10 +00002193 /* FIXME */
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002194 puts("\nPartition table entries are not in disk order");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002195 }
2196}
2197
Denis Vlasenko834410a2006-11-29 12:00:28 +00002198#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002199static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002200x_list_table(int extend)
2201{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002202 const struct pte *pe;
2203 const struct partition *p;
2204 int i;
2205
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002206 printf("\nDisk %s: %u heads, %u sectors, %u cylinders\n\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002207 disk_device, g_heads, g_sectors, g_cylinders);
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002208 puts("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002209 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002210 pe = &ptes[i];
2211 p = (extend ? pe->ext_pointer : pe->part_table);
2212 if (p != NULL) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002213 printf("%2u %02x%4u%4u%5u%4u%4u%5u%11"SECT_FMT"u%11"SECT_FMT"u %02x\n",
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002214 i + 1, p->boot_ind,
2215 p->head,
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002216 sector(p->sector),
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002217 cylinder(p->sector, p->cyl),
2218 p->end_head,
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002219 sector(p->end_sector),
2220 cylinder(p->end_sector, p->end_cyl),
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002221 get_start_sect(p),
2222 get_nr_sects(p),
2223 p->sys_ind
2224 );
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002225 if (p->sys_ind)
2226 check_consistency(p, i);
2227 }
2228 }
2229}
2230#endif
2231
Denis Vlasenko834410a2006-11-29 12:00:28 +00002232#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002233static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002234fill_bounds(sector_t *first, sector_t *last)
Rob Landleyb73451d2006-02-24 16:29:00 +00002235{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002236 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002237 const struct pte *pe = &ptes[0];
2238 const struct partition *p;
2239
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002240 for (i = 0; i < g_partitions; pe++,i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002241 p = pe->part_table;
Rob Landleyb73451d2006-02-24 16:29:00 +00002242 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002243 first[i] = 0xffffffff;
2244 last[i] = 0;
2245 } else {
Denys Vlasenkod958e902010-04-06 02:32:26 +02002246 first[i] = get_partition_start_from_dev_start(pe);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002247 last[i] = first[i] + get_nr_sects(p) - 1;
2248 }
2249 }
2250}
2251
2252static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002253check(int n, unsigned h, unsigned s, unsigned c, sector_t start)
Rob Landleyb73451d2006-02-24 16:29:00 +00002254{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002255 sector_t total, real_s, real_c;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002256
2257 real_s = sector(s) - 1;
2258 real_c = cylinder(s, c);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002259 total = (real_c * g_sectors + real_s) * g_heads + h;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002260 if (!total)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002261 printf("Partition %u contains sector 0\n", n);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002262 if (h >= g_heads)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002263 printf("Partition %u: head %u greater than maximum %u\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002264 n, h + 1, g_heads);
2265 if (real_s >= g_sectors)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002266 printf("Partition %u: sector %u greater than "
2267 "maximum %u\n", n, s, g_sectors);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002268 if (real_c >= g_cylinders)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002269 printf("Partition %u: cylinder %"SECT_FMT"u greater than "
2270 "maximum %u\n", n, real_c + 1, g_cylinders);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002271 if (g_cylinders <= 1024 && start != total)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002272 printf("Partition %u: previous sectors %"SECT_FMT"u disagrees with "
2273 "total %"SECT_FMT"u\n", n, start, total);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002274}
2275
2276static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002277verify(void)
2278{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002279 int i, j;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002280 sector_t total = 1;
Denys Vlasenko29483ff2016-08-23 17:18:45 +02002281 sector_t chs_size;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002282 sector_t first[g_partitions], last[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002283 struct partition *p;
2284
2285 if (warn_geometry())
2286 return;
2287
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002288 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002289 verify_sun();
2290 return;
2291 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002292 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002293 verify_sgi(1);
2294 return;
2295 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002296
2297 fill_bounds(first, last);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002298 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002299 struct pte *pe = &ptes[i];
2300
2301 p = pe->part_table;
Rob Landleyb73451d2006-02-24 16:29:00 +00002302 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002303 check_consistency(p, i);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002304 if (get_partition_start_from_dev_start(pe) < first[i])
Denis Vlasenkobd852072007-03-19 14:43:38 +00002305 printf("Warning: bad start-of-data in "
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002306 "partition %u\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002307 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
2308 last[i]);
2309 total += last[i] + 1 - first[i];
Denis Vlasenkobd852072007-03-19 14:43:38 +00002310 for (j = 0; j < i; j++) {
2311 if ((first[i] >= first[j] && first[i] <= last[j])
2312 || ((last[i] <= last[j] && last[i] >= first[j]))) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002313 printf("Warning: partition %u overlaps "
2314 "partition %u\n", j + 1, i + 1);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002315 total += first[i] >= first[j] ?
2316 first[i] : first[j];
2317 total -= last[i] <= last[j] ?
2318 last[i] : last[j];
2319 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002320 }
2321 }
2322 }
2323
2324 if (extended_offset) {
2325 struct pte *pex = &ptes[ext_index];
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002326 sector_t e_last = get_start_sect(pex->part_table) +
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002327 get_nr_sects(pex->part_table) - 1;
2328
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002329 for (i = 4; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002330 total++;
2331 p = ptes[i].part_table;
2332 if (!p->sys_ind) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002333 if (i != 4 || i + 1 < g_partitions)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002334 printf("Warning: partition %u "
Denis Vlasenkobd852072007-03-19 14:43:38 +00002335 "is empty\n", i + 1);
2336 } else if (first[i] < extended_offset || last[i] > e_last) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002337 printf("Logical partition %u not entirely in "
2338 "partition %u\n", i + 1, ext_index + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002339 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002340 }
2341 }
2342
Denys Vlasenko29483ff2016-08-23 17:18:45 +02002343 chs_size = (sector_t)g_heads * g_sectors * g_cylinders;
2344 if (total > chs_size)
2345 printf("Total allocated sectors %u"
2346 " greater than CHS size %"SECT_FMT"u\n",
2347 total, chs_size
2348 );
Denis Vlasenkobd852072007-03-19 14:43:38 +00002349 else {
Denys Vlasenko29483ff2016-08-23 17:18:45 +02002350 total = chs_size - total;
Denis Vlasenkobd852072007-03-19 14:43:38 +00002351 if (total != 0)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002352 printf("%"SECT_FMT"u unallocated sectors\n", total);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002353 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002354}
2355
2356static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002357add_partition(int n, int sys)
2358{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002359 char mesg[256]; /* 48 does not suffice in Japanese */
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002360 int i, num_read = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002361 struct partition *p = ptes[n].part_table;
2362 struct partition *q = ptes[ext_index].part_table;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002363 sector_t limit, temp;
2364 sector_t start, stop = 0;
2365 sector_t first[g_partitions], last[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002366
2367 if (p && p->sys_ind) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002368 printf(msg_part_already_defined, n + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002369 return;
2370 }
2371 fill_bounds(first, last);
2372 if (n < 4) {
2373 start = sector_offset;
Eric Andersen040f4402003-07-30 08:40:37 +00002374 if (display_in_cyl_units || !total_number_of_sectors)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002375 limit = (sector_t) g_heads * g_sectors * g_cylinders - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002376 else
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002377 limit = total_number_of_sectors - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002378 if (extended_offset) {
2379 first[ext_index] = extended_offset;
2380 last[ext_index] = get_start_sect(q) +
2381 get_nr_sects(q) - 1;
2382 }
2383 } else {
2384 start = extended_offset + sector_offset;
2385 limit = get_start_sect(q) + get_nr_sects(q) - 1;
2386 }
2387 if (display_in_cyl_units)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002388 for (i = 0; i < g_partitions; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002389 first[i] = (cround(first[i]) - 1) * units_per_sector;
2390
Denis Vlasenkobd852072007-03-19 14:43:38 +00002391 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002392 do {
2393 temp = start;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002394 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002395 int lastplusoff;
2396
Denys Vlasenkod958e902010-04-06 02:32:26 +02002397 if (start == ptes[i].offset_from_dev_start)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002398 start += sector_offset;
Rob Landleyb73451d2006-02-24 16:29:00 +00002399 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002400 if (start >= first[i] && start <= lastplusoff)
2401 start = lastplusoff + 1;
2402 }
2403 if (start > limit)
2404 break;
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002405 if (start >= temp+units_per_sector && num_read) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002406 printf("Sector %"SECT_FMT"u is already allocated\n", temp);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002407 temp = start;
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002408 num_read = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002409 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002410 if (!num_read && start == temp) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002411 sector_t saved_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002412
2413 saved_start = start;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002414 start = read_int(cround(saved_start), cround(saved_start), cround(limit), 0, mesg);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002415 if (display_in_cyl_units) {
2416 start = (start - 1) * units_per_sector;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002417 if (start < saved_start)
2418 start = saved_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002419 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002420 num_read = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002421 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002422 } while (start != temp || !num_read);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002423 if (n > 4) { /* NOT for fifth partition */
2424 struct pte *pe = &ptes[n];
2425
Denys Vlasenkod958e902010-04-06 02:32:26 +02002426 pe->offset_from_dev_start = start - sector_offset;
2427 if (pe->offset_from_dev_start == extended_offset) { /* must be corrected */
2428 pe->offset_from_dev_start++;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002429 if (sector_offset == 1)
2430 start++;
2431 }
2432 }
2433
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002434 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002435 struct pte *pe = &ptes[i];
2436
Denys Vlasenkod958e902010-04-06 02:32:26 +02002437 if (start < pe->offset_from_dev_start && limit >= pe->offset_from_dev_start)
2438 limit = pe->offset_from_dev_start - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002439 if (start < first[i] && limit >= first[i])
2440 limit = first[i] - 1;
2441 }
2442 if (start > limit) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002443 puts("No free sectors available");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002444 if (n > 4)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002445 g_partitions--;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002446 return;
2447 }
2448 if (cround(start) == cround(limit)) {
2449 stop = limit;
2450 } else {
2451 snprintf(mesg, sizeof(mesg),
Denis Vlasenkobd852072007-03-19 14:43:38 +00002452 "Last %s or +size or +sizeM or +sizeK",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002453 str_units(SINGULAR));
Denys Vlasenkod958e902010-04-06 02:32:26 +02002454 stop = read_int(cround(start), cround(limit), cround(limit), cround(start), mesg);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002455 if (display_in_cyl_units) {
2456 stop = stop * units_per_sector - 1;
2457 if (stop >limit)
2458 stop = limit;
2459 }
2460 }
2461
2462 set_partition(n, 0, start, stop, sys);
2463 if (n > 4)
Denys Vlasenkod958e902010-04-06 02:32:26 +02002464 set_partition(n - 1, 1, ptes[n].offset_from_dev_start, stop, EXTENDED);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002465
Rob Landleyb73451d2006-02-24 16:29:00 +00002466 if (IS_EXTENDED(sys)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002467 struct pte *pe4 = &ptes[4];
2468 struct pte *pen = &ptes[n];
2469
2470 ext_index = n;
2471 pen->ext_pointer = p;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002472 pe4->offset_from_dev_start = extended_offset = start;
Rob Landley081e3842006-08-03 20:07:35 +00002473 pe4->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002474 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2475 pe4->ext_pointer = pe4->part_table + 1;
2476 pe4->changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002477 g_partitions = 5;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002478 }
2479}
2480
2481static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002482add_logical(void)
2483{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002484 if (g_partitions > 5 || ptes[4].part_table->sys_ind) {
2485 struct pte *pe = &ptes[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002486
Rob Landley081e3842006-08-03 20:07:35 +00002487 pe->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002488 pe->part_table = pt_offset(pe->sectorbuffer, 0);
2489 pe->ext_pointer = pe->part_table + 1;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002490 pe->offset_from_dev_start = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002491 pe->changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002492 g_partitions++;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002493 }
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002494 add_partition(g_partitions - 1, LINUX_NATIVE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002495}
2496
2497static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002498new_partition(void)
2499{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002500 int i, free_primary = 0;
2501
2502 if (warn_geometry())
2503 return;
2504
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002505 if (LABEL_IS_SUN) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002506 add_sun_partition(get_partition(0, g_partitions), LINUX_NATIVE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002507 return;
2508 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002509 if (LABEL_IS_SGI) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002510 sgi_add_partition(get_partition(0, g_partitions), LINUX_NATIVE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002511 return;
2512 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002513 if (LABEL_IS_AIX) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002514 puts("Sorry - this fdisk cannot handle AIX disk labels.\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +00002515"If you want to add DOS-type partitions, create a new empty DOS partition\n"
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002516"table first (use 'o'). This will destroy the present disk contents.");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002517 return;
2518 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002519
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002520 for (i = 0; i < 4; i++)
2521 free_primary += !ptes[i].part_table->sys_ind;
Eric Andersenc48d49a2003-07-03 10:02:32 +00002522
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002523 if (!free_primary && g_partitions >= MAXIMUM_PARTS) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002524 puts("The maximum number of partitions has been created");
Eric Andersen84bdea82004-05-19 10:49:17 +00002525 return;
Rob Landleyb73451d2006-02-24 16:29:00 +00002526 }
Eric Andersenc48d49a2003-07-03 10:02:32 +00002527
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002528 if (!free_primary) {
2529 if (extended_offset)
2530 add_logical();
2531 else
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002532 puts("You must delete some partition and add "
2533 "an extended partition first");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002534 } else {
Denis Vlasenkodfce08f2007-03-19 14:45:10 +00002535 char c, line[80];
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00002536 snprintf(line, sizeof(line),
2537 "Command action\n"
2538 " %s\n"
2539 " p primary partition (1-4)\n",
2540 (extended_offset ?
2541 "l logical (5 or over)" : "e extended"));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002542 while (1) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002543 c = read_nonempty(line);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002544 if ((c | 0x20) == 'p') {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002545 i = get_nonexisting_partition(0, 4);
2546 if (i >= 0)
2547 add_partition(i, LINUX_NATIVE);
2548 return;
2549 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002550 if (c == 'l' && extended_offset) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002551 add_logical();
2552 return;
2553 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002554 if (c == 'e' && !extended_offset) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002555 i = get_nonexisting_partition(0, 4);
2556 if (i >= 0)
2557 add_partition(i, EXTENDED);
2558 return;
2559 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002560 printf("Invalid partition number "
2561 "for type '%c'\n", c);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002562 }
2563 }
2564}
2565
2566static void
Denys Vlasenkob347df92011-08-09 22:49:15 +02002567reread_partition_table(int leave)
2568{
2569 int i;
2570
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002571 puts("Calling ioctl() to re-read partition table");
Denys Vlasenkob347df92011-08-09 22:49:15 +02002572 sync();
2573 /* Users with slow external USB disks on a 320MHz ARM system (year 2011)
2574 * report that sleep is needed, otherwise BLKRRPART may fail with -EIO:
2575 */
2576 sleep(1);
2577 i = ioctl_or_perror(dev_fd, BLKRRPART, NULL,
2578 "WARNING: rereading partition table "
2579 "failed, kernel still uses old table");
2580#if 0
2581 if (dos_changed)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002582 puts(
Denys Vlasenkob347df92011-08-09 22:49:15 +02002583 "\nWARNING: If you have created or modified any DOS 6.x\n"
2584 "partitions, please see the fdisk manual page for additional\n"
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002585 "information");
Denys Vlasenkob347df92011-08-09 22:49:15 +02002586#endif
2587
2588 if (leave) {
2589 if (ENABLE_FEATURE_CLEAN_UP)
2590 close_dev_fd();
2591 exit(i != 0);
2592 }
2593}
2594
2595static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002596write_table(void)
2597{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002598 int i;
2599
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002600 if (LABEL_IS_DOS) {
Rob Landleyb73451d2006-02-24 16:29:00 +00002601 for (i = 0; i < 3; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002602 if (ptes[i].changed)
2603 ptes[3].changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002604 for (i = 3; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002605 struct pte *pe = &ptes[i];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002606 if (pe->changed) {
2607 write_part_table_flag(pe->sectorbuffer);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002608 write_sector(pe->offset_from_dev_start, pe->sectorbuffer);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002609 }
2610 }
2611 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002612 else if (LABEL_IS_SGI) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002613 /* no test on change? the "altered" msg below might be mistaken */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002614 sgi_write_table();
2615 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002616 else if (LABEL_IS_SUN) {
Denys Vlasenko80856b32011-07-13 09:06:32 +02002617 for (i = 0; i < 8; i++) {
2618 if (ptes[i].changed) {
2619 sun_write_table();
2620 break;
2621 }
2622 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002623 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002624
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002625 puts("The partition table has been altered.");
Denys Vlasenkob347df92011-08-09 22:49:15 +02002626 reread_partition_table(1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002627}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00002628#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002629
Denis Vlasenko834410a2006-11-29 12:00:28 +00002630#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002631#define MAX_PER_LINE 16
2632static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002633print_buffer(char *pbuffer)
2634{
2635 int i,l;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002636
2637 for (i = 0, l = 0; i < sector_size; i++, l++) {
2638 if (l == 0)
2639 printf("0x%03X:", i);
2640 printf(" %02X", (unsigned char) pbuffer[i]);
2641 if (l == MAX_PER_LINE - 1) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002642 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002643 l = -1;
2644 }
2645 }
2646 if (l > 0)
Denis Vlasenko4daad902007-09-27 10:20:47 +00002647 bb_putchar('\n');
2648 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002649}
2650
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002651static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002652print_raw(void)
2653{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002654 int i;
2655
Denis Vlasenkobd852072007-03-19 14:43:38 +00002656 printf("Device: %s\n", disk_device);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002657 if (LABEL_IS_SGI || LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002658 print_buffer(MBRbuffer);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002659 else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002660 for (i = 3; i < g_partitions; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002661 print_buffer(ptes[i].sectorbuffer);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002662 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002663}
2664
2665static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002666move_begin(unsigned i)
Rob Landleyb73451d2006-02-24 16:29:00 +00002667{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002668 struct pte *pe = &ptes[i];
2669 struct partition *p = pe->part_table;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002670 sector_t new, first, nr_sects;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002671
2672 if (warn_geometry())
2673 return;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002674 nr_sects = get_nr_sects(p);
2675 if (!p->sys_ind || !nr_sects || IS_EXTENDED(p->sys_ind)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002676 printf("Partition %u has no data area\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002677 return;
2678 }
Denys Vlasenkofcad7682010-04-06 16:56:33 +02002679 first = get_partition_start_from_dev_start(pe); /* == pe->offset_from_dev_start + get_start_sect(p) */
Denys Vlasenkod958e902010-04-06 02:32:26 +02002680 new = read_int(0 /*was:first*/, first, first + nr_sects - 1, first, "New beginning of data");
2681 if (new != first) {
2682 sector_t new_relative = new - pe->offset_from_dev_start;
2683 nr_sects += (get_start_sect(p) - new_relative);
2684 set_start_sect(p, new_relative);
2685 set_nr_sects(p, nr_sects);
2686 read_nonempty("Recalculate C/H/S values? (Y/N): ");
2687 if ((line_ptr[0] | 0x20) == 'y')
2688 set_hsc_start_end(p, new, new + nr_sects - 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002689 pe->changed = 1;
2690 }
2691}
2692
2693static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002694xselect(void)
2695{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002696 char c;
2697
Rob Landleyb73451d2006-02-24 16:29:00 +00002698 while (1) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002699 bb_putchar('\n');
Denys Vlasenkod958e902010-04-06 02:32:26 +02002700 c = 0x20 | read_nonempty("Expert command (m for help): ");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002701 switch (c) {
2702 case 'a':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002703 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002704 sun_set_alt_cyl();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002705 break;
2706 case 'b':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002707 if (LABEL_IS_DOS)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002708 move_begin(get_partition(0, g_partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002709 break;
2710 case 'c':
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002711 user_cylinders = g_cylinders =
2712 read_int(1, g_cylinders, 1048576, 0,
Denis Vlasenkobd852072007-03-19 14:43:38 +00002713 "Number of cylinders");
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002714 if (LABEL_IS_SUN)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002715 sun_set_ncyl(g_cylinders);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002716 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002717 warn_cylinders();
2718 break;
2719 case 'd':
2720 print_raw();
2721 break;
2722 case 'e':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002723 if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002724 sgi_set_xcyl();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002725 else if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002726 sun_set_xcyl();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002727 else if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002728 x_list_table(1);
2729 break;
2730 case 'f':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002731 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002732 fix_partition_table_order();
2733 break;
2734 case 'g':
Denis Vlasenko834410a2006-11-29 12:00:28 +00002735#if ENABLE_FEATURE_SGI_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002736 create_sgilabel();
2737#endif
2738 break;
2739 case 'h':
Denys Vlasenkod958e902010-04-06 02:32:26 +02002740 user_heads = g_heads = read_int(1, g_heads, 256, 0, "Number of heads");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002741 update_units();
2742 break;
2743 case 'i':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002744 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002745 sun_set_ilfact();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002746 break;
2747 case 'o':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002748 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002749 sun_set_rspeed();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002750 break;
2751 case 'p':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002752 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002753 list_table(1);
2754 else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002755 x_list_table(0);
2756 break;
2757 case 'q':
Denis Vlasenko4437d192008-04-17 00:12:10 +00002758 if (ENABLE_FEATURE_CLEAN_UP)
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002759 close_dev_fd();
Denis Vlasenko4daad902007-09-27 10:20:47 +00002760 bb_putchar('\n');
Bernhard Reutner-Fischer636a1f82008-05-19 09:29:47 +00002761 exit(EXIT_SUCCESS);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002762 case 'r':
2763 return;
2764 case 's':
Denys Vlasenkod958e902010-04-06 02:32:26 +02002765 user_sectors = g_sectors = read_int(1, g_sectors, 63, 0, "Number of sectors");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002766 if (dos_compatible_flag) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002767 sector_offset = g_sectors;
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002768 puts("Warning: setting sector offset for DOS "
2769 "compatiblity");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002770 }
2771 update_units();
2772 break;
2773 case 'v':
2774 verify();
2775 break;
2776 case 'w':
2777 write_table(); /* does not return */
2778 break;
2779 case 'y':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002780 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002781 sun_set_pcylcount();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002782 break;
2783 default:
2784 xmenu();
2785 }
2786 }
2787}
2788#endif /* ADVANCED mode */
2789
2790static int
Rob Landleyb73451d2006-02-24 16:29:00 +00002791is_ide_cdrom_or_tape(const char *device)
2792{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002793 FILE *procf;
2794 char buf[100];
2795 struct stat statbuf;
2796 int is_ide = 0;
2797
2798 /* No device was given explicitly, and we are trying some
2799 likely things. But opening /dev/hdc may produce errors like
2800 "hdc: tray open or drive not ready"
2801 if it happens to be a CD-ROM drive. It even happens that
2802 the process hangs on the attempt to read a music CD.
2803 So try to be careful. This only works since 2.1.73. */
2804
Denys Vlasenko8dff01d2015-03-12 17:48:34 +01002805 if (!is_prefixed_with(device, "/dev/hd"))
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002806 return 0;
2807
2808 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
Denis Vlasenko5415c852008-07-21 23:05:26 +00002809 procf = fopen_for_read(buf);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002810 if (procf != NULL && fgets(buf, sizeof(buf), procf))
Denys Vlasenko8dff01d2015-03-12 17:48:34 +01002811 is_ide = (is_prefixed_with(buf, "cdrom") ||
2812 is_prefixed_with(buf, "tape"));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002813 else
2814 /* Now when this proc file does not exist, skip the
2815 device when it is read-only. */
2816 if (stat(device, &statbuf) == 0)
2817 is_ide = ((statbuf.st_mode & 0222) == 0);
2818
2819 if (procf)
2820 fclose(procf);
2821 return is_ide;
2822}
2823
Rob Landley5527b912006-02-25 03:46:10 +00002824
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002825static void
Denis Vlasenko4437d192008-04-17 00:12:10 +00002826open_list_and_close(const char *device, int user_specified)
Rob Landleyb73451d2006-02-24 16:29:00 +00002827{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002828 int gb;
2829
2830 disk_device = device;
2831 if (setjmp(listingbuf))
2832 return;
2833 if (!user_specified)
2834 if (is_ide_cdrom_or_tape(device))
2835 return;
Denis Vlasenko4437d192008-04-17 00:12:10 +00002836
2837 /* Open disk_device, save file descriptor to dev_fd */
2838 errno = 0;
2839 gb = get_boot(TRY_ONLY);
2840 if (gb > 0) { /* I/O error */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002841 /* Ignore other errors, since we try IDE
2842 and SCSI hard disks which may not be
2843 installed on the system. */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002844 if (user_specified || errno == EACCES)
2845 bb_perror_msg("can't open '%s'", device);
2846 return;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002847 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00002848
2849 if (gb < 0) { /* no DOS signature */
2850 list_disk_geometry();
2851 if (LABEL_IS_AIX)
2852 goto ret;
2853#if ENABLE_FEATURE_OSF_LABEL
2854 if (bsd_trydev(device) < 0)
2855#endif
2856 printf("Disk %s doesn't contain a valid "
2857 "partition table\n", device);
2858 } else {
2859 list_table(0);
2860#if ENABLE_FEATURE_FDISK_WRITABLE
2861 if (!LABEL_IS_SUN && g_partitions > 4) {
2862 delete_partition(ext_index);
2863 }
2864#endif
2865 }
2866 ret:
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002867 close_dev_fd();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002868}
2869
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002870/* Is it a whole disk? The digit check is still useful
2871 for Xen devices for example. */
2872static int is_whole_disk(const char *disk)
2873{
2874 unsigned len;
2875 int fd = open(disk, O_RDONLY);
2876
2877 if (fd != -1) {
2878 struct hd_geometry geometry;
2879 int err = ioctl(fd, HDIO_GETGEO, &geometry);
2880 close(fd);
2881 if (!err)
2882 return (geometry.start == 0);
2883 }
2884
2885 /* Treat "nameN" as a partition name, not whole disk */
2886 /* note: mmcblk0 should work from the geometry check above */
2887 len = strlen(disk);
2888 if (len != 0 && isdigit(disk[len - 1]))
2889 return 0;
2890
2891 return 1;
2892}
2893
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002894/* for fdisk -l: try all things in /proc/partitions
2895 that look like a partition name (do not end in a digit) */
2896static void
Denis Vlasenko4437d192008-04-17 00:12:10 +00002897list_devs_in_proc_partititons(void)
Rob Landleyb73451d2006-02-24 16:29:00 +00002898{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002899 FILE *procpt;
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002900 char line[100], ptname[100], devname[120];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002901 int ma, mi, sz;
2902
Denis Vlasenkoddec5af2006-10-26 23:25:17 +00002903 procpt = fopen_or_warn("/proc/partitions", "r");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002904
2905 while (fgets(line, sizeof(line), procpt)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002906 if (sscanf(line, " %u %u %u %[^\n ]",
Rob Landleyb73451d2006-02-24 16:29:00 +00002907 &ma, &mi, &sz, ptname) != 4)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002908 continue;
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002909
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002910 sprintf(devname, "/dev/%s", ptname);
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002911 if (is_whole_disk(devname))
2912 open_list_and_close(devname, 0);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002913 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002914#if ENABLE_FEATURE_CLEAN_UP
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002915 fclose(procpt);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002916#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002917}
2918
Denis Vlasenko834410a2006-11-29 12:00:28 +00002919#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002920static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002921unknown_command(int c)
2922{
Denis Vlasenkobd852072007-03-19 14:43:38 +00002923 printf("%c: unknown command\n", c);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002924}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002925#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002926
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00002927int fdisk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002928int fdisk_main(int argc UNUSED_PARAM, char **argv)
Rob Landleyb73451d2006-02-24 16:29:00 +00002929{
Denis Vlasenko834410a2006-11-29 12:00:28 +00002930 unsigned opt;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002931 /*
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002932 * fdisk -v
2933 * fdisk -l [-b sectorsize] [-u] device ...
2934 * fdisk -s [partition] ...
2935 * fdisk [-b sectorsize] [-u] device
2936 *
2937 * Options -C, -H, -S set the geometry.
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002938 */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002939 INIT_G();
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +00002940
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002941 close_dev_fd(); /* needed: fd 3 must not stay closed */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002942
Denys Vlasenko237bedd2016-07-06 21:58:02 +02002943 opt = getopt32(argv, "b:+C:+H:+lS:+u" IF_FEATURE_FDISK_BLKSIZE("s"),
Denis Vlasenko04e11c92008-02-10 19:44:20 +00002944 &sector_size, &user_cylinders, &user_heads, &user_sectors);
Denis Vlasenko834410a2006-11-29 12:00:28 +00002945 argv += optind;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002946 if (opt & OPT_b) {
Denis Vlasenko834410a2006-11-29 12:00:28 +00002947 /* Ugly: this sector size is really per device,
Denys Vlasenkod958e902010-04-06 02:32:26 +02002948 * so cannot be combined with multiple disks,
2949 * and the same goes for the C/H/S options.
2950 */
2951 if (sector_size < 512
2952 || sector_size > 0x10000
2953 || (sector_size & (sector_size-1)) /* not power of 2 */
2954 ) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002955 bb_show_usage();
Denys Vlasenkod958e902010-04-06 02:32:26 +02002956 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002957 sector_offset = 2;
2958 user_set_sector_size = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002959 }
Denis Vlasenko04e11c92008-02-10 19:44:20 +00002960 if (user_heads <= 0 || user_heads >= 256)
2961 user_heads = 0;
2962 if (user_sectors <= 0 || user_sectors >= 64)
2963 user_sectors = 0;
2964 if (opt & OPT_u)
2965 display_in_cyl_units = 0; // -u
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002966
Denis Vlasenko834410a2006-11-29 12:00:28 +00002967#if ENABLE_FEATURE_FDISK_WRITABLE
2968 if (opt & OPT_l) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002969 nowarn = 1;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002970#endif
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002971 if (*argv) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002972 listing = 1;
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002973 do {
Denis Vlasenko4437d192008-04-17 00:12:10 +00002974 open_list_and_close(*argv, 1);
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002975 } while (*++argv);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002976 } else {
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002977 /* we don't have device names, */
2978 /* use /proc/partitions instead */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002979 list_devs_in_proc_partititons();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002980 }
2981 return 0;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002982#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002983 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002984#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002985
Denis Vlasenko834410a2006-11-29 12:00:28 +00002986#if ENABLE_FEATURE_FDISK_BLKSIZE
2987 if (opt & OPT_s) {
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002988 int j;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002989
2990 nowarn = 1;
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002991 if (!argv[0])
Manuel Novoa III cad53642003-03-19 09:13:01 +00002992 bb_show_usage();
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002993 for (j = 0; argv[j]; j++) {
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002994 unsigned long long size;
2995 fd = xopen(argv[j], O_RDONLY);
Denis Vlasenko4437d192008-04-17 00:12:10 +00002996 size = bb_BLKGETSIZE_sectors(fd) / 2;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002997 close(fd);
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002998 if (argv[1])
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002999 printf("%llu\n", size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003000 else
Denys Vlasenkoddf78502009-09-16 03:03:13 +02003001 printf("%s: %llu\n", argv[j], size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003002 }
3003 return 0;
3004 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00003005#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003006
Denis Vlasenko834410a2006-11-29 12:00:28 +00003007#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01003008 if (!argv[0] || argv[1])
Manuel Novoa III cad53642003-03-19 09:13:01 +00003009 bb_show_usage();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003010
Denis Vlasenko834410a2006-11-29 12:00:28 +00003011 disk_device = argv[0];
Denis Vlasenko4437d192008-04-17 00:12:10 +00003012 get_boot(OPEN_MAIN);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003013
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003014 if (LABEL_IS_OSF) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003015 /* OSF label, and no DOS label */
Denis Vlasenkobd852072007-03-19 14:43:38 +00003016 printf("Detected an OSF/1 disklabel on %s, entering "
3017 "disklabel mode\n", disk_device);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +00003018 bsd_select();
Rob Landley5527b912006-02-25 03:46:10 +00003019 /*Why do we do this? It seems to be counter-intuitive*/
Denis Vlasenko4437d192008-04-17 00:12:10 +00003020 current_label_type = LABEL_DOS;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003021 /* If we return we may want to make an empty DOS label? */
3022 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003023
3024 while (1) {
Denis Vlasenko3bba5452006-12-30 17:57:03 +00003025 int c;
Denis Vlasenko4daad902007-09-27 10:20:47 +00003026 bb_putchar('\n');
Denys Vlasenkod958e902010-04-06 02:32:26 +02003027 c = 0x20 | read_nonempty("Command (m for help): ");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003028 switch (c) {
3029 case 'a':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003030 if (LABEL_IS_DOS)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003031 toggle_active(get_partition(1, g_partitions));
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003032 else if (LABEL_IS_SUN)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003033 toggle_sunflags(get_partition(1, g_partitions),
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003034 0x01);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003035 else if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003036 sgi_set_bootpartition(
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003037 get_partition(1, g_partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003038 else
3039 unknown_command(c);
3040 break;
3041 case 'b':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003042 if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00003043 printf("\nThe current boot file is: %s\n",
Rob Landleyb73451d2006-02-24 16:29:00 +00003044 sgi_get_bootfile());
Denis Vlasenkobd852072007-03-19 14:43:38 +00003045 if (read_maybe_empty("Please enter the name of the "
Denys Vlasenko69675782013-01-14 01:34:48 +01003046 "new boot file: ") == '\n')
Denys Vlasenkod60752f2015-10-07 22:42:45 +02003047 puts("Boot file unchanged");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003048 else
3049 sgi_set_bootfile(line_ptr);
Denis Vlasenko834410a2006-11-29 12:00:28 +00003050 }
3051#if ENABLE_FEATURE_OSF_LABEL
3052 else
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +00003053 bsd_select();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003054#endif
3055 break;
3056 case 'c':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003057 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003058 toggle_dos_compatibility_flag();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003059 else if (LABEL_IS_SUN)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003060 toggle_sunflags(get_partition(1, g_partitions),
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003061 0x10);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003062 else if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003063 sgi_set_swappartition(
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003064 get_partition(1, g_partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003065 else
3066 unknown_command(c);
3067 break;
3068 case 'd':
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00003069 {
Eric Andersen040f4402003-07-30 08:40:37 +00003070 int j;
Eric Andersen040f4402003-07-30 08:40:37 +00003071 /* If sgi_label then don't use get_existing_partition,
3072 let the user select a partition, since
3073 get_existing_partition() only works for Linux-like
3074 partition tables */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003075 if (!LABEL_IS_SGI) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003076 j = get_existing_partition(1, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00003077 } else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003078 j = get_partition(1, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00003079 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00003080 if (j >= 0)
3081 delete_partition(j);
3082 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003083 break;
3084 case 'i':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003085 if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003086 create_sgiinfo();
3087 else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003088 unknown_command(c);
3089 case 'l':
3090 list_types(get_sys_types());
3091 break;
3092 case 'm':
3093 menu();
3094 break;
3095 case 'n':
3096 new_partition();
3097 break;
3098 case 'o':
3099 create_doslabel();
3100 break;
3101 case 'p':
3102 list_table(0);
3103 break;
3104 case 'q':
Denis Vlasenkoc033d512008-04-17 01:52:28 +00003105 if (ENABLE_FEATURE_CLEAN_UP)
3106 close_dev_fd();
Denis Vlasenko4daad902007-09-27 10:20:47 +00003107 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003108 return 0;
3109 case 's':
Denis Vlasenko834410a2006-11-29 12:00:28 +00003110#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003111 create_sunlabel();
3112#endif
3113 break;
3114 case 't':
3115 change_sysid();
3116 break;
3117 case 'u':
3118 change_units();
3119 break;
3120 case 'v':
3121 verify();
3122 break;
3123 case 'w':
Denys Vlasenko80856b32011-07-13 09:06:32 +02003124 write_table(); /* does not return */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003125 break;
Denis Vlasenko834410a2006-11-29 12:00:28 +00003126#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003127 case 'x':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003128 if (LABEL_IS_SGI) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02003129 puts("\n\tSorry, no experts menu for SGI "
3130 "partition tables available\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003131 } else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003132 xselect();
3133 break;
3134#endif
3135 default:
3136 unknown_command(c);
3137 menu();
3138 }
3139 }
3140 return 0;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003141#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003142}