blob: 6b5e3880fc9baac7fc24c1923d351b62a8457a49 [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);
1900 long megabytes = bytes / 1000000;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001901
1902 if (megabytes < 10000)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001903 printf("\nDisk %s: %lu MB, %llu bytes\n",
1904 disk_device, megabytes, bytes);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001905 else
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001906 printf("\nDisk %s: %lu.%lu GB, %llu bytes\n",
1907 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
1908 printf("%u heads, %u sectors/track, %u cylinders",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001909 g_heads, g_sectors, g_cylinders);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001910 if (units_per_sector == 1)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001911 printf(", total %"SECT_FMT"u sectors",
1912 total_number_of_sectors / (sector_size/512));
1913 printf("\nUnits = %s of %u * %u = %u bytes\n\n",
1914 str_units(PLURAL),
1915 units_per_sector, sector_size, units_per_sector * sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001916}
1917
1918/*
1919 * Check whether partition entries are ordered by their starting positions.
1920 * Return 0 if OK. Return i if partition i should have been earlier.
1921 * Two separate checks: primary and logical partitions.
1922 */
1923static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001924wrong_p_order(int *prev)
1925{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001926 const struct pte *pe;
1927 const struct partition *p;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001928 sector_t last_p_start_pos = 0, p_start_pos;
1929 unsigned i, last_i = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001930
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001931 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001932 if (i == 4) {
1933 last_i = 4;
1934 last_p_start_pos = 0;
1935 }
1936 pe = &ptes[i];
Denis Vlasenko6bef3d12007-11-06 03:05:54 +00001937 p = pe->part_table;
1938 if (p->sys_ind) {
Denys Vlasenkod958e902010-04-06 02:32:26 +02001939 p_start_pos = get_partition_start_from_dev_start(pe);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001940
1941 if (last_p_start_pos > p_start_pos) {
1942 if (prev)
1943 *prev = last_i;
1944 return i;
1945 }
1946
1947 last_p_start_pos = p_start_pos;
1948 last_i = i;
1949 }
1950 }
1951 return 0;
1952}
1953
Denis Vlasenko834410a2006-11-29 12:00:28 +00001954#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001955/*
1956 * Fix the chain of logicals.
1957 * extended_offset is unchanged, the set of sectors used is unchanged
1958 * The chain is sorted so that sectors increase, and so that
1959 * starting sectors increase.
1960 *
1961 * After this it may still be that cfdisk doesnt like the table.
1962 * (This is because cfdisk considers expanded parts, from link to
1963 * end of partition, and these may still overlap.)
1964 * Now
1965 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
1966 * may help.
1967 */
1968static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001969fix_chain_of_logicals(void)
1970{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001971 int j, oj, ojj, sj, sjj;
1972 struct partition *pj,*pjj,tmp;
1973
1974 /* Stage 1: sort sectors but leave sector of part 4 */
1975 /* (Its sector is the global extended_offset.) */
1976 stage1:
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001977 for (j = 5; j < g_partitions - 1; j++) {
Denys Vlasenkod958e902010-04-06 02:32:26 +02001978 oj = ptes[j].offset_from_dev_start;
1979 ojj = ptes[j+1].offset_from_dev_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001980 if (oj > ojj) {
Denys Vlasenkod958e902010-04-06 02:32:26 +02001981 ptes[j].offset_from_dev_start = ojj;
1982 ptes[j+1].offset_from_dev_start = oj;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001983 pj = ptes[j].part_table;
1984 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
1985 pjj = ptes[j+1].part_table;
1986 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
1987 set_start_sect(ptes[j-1].ext_pointer,
Rob Landleyb73451d2006-02-24 16:29:00 +00001988 ojj-extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001989 set_start_sect(ptes[j].ext_pointer,
Rob Landleyb73451d2006-02-24 16:29:00 +00001990 oj-extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001991 goto stage1;
1992 }
1993 }
1994
1995 /* Stage 2: sort starting sectors */
1996 stage2:
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001997 for (j = 4; j < g_partitions - 1; j++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001998 pj = ptes[j].part_table;
1999 pjj = ptes[j+1].part_table;
2000 sj = get_start_sect(pj);
2001 sjj = get_start_sect(pjj);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002002 oj = ptes[j].offset_from_dev_start;
2003 ojj = ptes[j+1].offset_from_dev_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002004 if (oj+sj > ojj+sjj) {
2005 tmp = *pj;
2006 *pj = *pjj;
2007 *pjj = tmp;
2008 set_start_sect(pj, ojj+sjj-oj);
2009 set_start_sect(pjj, oj+sj-ojj);
2010 goto stage2;
2011 }
2012 }
2013
2014 /* Probably something was changed */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002015 for (j = 4; j < g_partitions; j++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002016 ptes[j].changed = 1;
2017}
2018
2019
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002020static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002021fix_partition_table_order(void)
2022{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002023 struct pte *pei, *pek;
2024 int i,k;
2025
2026 if (!wrong_p_order(NULL)) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002027 puts("Ordering is already correct\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002028 return;
2029 }
2030
2031 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
2032 /* partition i should have come earlier, move it */
2033 /* We have to move data in the MBR */
2034 struct partition *pi, *pk, *pe, pbuf;
2035 pei = &ptes[i];
2036 pek = &ptes[k];
2037
2038 pe = pei->ext_pointer;
2039 pei->ext_pointer = pek->ext_pointer;
2040 pek->ext_pointer = pe;
2041
2042 pi = pei->part_table;
2043 pk = pek->part_table;
2044
2045 memmove(&pbuf, pi, sizeof(struct partition));
2046 memmove(pi, pk, sizeof(struct partition));
2047 memmove(pk, &pbuf, sizeof(struct partition));
2048
2049 pei->changed = pek->changed = 1;
2050 }
2051
2052 if (i)
2053 fix_chain_of_logicals();
2054
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002055 puts("Done");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002056}
2057#endif
2058
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002059/* Return partition name */
2060static const char *
2061partname(const char *dev, int pno, int lth)
2062{
2063 const char *p;
2064 int w, wp;
2065 int bufsiz;
2066 char *bufp;
2067
2068 bufp = auto_string(xzalloc(80));
2069 bufsiz = 80;
2070
2071 w = strlen(dev);
2072 p = "";
2073
2074 if (isdigit(dev[w-1]))
2075 p = "p";
2076
2077 /* devfs kludge - note: fdisk partition names are not supposed
2078 to equal kernel names, so there is no reason to do this */
2079 if (strcmp(dev + w - 4, "disc") == 0) {
2080 w -= 4;
2081 p = "part";
2082 }
2083
2084 wp = strlen(p);
2085
2086 if (lth) {
2087 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
2088 lth-wp-2, w, dev, p, pno);
2089 } else {
2090 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
2091 }
2092 return bufp;
2093}
2094
2095static const char *
2096chs_string11(unsigned cyl, unsigned head, unsigned sect)
2097{
2098 char *buf = auto_string(xzalloc(sizeof(int)*3 * 3));
2099 sprintf(buf, "%u,%u,%u", cylinder(sect,cyl), head, sector(sect));
2100 return buf;
2101}
2102
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002103static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002104list_table(int xtra)
2105{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002106 int i, w;
2107
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002108 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002109 sun_list_table(xtra);
2110 return;
2111 }
Kevin Cernekeeccb07042010-10-25 02:00:24 +02002112 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002113 sgi_list_table(xtra);
2114 return;
2115 }
Kevin Cernekeeccb07042010-10-25 02:00:24 +02002116 if (LABEL_IS_GPT) {
2117 gpt_list_table(xtra);
2118 return;
2119 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002120
2121 list_disk_geometry();
2122
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002123 if (LABEL_IS_OSF) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002124 xbsd_print_disklabel(xtra);
2125 return;
2126 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002127
2128 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002129 * but if the device name ends in a digit, say /dev/foo1,
2130 * then the partition is called /dev/foo1p3.
2131 */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002132 w = strlen(disk_device);
2133 if (w && isdigit(disk_device[w-1]))
2134 w++;
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002135 if (w < 7)
2136 w = 7;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002137
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002138 printf("%-*s Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type\n",
2139 w-1, "Device");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002140
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002141 for (i = 0; i < g_partitions; i++) {
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002142 const struct partition *p;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002143 const struct pte *pe = &ptes[i];
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002144 char boot4[4];
2145 char numstr6[6];
2146 sector_t start_sect;
2147 sector_t end_sect;
2148 sector_t nr_sects;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002149
2150 p = pe->part_table;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002151 if (!p || is_cleared_partition(p))
2152 continue;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002153
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002154 sprintf(boot4, "%02x", p->boot_ind);
2155 if ((p->boot_ind & 0x7f) == 0) {
2156 /* 0x80 shown as '*', 0x00 is ' ' */
2157 boot4[0] = p->boot_ind ? '*' : ' ';
2158 boot4[1] = ' ';
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002159 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002160
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002161 start_sect = get_partition_start_from_dev_start(pe);
2162 end_sect = start_sect;
2163 nr_sects = get_nr_sects(p);
2164 if (nr_sects != 0)
2165 end_sect += nr_sects - 1;
2166
2167 smart_ulltoa5((ullong)nr_sects * sector_size,
2168 numstr6, " KMGTPEZY")[0] = '\0';
2169
2170#define SFMT SECT_FMT
2171 // Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type
2172 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 +00002173 partname(disk_device, i+1, w+2),
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002174 boot4,
2175 chs_string11(p->cyl, p->head, p->sector),
2176 chs_string11(p->end_cyl, p->end_head, p->end_sector),
2177 start_sect,
2178 end_sect,
2179 nr_sects,
2180 numstr6,
2181 p->sys_ind,
2182 partition_type(p->sys_ind)
2183 );
2184#undef SFMT
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002185 check_consistency(p, i);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002186 }
2187
2188 /* Is partition table in disk order? It need not be, but... */
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002189 /* partition table entries are not checked for correct order
2190 * if this is a sgi, sun or aix labeled disk... */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002191 if (LABEL_IS_DOS && wrong_p_order(NULL)) {
Rob Landley5527b912006-02-25 03:46:10 +00002192 /* FIXME */
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002193 puts("\nPartition table entries are not in disk order");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002194 }
2195}
2196
Denis Vlasenko834410a2006-11-29 12:00:28 +00002197#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002198static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002199x_list_table(int extend)
2200{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002201 const struct pte *pe;
2202 const struct partition *p;
2203 int i;
2204
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002205 printf("\nDisk %s: %u heads, %u sectors, %u cylinders\n\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002206 disk_device, g_heads, g_sectors, g_cylinders);
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002207 puts("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002208 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002209 pe = &ptes[i];
2210 p = (extend ? pe->ext_pointer : pe->part_table);
2211 if (p != NULL) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002212 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 +02002213 i + 1, p->boot_ind,
2214 p->head,
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002215 sector(p->sector),
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002216 cylinder(p->sector, p->cyl),
2217 p->end_head,
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002218 sector(p->end_sector),
2219 cylinder(p->end_sector, p->end_cyl),
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002220 get_start_sect(p),
2221 get_nr_sects(p),
2222 p->sys_ind
2223 );
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002224 if (p->sys_ind)
2225 check_consistency(p, i);
2226 }
2227 }
2228}
2229#endif
2230
Denis Vlasenko834410a2006-11-29 12:00:28 +00002231#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002232static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002233fill_bounds(sector_t *first, sector_t *last)
Rob Landleyb73451d2006-02-24 16:29:00 +00002234{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002235 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002236 const struct pte *pe = &ptes[0];
2237 const struct partition *p;
2238
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002239 for (i = 0; i < g_partitions; pe++,i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002240 p = pe->part_table;
Rob Landleyb73451d2006-02-24 16:29:00 +00002241 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002242 first[i] = 0xffffffff;
2243 last[i] = 0;
2244 } else {
Denys Vlasenkod958e902010-04-06 02:32:26 +02002245 first[i] = get_partition_start_from_dev_start(pe);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002246 last[i] = first[i] + get_nr_sects(p) - 1;
2247 }
2248 }
2249}
2250
2251static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002252check(int n, unsigned h, unsigned s, unsigned c, sector_t start)
Rob Landleyb73451d2006-02-24 16:29:00 +00002253{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002254 sector_t total, real_s, real_c;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002255
2256 real_s = sector(s) - 1;
2257 real_c = cylinder(s, c);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002258 total = (real_c * g_sectors + real_s) * g_heads + h;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002259 if (!total)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002260 printf("Partition %u contains sector 0\n", n);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002261 if (h >= g_heads)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002262 printf("Partition %u: head %u greater than maximum %u\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002263 n, h + 1, g_heads);
2264 if (real_s >= g_sectors)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002265 printf("Partition %u: sector %u greater than "
2266 "maximum %u\n", n, s, g_sectors);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002267 if (real_c >= g_cylinders)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002268 printf("Partition %u: cylinder %"SECT_FMT"u greater than "
2269 "maximum %u\n", n, real_c + 1, g_cylinders);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002270 if (g_cylinders <= 1024 && start != total)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002271 printf("Partition %u: previous sectors %"SECT_FMT"u disagrees with "
2272 "total %"SECT_FMT"u\n", n, start, total);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002273}
2274
2275static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002276verify(void)
2277{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002278 int i, j;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002279 sector_t total = 1;
2280 sector_t first[g_partitions], last[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002281 struct partition *p;
2282
2283 if (warn_geometry())
2284 return;
2285
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002286 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002287 verify_sun();
2288 return;
2289 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002290 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002291 verify_sgi(1);
2292 return;
2293 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002294
2295 fill_bounds(first, last);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002296 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002297 struct pte *pe = &ptes[i];
2298
2299 p = pe->part_table;
Rob Landleyb73451d2006-02-24 16:29:00 +00002300 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002301 check_consistency(p, i);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002302 if (get_partition_start_from_dev_start(pe) < first[i])
Denis Vlasenkobd852072007-03-19 14:43:38 +00002303 printf("Warning: bad start-of-data in "
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002304 "partition %u\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002305 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
2306 last[i]);
2307 total += last[i] + 1 - first[i];
Denis Vlasenkobd852072007-03-19 14:43:38 +00002308 for (j = 0; j < i; j++) {
2309 if ((first[i] >= first[j] && first[i] <= last[j])
2310 || ((last[i] <= last[j] && last[i] >= first[j]))) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002311 printf("Warning: partition %u overlaps "
2312 "partition %u\n", j + 1, i + 1);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002313 total += first[i] >= first[j] ?
2314 first[i] : first[j];
2315 total -= last[i] <= last[j] ?
2316 last[i] : last[j];
2317 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002318 }
2319 }
2320 }
2321
2322 if (extended_offset) {
2323 struct pte *pex = &ptes[ext_index];
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002324 sector_t e_last = get_start_sect(pex->part_table) +
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002325 get_nr_sects(pex->part_table) - 1;
2326
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002327 for (i = 4; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002328 total++;
2329 p = ptes[i].part_table;
2330 if (!p->sys_ind) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002331 if (i != 4 || i + 1 < g_partitions)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002332 printf("Warning: partition %u "
Denis Vlasenkobd852072007-03-19 14:43:38 +00002333 "is empty\n", i + 1);
2334 } else if (first[i] < extended_offset || last[i] > e_last) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002335 printf("Logical partition %u not entirely in "
2336 "partition %u\n", i + 1, ext_index + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002337 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002338 }
2339 }
2340
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002341 if (total > g_heads * g_sectors * g_cylinders)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002342 printf("Total allocated sectors %u greater than the maximum "
2343 "%u\n", total, g_heads * g_sectors * g_cylinders);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002344 else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002345 total = g_heads * g_sectors * g_cylinders - total;
Denis Vlasenkobd852072007-03-19 14:43:38 +00002346 if (total != 0)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002347 printf("%"SECT_FMT"u unallocated sectors\n", total);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002348 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002349}
2350
2351static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002352add_partition(int n, int sys)
2353{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002354 char mesg[256]; /* 48 does not suffice in Japanese */
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002355 int i, num_read = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002356 struct partition *p = ptes[n].part_table;
2357 struct partition *q = ptes[ext_index].part_table;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002358 sector_t limit, temp;
2359 sector_t start, stop = 0;
2360 sector_t first[g_partitions], last[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002361
2362 if (p && p->sys_ind) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002363 printf(msg_part_already_defined, n + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002364 return;
2365 }
2366 fill_bounds(first, last);
2367 if (n < 4) {
2368 start = sector_offset;
Eric Andersen040f4402003-07-30 08:40:37 +00002369 if (display_in_cyl_units || !total_number_of_sectors)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002370 limit = (sector_t) g_heads * g_sectors * g_cylinders - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002371 else
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002372 limit = total_number_of_sectors - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002373 if (extended_offset) {
2374 first[ext_index] = extended_offset;
2375 last[ext_index] = get_start_sect(q) +
2376 get_nr_sects(q) - 1;
2377 }
2378 } else {
2379 start = extended_offset + sector_offset;
2380 limit = get_start_sect(q) + get_nr_sects(q) - 1;
2381 }
2382 if (display_in_cyl_units)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002383 for (i = 0; i < g_partitions; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002384 first[i] = (cround(first[i]) - 1) * units_per_sector;
2385
Denis Vlasenkobd852072007-03-19 14:43:38 +00002386 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002387 do {
2388 temp = start;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002389 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002390 int lastplusoff;
2391
Denys Vlasenkod958e902010-04-06 02:32:26 +02002392 if (start == ptes[i].offset_from_dev_start)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002393 start += sector_offset;
Rob Landleyb73451d2006-02-24 16:29:00 +00002394 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002395 if (start >= first[i] && start <= lastplusoff)
2396 start = lastplusoff + 1;
2397 }
2398 if (start > limit)
2399 break;
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002400 if (start >= temp+units_per_sector && num_read) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002401 printf("Sector %"SECT_FMT"u is already allocated\n", temp);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002402 temp = start;
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002403 num_read = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002404 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002405 if (!num_read && start == temp) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002406 sector_t saved_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002407
2408 saved_start = start;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002409 start = read_int(cround(saved_start), cround(saved_start), cround(limit), 0, mesg);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002410 if (display_in_cyl_units) {
2411 start = (start - 1) * units_per_sector;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002412 if (start < saved_start)
2413 start = saved_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002414 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002415 num_read = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002416 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002417 } while (start != temp || !num_read);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002418 if (n > 4) { /* NOT for fifth partition */
2419 struct pte *pe = &ptes[n];
2420
Denys Vlasenkod958e902010-04-06 02:32:26 +02002421 pe->offset_from_dev_start = start - sector_offset;
2422 if (pe->offset_from_dev_start == extended_offset) { /* must be corrected */
2423 pe->offset_from_dev_start++;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002424 if (sector_offset == 1)
2425 start++;
2426 }
2427 }
2428
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002429 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002430 struct pte *pe = &ptes[i];
2431
Denys Vlasenkod958e902010-04-06 02:32:26 +02002432 if (start < pe->offset_from_dev_start && limit >= pe->offset_from_dev_start)
2433 limit = pe->offset_from_dev_start - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002434 if (start < first[i] && limit >= first[i])
2435 limit = first[i] - 1;
2436 }
2437 if (start > limit) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002438 puts("No free sectors available");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002439 if (n > 4)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002440 g_partitions--;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002441 return;
2442 }
2443 if (cround(start) == cround(limit)) {
2444 stop = limit;
2445 } else {
2446 snprintf(mesg, sizeof(mesg),
Denis Vlasenkobd852072007-03-19 14:43:38 +00002447 "Last %s or +size or +sizeM or +sizeK",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002448 str_units(SINGULAR));
Denys Vlasenkod958e902010-04-06 02:32:26 +02002449 stop = read_int(cround(start), cround(limit), cround(limit), cround(start), mesg);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002450 if (display_in_cyl_units) {
2451 stop = stop * units_per_sector - 1;
2452 if (stop >limit)
2453 stop = limit;
2454 }
2455 }
2456
2457 set_partition(n, 0, start, stop, sys);
2458 if (n > 4)
Denys Vlasenkod958e902010-04-06 02:32:26 +02002459 set_partition(n - 1, 1, ptes[n].offset_from_dev_start, stop, EXTENDED);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002460
Rob Landleyb73451d2006-02-24 16:29:00 +00002461 if (IS_EXTENDED(sys)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002462 struct pte *pe4 = &ptes[4];
2463 struct pte *pen = &ptes[n];
2464
2465 ext_index = n;
2466 pen->ext_pointer = p;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002467 pe4->offset_from_dev_start = extended_offset = start;
Rob Landley081e3842006-08-03 20:07:35 +00002468 pe4->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002469 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2470 pe4->ext_pointer = pe4->part_table + 1;
2471 pe4->changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002472 g_partitions = 5;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002473 }
2474}
2475
2476static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002477add_logical(void)
2478{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002479 if (g_partitions > 5 || ptes[4].part_table->sys_ind) {
2480 struct pte *pe = &ptes[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002481
Rob Landley081e3842006-08-03 20:07:35 +00002482 pe->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002483 pe->part_table = pt_offset(pe->sectorbuffer, 0);
2484 pe->ext_pointer = pe->part_table + 1;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002485 pe->offset_from_dev_start = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002486 pe->changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002487 g_partitions++;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002488 }
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002489 add_partition(g_partitions - 1, LINUX_NATIVE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002490}
2491
2492static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002493new_partition(void)
2494{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002495 int i, free_primary = 0;
2496
2497 if (warn_geometry())
2498 return;
2499
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002500 if (LABEL_IS_SUN) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002501 add_sun_partition(get_partition(0, g_partitions), LINUX_NATIVE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002502 return;
2503 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002504 if (LABEL_IS_SGI) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002505 sgi_add_partition(get_partition(0, g_partitions), LINUX_NATIVE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002506 return;
2507 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002508 if (LABEL_IS_AIX) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002509 puts("Sorry - this fdisk cannot handle AIX disk labels.\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +00002510"If you want to add DOS-type partitions, create a new empty DOS partition\n"
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002511"table first (use 'o'). This will destroy the present disk contents.");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002512 return;
2513 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002514
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002515 for (i = 0; i < 4; i++)
2516 free_primary += !ptes[i].part_table->sys_ind;
Eric Andersenc48d49a2003-07-03 10:02:32 +00002517
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002518 if (!free_primary && g_partitions >= MAXIMUM_PARTS) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002519 puts("The maximum number of partitions has been created");
Eric Andersen84bdea82004-05-19 10:49:17 +00002520 return;
Rob Landleyb73451d2006-02-24 16:29:00 +00002521 }
Eric Andersenc48d49a2003-07-03 10:02:32 +00002522
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002523 if (!free_primary) {
2524 if (extended_offset)
2525 add_logical();
2526 else
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002527 puts("You must delete some partition and add "
2528 "an extended partition first");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002529 } else {
Denis Vlasenkodfce08f2007-03-19 14:45:10 +00002530 char c, line[80];
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00002531 snprintf(line, sizeof(line),
2532 "Command action\n"
2533 " %s\n"
2534 " p primary partition (1-4)\n",
2535 (extended_offset ?
2536 "l logical (5 or over)" : "e extended"));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002537 while (1) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002538 c = read_nonempty(line);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002539 if ((c | 0x20) == 'p') {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002540 i = get_nonexisting_partition(0, 4);
2541 if (i >= 0)
2542 add_partition(i, LINUX_NATIVE);
2543 return;
2544 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002545 if (c == 'l' && extended_offset) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002546 add_logical();
2547 return;
2548 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002549 if (c == 'e' && !extended_offset) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002550 i = get_nonexisting_partition(0, 4);
2551 if (i >= 0)
2552 add_partition(i, EXTENDED);
2553 return;
2554 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002555 printf("Invalid partition number "
2556 "for type '%c'\n", c);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002557 }
2558 }
2559}
2560
2561static void
Denys Vlasenkob347df92011-08-09 22:49:15 +02002562reread_partition_table(int leave)
2563{
2564 int i;
2565
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002566 puts("Calling ioctl() to re-read partition table");
Denys Vlasenkob347df92011-08-09 22:49:15 +02002567 sync();
2568 /* Users with slow external USB disks on a 320MHz ARM system (year 2011)
2569 * report that sleep is needed, otherwise BLKRRPART may fail with -EIO:
2570 */
2571 sleep(1);
2572 i = ioctl_or_perror(dev_fd, BLKRRPART, NULL,
2573 "WARNING: rereading partition table "
2574 "failed, kernel still uses old table");
2575#if 0
2576 if (dos_changed)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002577 puts(
Denys Vlasenkob347df92011-08-09 22:49:15 +02002578 "\nWARNING: If you have created or modified any DOS 6.x\n"
2579 "partitions, please see the fdisk manual page for additional\n"
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002580 "information");
Denys Vlasenkob347df92011-08-09 22:49:15 +02002581#endif
2582
2583 if (leave) {
2584 if (ENABLE_FEATURE_CLEAN_UP)
2585 close_dev_fd();
2586 exit(i != 0);
2587 }
2588}
2589
2590static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002591write_table(void)
2592{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002593 int i;
2594
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002595 if (LABEL_IS_DOS) {
Rob Landleyb73451d2006-02-24 16:29:00 +00002596 for (i = 0; i < 3; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002597 if (ptes[i].changed)
2598 ptes[3].changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002599 for (i = 3; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002600 struct pte *pe = &ptes[i];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002601 if (pe->changed) {
2602 write_part_table_flag(pe->sectorbuffer);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002603 write_sector(pe->offset_from_dev_start, pe->sectorbuffer);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002604 }
2605 }
2606 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002607 else if (LABEL_IS_SGI) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002608 /* no test on change? the "altered" msg below might be mistaken */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002609 sgi_write_table();
2610 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002611 else if (LABEL_IS_SUN) {
Denys Vlasenko80856b32011-07-13 09:06:32 +02002612 for (i = 0; i < 8; i++) {
2613 if (ptes[i].changed) {
2614 sun_write_table();
2615 break;
2616 }
2617 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002618 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002619
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002620 puts("The partition table has been altered.");
Denys Vlasenkob347df92011-08-09 22:49:15 +02002621 reread_partition_table(1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002622}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00002623#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002624
Denis Vlasenko834410a2006-11-29 12:00:28 +00002625#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002626#define MAX_PER_LINE 16
2627static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002628print_buffer(char *pbuffer)
2629{
2630 int i,l;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002631
2632 for (i = 0, l = 0; i < sector_size; i++, l++) {
2633 if (l == 0)
2634 printf("0x%03X:", i);
2635 printf(" %02X", (unsigned char) pbuffer[i]);
2636 if (l == MAX_PER_LINE - 1) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002637 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002638 l = -1;
2639 }
2640 }
2641 if (l > 0)
Denis Vlasenko4daad902007-09-27 10:20:47 +00002642 bb_putchar('\n');
2643 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002644}
2645
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002646static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002647print_raw(void)
2648{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002649 int i;
2650
Denis Vlasenkobd852072007-03-19 14:43:38 +00002651 printf("Device: %s\n", disk_device);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002652 if (LABEL_IS_SGI || LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002653 print_buffer(MBRbuffer);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002654 else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002655 for (i = 3; i < g_partitions; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002656 print_buffer(ptes[i].sectorbuffer);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002657 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002658}
2659
2660static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002661move_begin(unsigned i)
Rob Landleyb73451d2006-02-24 16:29:00 +00002662{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002663 struct pte *pe = &ptes[i];
2664 struct partition *p = pe->part_table;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002665 sector_t new, first, nr_sects;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002666
2667 if (warn_geometry())
2668 return;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002669 nr_sects = get_nr_sects(p);
2670 if (!p->sys_ind || !nr_sects || IS_EXTENDED(p->sys_ind)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002671 printf("Partition %u has no data area\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002672 return;
2673 }
Denys Vlasenkofcad7682010-04-06 16:56:33 +02002674 first = get_partition_start_from_dev_start(pe); /* == pe->offset_from_dev_start + get_start_sect(p) */
Denys Vlasenkod958e902010-04-06 02:32:26 +02002675 new = read_int(0 /*was:first*/, first, first + nr_sects - 1, first, "New beginning of data");
2676 if (new != first) {
2677 sector_t new_relative = new - pe->offset_from_dev_start;
2678 nr_sects += (get_start_sect(p) - new_relative);
2679 set_start_sect(p, new_relative);
2680 set_nr_sects(p, nr_sects);
2681 read_nonempty("Recalculate C/H/S values? (Y/N): ");
2682 if ((line_ptr[0] | 0x20) == 'y')
2683 set_hsc_start_end(p, new, new + nr_sects - 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002684 pe->changed = 1;
2685 }
2686}
2687
2688static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002689xselect(void)
2690{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002691 char c;
2692
Rob Landleyb73451d2006-02-24 16:29:00 +00002693 while (1) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002694 bb_putchar('\n');
Denys Vlasenkod958e902010-04-06 02:32:26 +02002695 c = 0x20 | read_nonempty("Expert command (m for help): ");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002696 switch (c) {
2697 case 'a':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002698 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002699 sun_set_alt_cyl();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002700 break;
2701 case 'b':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002702 if (LABEL_IS_DOS)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002703 move_begin(get_partition(0, g_partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002704 break;
2705 case 'c':
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002706 user_cylinders = g_cylinders =
2707 read_int(1, g_cylinders, 1048576, 0,
Denis Vlasenkobd852072007-03-19 14:43:38 +00002708 "Number of cylinders");
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002709 if (LABEL_IS_SUN)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002710 sun_set_ncyl(g_cylinders);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002711 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002712 warn_cylinders();
2713 break;
2714 case 'd':
2715 print_raw();
2716 break;
2717 case 'e':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002718 if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002719 sgi_set_xcyl();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002720 else if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002721 sun_set_xcyl();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002722 else if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002723 x_list_table(1);
2724 break;
2725 case 'f':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002726 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002727 fix_partition_table_order();
2728 break;
2729 case 'g':
Denis Vlasenko834410a2006-11-29 12:00:28 +00002730#if ENABLE_FEATURE_SGI_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002731 create_sgilabel();
2732#endif
2733 break;
2734 case 'h':
Denys Vlasenkod958e902010-04-06 02:32:26 +02002735 user_heads = g_heads = read_int(1, g_heads, 256, 0, "Number of heads");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002736 update_units();
2737 break;
2738 case 'i':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002739 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002740 sun_set_ilfact();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002741 break;
2742 case 'o':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002743 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002744 sun_set_rspeed();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002745 break;
2746 case 'p':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002747 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002748 list_table(1);
2749 else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002750 x_list_table(0);
2751 break;
2752 case 'q':
Denis Vlasenko4437d192008-04-17 00:12:10 +00002753 if (ENABLE_FEATURE_CLEAN_UP)
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002754 close_dev_fd();
Denis Vlasenko4daad902007-09-27 10:20:47 +00002755 bb_putchar('\n');
Bernhard Reutner-Fischer636a1f82008-05-19 09:29:47 +00002756 exit(EXIT_SUCCESS);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002757 case 'r':
2758 return;
2759 case 's':
Denys Vlasenkod958e902010-04-06 02:32:26 +02002760 user_sectors = g_sectors = read_int(1, g_sectors, 63, 0, "Number of sectors");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002761 if (dos_compatible_flag) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002762 sector_offset = g_sectors;
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002763 puts("Warning: setting sector offset for DOS "
2764 "compatiblity");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002765 }
2766 update_units();
2767 break;
2768 case 'v':
2769 verify();
2770 break;
2771 case 'w':
2772 write_table(); /* does not return */
2773 break;
2774 case 'y':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002775 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002776 sun_set_pcylcount();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002777 break;
2778 default:
2779 xmenu();
2780 }
2781 }
2782}
2783#endif /* ADVANCED mode */
2784
2785static int
Rob Landleyb73451d2006-02-24 16:29:00 +00002786is_ide_cdrom_or_tape(const char *device)
2787{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002788 FILE *procf;
2789 char buf[100];
2790 struct stat statbuf;
2791 int is_ide = 0;
2792
2793 /* No device was given explicitly, and we are trying some
2794 likely things. But opening /dev/hdc may produce errors like
2795 "hdc: tray open or drive not ready"
2796 if it happens to be a CD-ROM drive. It even happens that
2797 the process hangs on the attempt to read a music CD.
2798 So try to be careful. This only works since 2.1.73. */
2799
Denys Vlasenko8dff01d2015-03-12 17:48:34 +01002800 if (!is_prefixed_with(device, "/dev/hd"))
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002801 return 0;
2802
2803 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
Denis Vlasenko5415c852008-07-21 23:05:26 +00002804 procf = fopen_for_read(buf);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002805 if (procf != NULL && fgets(buf, sizeof(buf), procf))
Denys Vlasenko8dff01d2015-03-12 17:48:34 +01002806 is_ide = (is_prefixed_with(buf, "cdrom") ||
2807 is_prefixed_with(buf, "tape"));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002808 else
2809 /* Now when this proc file does not exist, skip the
2810 device when it is read-only. */
2811 if (stat(device, &statbuf) == 0)
2812 is_ide = ((statbuf.st_mode & 0222) == 0);
2813
2814 if (procf)
2815 fclose(procf);
2816 return is_ide;
2817}
2818
Rob Landley5527b912006-02-25 03:46:10 +00002819
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002820static void
Denis Vlasenko4437d192008-04-17 00:12:10 +00002821open_list_and_close(const char *device, int user_specified)
Rob Landleyb73451d2006-02-24 16:29:00 +00002822{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002823 int gb;
2824
2825 disk_device = device;
2826 if (setjmp(listingbuf))
2827 return;
2828 if (!user_specified)
2829 if (is_ide_cdrom_or_tape(device))
2830 return;
Denis Vlasenko4437d192008-04-17 00:12:10 +00002831
2832 /* Open disk_device, save file descriptor to dev_fd */
2833 errno = 0;
2834 gb = get_boot(TRY_ONLY);
2835 if (gb > 0) { /* I/O error */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002836 /* Ignore other errors, since we try IDE
2837 and SCSI hard disks which may not be
2838 installed on the system. */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002839 if (user_specified || errno == EACCES)
2840 bb_perror_msg("can't open '%s'", device);
2841 return;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002842 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00002843
2844 if (gb < 0) { /* no DOS signature */
2845 list_disk_geometry();
2846 if (LABEL_IS_AIX)
2847 goto ret;
2848#if ENABLE_FEATURE_OSF_LABEL
2849 if (bsd_trydev(device) < 0)
2850#endif
2851 printf("Disk %s doesn't contain a valid "
2852 "partition table\n", device);
2853 } else {
2854 list_table(0);
2855#if ENABLE_FEATURE_FDISK_WRITABLE
2856 if (!LABEL_IS_SUN && g_partitions > 4) {
2857 delete_partition(ext_index);
2858 }
2859#endif
2860 }
2861 ret:
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002862 close_dev_fd();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002863}
2864
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002865/* Is it a whole disk? The digit check is still useful
2866 for Xen devices for example. */
2867static int is_whole_disk(const char *disk)
2868{
2869 unsigned len;
2870 int fd = open(disk, O_RDONLY);
2871
2872 if (fd != -1) {
2873 struct hd_geometry geometry;
2874 int err = ioctl(fd, HDIO_GETGEO, &geometry);
2875 close(fd);
2876 if (!err)
2877 return (geometry.start == 0);
2878 }
2879
2880 /* Treat "nameN" as a partition name, not whole disk */
2881 /* note: mmcblk0 should work from the geometry check above */
2882 len = strlen(disk);
2883 if (len != 0 && isdigit(disk[len - 1]))
2884 return 0;
2885
2886 return 1;
2887}
2888
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002889/* for fdisk -l: try all things in /proc/partitions
2890 that look like a partition name (do not end in a digit) */
2891static void
Denis Vlasenko4437d192008-04-17 00:12:10 +00002892list_devs_in_proc_partititons(void)
Rob Landleyb73451d2006-02-24 16:29:00 +00002893{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002894 FILE *procpt;
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002895 char line[100], ptname[100], devname[120];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002896 int ma, mi, sz;
2897
Denis Vlasenkoddec5af2006-10-26 23:25:17 +00002898 procpt = fopen_or_warn("/proc/partitions", "r");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002899
2900 while (fgets(line, sizeof(line), procpt)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002901 if (sscanf(line, " %u %u %u %[^\n ]",
Rob Landleyb73451d2006-02-24 16:29:00 +00002902 &ma, &mi, &sz, ptname) != 4)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002903 continue;
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002904
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002905 sprintf(devname, "/dev/%s", ptname);
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002906 if (is_whole_disk(devname))
2907 open_list_and_close(devname, 0);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002908 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002909#if ENABLE_FEATURE_CLEAN_UP
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002910 fclose(procpt);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002911#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002912}
2913
Denis Vlasenko834410a2006-11-29 12:00:28 +00002914#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002915static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002916unknown_command(int c)
2917{
Denis Vlasenkobd852072007-03-19 14:43:38 +00002918 printf("%c: unknown command\n", c);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002919}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002920#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002921
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00002922int fdisk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002923int fdisk_main(int argc UNUSED_PARAM, char **argv)
Rob Landleyb73451d2006-02-24 16:29:00 +00002924{
Denis Vlasenko834410a2006-11-29 12:00:28 +00002925 unsigned opt;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002926 /*
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002927 * fdisk -v
2928 * fdisk -l [-b sectorsize] [-u] device ...
2929 * fdisk -s [partition] ...
2930 * fdisk [-b sectorsize] [-u] device
2931 *
2932 * Options -C, -H, -S set the geometry.
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002933 */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002934 INIT_G();
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +00002935
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002936 close_dev_fd(); /* needed: fd 3 must not stay closed */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002937
Denys Vlasenko237bedd2016-07-06 21:58:02 +02002938 opt = getopt32(argv, "b:+C:+H:+lS:+u" IF_FEATURE_FDISK_BLKSIZE("s"),
Denis Vlasenko04e11c92008-02-10 19:44:20 +00002939 &sector_size, &user_cylinders, &user_heads, &user_sectors);
Denis Vlasenko834410a2006-11-29 12:00:28 +00002940 argv += optind;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002941 if (opt & OPT_b) {
Denis Vlasenko834410a2006-11-29 12:00:28 +00002942 /* Ugly: this sector size is really per device,
Denys Vlasenkod958e902010-04-06 02:32:26 +02002943 * so cannot be combined with multiple disks,
2944 * and the same goes for the C/H/S options.
2945 */
2946 if (sector_size < 512
2947 || sector_size > 0x10000
2948 || (sector_size & (sector_size-1)) /* not power of 2 */
2949 ) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002950 bb_show_usage();
Denys Vlasenkod958e902010-04-06 02:32:26 +02002951 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002952 sector_offset = 2;
2953 user_set_sector_size = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002954 }
Denis Vlasenko04e11c92008-02-10 19:44:20 +00002955 if (user_heads <= 0 || user_heads >= 256)
2956 user_heads = 0;
2957 if (user_sectors <= 0 || user_sectors >= 64)
2958 user_sectors = 0;
2959 if (opt & OPT_u)
2960 display_in_cyl_units = 0; // -u
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002961
Denis Vlasenko834410a2006-11-29 12:00:28 +00002962#if ENABLE_FEATURE_FDISK_WRITABLE
2963 if (opt & OPT_l) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002964 nowarn = 1;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002965#endif
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002966 if (*argv) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002967 listing = 1;
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002968 do {
Denis Vlasenko4437d192008-04-17 00:12:10 +00002969 open_list_and_close(*argv, 1);
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002970 } while (*++argv);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002971 } else {
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002972 /* we don't have device names, */
2973 /* use /proc/partitions instead */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002974 list_devs_in_proc_partititons();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002975 }
2976 return 0;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002977#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002978 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002979#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002980
Denis Vlasenko834410a2006-11-29 12:00:28 +00002981#if ENABLE_FEATURE_FDISK_BLKSIZE
2982 if (opt & OPT_s) {
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002983 int j;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002984
2985 nowarn = 1;
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002986 if (!argv[0])
Manuel Novoa III cad53642003-03-19 09:13:01 +00002987 bb_show_usage();
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002988 for (j = 0; argv[j]; j++) {
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002989 unsigned long long size;
2990 fd = xopen(argv[j], O_RDONLY);
Denis Vlasenko4437d192008-04-17 00:12:10 +00002991 size = bb_BLKGETSIZE_sectors(fd) / 2;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002992 close(fd);
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002993 if (argv[1])
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002994 printf("%llu\n", size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002995 else
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002996 printf("%s: %llu\n", argv[j], size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002997 }
2998 return 0;
2999 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00003000#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003001
Denis Vlasenko834410a2006-11-29 12:00:28 +00003002#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01003003 if (!argv[0] || argv[1])
Manuel Novoa III cad53642003-03-19 09:13:01 +00003004 bb_show_usage();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003005
Denis Vlasenko834410a2006-11-29 12:00:28 +00003006 disk_device = argv[0];
Denis Vlasenko4437d192008-04-17 00:12:10 +00003007 get_boot(OPEN_MAIN);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003008
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003009 if (LABEL_IS_OSF) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003010 /* OSF label, and no DOS label */
Denis Vlasenkobd852072007-03-19 14:43:38 +00003011 printf("Detected an OSF/1 disklabel on %s, entering "
3012 "disklabel mode\n", disk_device);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +00003013 bsd_select();
Rob Landley5527b912006-02-25 03:46:10 +00003014 /*Why do we do this? It seems to be counter-intuitive*/
Denis Vlasenko4437d192008-04-17 00:12:10 +00003015 current_label_type = LABEL_DOS;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003016 /* If we return we may want to make an empty DOS label? */
3017 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003018
3019 while (1) {
Denis Vlasenko3bba5452006-12-30 17:57:03 +00003020 int c;
Denis Vlasenko4daad902007-09-27 10:20:47 +00003021 bb_putchar('\n');
Denys Vlasenkod958e902010-04-06 02:32:26 +02003022 c = 0x20 | read_nonempty("Command (m for help): ");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003023 switch (c) {
3024 case 'a':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003025 if (LABEL_IS_DOS)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003026 toggle_active(get_partition(1, g_partitions));
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003027 else if (LABEL_IS_SUN)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003028 toggle_sunflags(get_partition(1, g_partitions),
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003029 0x01);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003030 else if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003031 sgi_set_bootpartition(
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003032 get_partition(1, g_partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003033 else
3034 unknown_command(c);
3035 break;
3036 case 'b':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003037 if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00003038 printf("\nThe current boot file is: %s\n",
Rob Landleyb73451d2006-02-24 16:29:00 +00003039 sgi_get_bootfile());
Denis Vlasenkobd852072007-03-19 14:43:38 +00003040 if (read_maybe_empty("Please enter the name of the "
Denys Vlasenko69675782013-01-14 01:34:48 +01003041 "new boot file: ") == '\n')
Denys Vlasenkod60752f2015-10-07 22:42:45 +02003042 puts("Boot file unchanged");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003043 else
3044 sgi_set_bootfile(line_ptr);
Denis Vlasenko834410a2006-11-29 12:00:28 +00003045 }
3046#if ENABLE_FEATURE_OSF_LABEL
3047 else
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +00003048 bsd_select();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003049#endif
3050 break;
3051 case 'c':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003052 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003053 toggle_dos_compatibility_flag();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003054 else if (LABEL_IS_SUN)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003055 toggle_sunflags(get_partition(1, g_partitions),
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003056 0x10);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003057 else if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003058 sgi_set_swappartition(
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003059 get_partition(1, g_partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003060 else
3061 unknown_command(c);
3062 break;
3063 case 'd':
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00003064 {
Eric Andersen040f4402003-07-30 08:40:37 +00003065 int j;
Eric Andersen040f4402003-07-30 08:40:37 +00003066 /* If sgi_label then don't use get_existing_partition,
3067 let the user select a partition, since
3068 get_existing_partition() only works for Linux-like
3069 partition tables */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003070 if (!LABEL_IS_SGI) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003071 j = get_existing_partition(1, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00003072 } else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003073 j = get_partition(1, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00003074 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00003075 if (j >= 0)
3076 delete_partition(j);
3077 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003078 break;
3079 case 'i':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003080 if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003081 create_sgiinfo();
3082 else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003083 unknown_command(c);
3084 case 'l':
3085 list_types(get_sys_types());
3086 break;
3087 case 'm':
3088 menu();
3089 break;
3090 case 'n':
3091 new_partition();
3092 break;
3093 case 'o':
3094 create_doslabel();
3095 break;
3096 case 'p':
3097 list_table(0);
3098 break;
3099 case 'q':
Denis Vlasenkoc033d512008-04-17 01:52:28 +00003100 if (ENABLE_FEATURE_CLEAN_UP)
3101 close_dev_fd();
Denis Vlasenko4daad902007-09-27 10:20:47 +00003102 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003103 return 0;
3104 case 's':
Denis Vlasenko834410a2006-11-29 12:00:28 +00003105#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003106 create_sunlabel();
3107#endif
3108 break;
3109 case 't':
3110 change_sysid();
3111 break;
3112 case 'u':
3113 change_units();
3114 break;
3115 case 'v':
3116 verify();
3117 break;
3118 case 'w':
Denys Vlasenko80856b32011-07-13 09:06:32 +02003119 write_table(); /* does not return */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003120 break;
Denis Vlasenko834410a2006-11-29 12:00:28 +00003121#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003122 case 'x':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003123 if (LABEL_IS_SGI) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02003124 puts("\n\tSorry, no experts menu for SGI "
3125 "partition tables available\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003126 } else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003127 xselect();
3128 break;
3129#endif
3130 default:
3131 unknown_command(c);
3132 menu();
3133 }
3134 }
3135 return 0;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003136#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003137}