blob: 32a66d03d939d610fd285eda9f66440687b11519 [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
Denys Vlasenkob157eb12016-09-17 21:05:06 +0200476/* Return partition name */
477static const char *
478partname(const char *dev, int pno, int lth)
479{
480 const char *p;
481 int w, wp;
482 int bufsiz;
483 char *bufp;
484
485 bufp = auto_string(xzalloc(80));
486 bufsiz = 80;
487
488 w = strlen(dev);
489 p = "";
490
491 if (isdigit(dev[w-1]))
492 p = "p";
493
494 /* devfs kludge - note: fdisk partition names are not supposed
495 to equal kernel names, so there is no reason to do this */
496 if (strcmp(dev + w - 4, "disc") == 0) {
497 w -= 4;
498 p = "part";
499 }
500
501 wp = strlen(p);
502
503 if (lth) {
504 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
505 lth-wp-2, w, dev, p, pno);
506 } else {
507 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
508 }
509 return bufp;
510}
511
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000512static ALWAYS_INLINE struct partition *
Rob Landleyb73451d2006-02-24 16:29:00 +0000513get_part_table(int i)
514{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000515 return ptes[i].part_table;
516}
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000517
518static const char *
Rob Landleyb73451d2006-02-24 16:29:00 +0000519str_units(int n)
520{ /* n==1: use singular */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000521 if (n == 1)
Denis Vlasenkobd852072007-03-19 14:43:38 +0000522 return display_in_cyl_units ? "cylinder" : "sector";
523 return display_in_cyl_units ? "cylinders" : "sectors";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000524}
525
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000526static int
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000527valid_part_table_flag(const char *mbuffer)
528{
Denis Vlasenko834410a2006-11-29 12:00:28 +0000529 return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000530}
531
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200532static void fdisk_fatal(const char *why)
533{
534 if (listing) {
535 close_dev_fd();
536 longjmp(listingbuf, 1);
537 }
538 bb_error_msg_and_die(why, disk_device);
539}
540
541static void
542seek_sector(sector_t secno)
543{
544#if ENABLE_FDISK_SUPPORT_LARGE_DISKS
545 off64_t off = (off64_t)secno * sector_size;
546 if (lseek64(dev_fd, off, SEEK_SET) == (off64_t) -1)
547 fdisk_fatal(unable_to_seek);
548#else
549 uint64_t off = (uint64_t)secno * sector_size;
550 if (off > MAXINT(off_t)
551 || lseek(dev_fd, (off_t)off, SEEK_SET) == (off_t) -1
552 ) {
553 fdisk_fatal(unable_to_seek);
554 }
555#endif
556}
557
Denis Vlasenko834410a2006-11-29 12:00:28 +0000558#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200559/* Read line; return 0 or first printable char */
560static int
561read_line(const char *prompt)
562{
563 int sz;
564
Denys Vlasenko66c5b122011-02-08 05:07:02 +0100565 sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer), /*timeout*/ -1);
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200566 if (sz <= 0)
567 exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
568
569 if (line_buffer[sz-1] == '\n')
570 line_buffer[--sz] = '\0';
571
572 line_ptr = line_buffer;
573 while (*line_ptr != '\0' && (unsigned char)*line_ptr <= ' ')
574 line_ptr++;
575 return *line_ptr;
576}
577
578static void
579set_all_unchanged(void)
580{
581 int i;
582
583 for (i = 0; i < MAXIMUM_PARTS; i++)
584 ptes[i].changed = 0;
585}
586
587static ALWAYS_INLINE void
588set_changed(int i)
589{
590 ptes[i].changed = 1;
591}
592
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000593static ALWAYS_INLINE void
Denis Vlasenko834410a2006-11-29 12:00:28 +0000594write_part_table_flag(char *b)
595{
596 b[510] = 0x55;
597 b[511] = 0xaa;
598}
599
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000600static char
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000601read_nonempty(const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000602{
Denis Vlasenko9764d692008-07-09 21:20:50 +0000603 while (!read_line(mesg))
604 continue;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000605 return *line_ptr;
606}
607
608static char
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000609read_maybe_empty(const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000610{
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000611 if (!read_line(mesg)) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000612 line_ptr = line_buffer;
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000613 line_ptr[0] = '\n';
614 line_ptr[1] = '\0';
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000615 }
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000616 return line_ptr[0];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000617}
618
619static int
Denis Vlasenkobd852072007-03-19 14:43:38 +0000620read_hex(const char *const *sys)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000621{
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000622 unsigned long v;
Rob Landleyb73451d2006-02-24 16:29:00 +0000623 while (1) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000624 read_nonempty("Hex code (type L to list codes): ");
Denys Vlasenkod958e902010-04-06 02:32:26 +0200625 if ((line_ptr[0] | 0x20) == 'l') {
Rob Landleyb73451d2006-02-24 16:29:00 +0000626 list_types(sys);
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000627 continue;
Rob Landleyb73451d2006-02-24 16:29:00 +0000628 }
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000629 v = bb_strtoul(line_ptr, NULL, 16);
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200630 if (v <= 0xff)
631 return v;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000632 }
633}
634
Denis Vlasenko9764d692008-07-09 21:20:50 +0000635static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200636write_sector(sector_t secno, const void *buf)
Denis Vlasenko9764d692008-07-09 21:20:50 +0000637{
638 seek_sector(secno);
639 xwrite(dev_fd, buf, sector_size);
640}
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200641#endif /* FEATURE_FDISK_WRITABLE */
Denis Vlasenko9764d692008-07-09 21:20:50 +0000642
643
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000644#include "fdisk_aix.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000645
Denys Vlasenko36659fd2010-02-05 14:40:23 +0100646struct sun_partition {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000647 unsigned char info[128]; /* Informative text string */
648 unsigned char spare0[14];
649 struct sun_info {
650 unsigned char spare1;
651 unsigned char id;
652 unsigned char spare2;
653 unsigned char flags;
654 } infos[8];
655 unsigned char spare1[246]; /* Boot information etc. */
656 unsigned short rspeed; /* Disk rotational speed */
657 unsigned short pcylcount; /* Physical cylinder count */
658 unsigned short sparecyl; /* extra sects per cylinder */
659 unsigned char spare2[4]; /* More magic... */
660 unsigned short ilfact; /* Interleave factor */
661 unsigned short ncyl; /* Data cylinder count */
662 unsigned short nacyl; /* Alt. cylinder count */
663 unsigned short ntrks; /* Tracks per cylinder */
664 unsigned short nsect; /* Sectors per track */
665 unsigned char spare3[4]; /* Even more magic... */
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000666 struct sun_partinfo {
Eric Andersenacd244a2002-12-11 03:49:33 +0000667 uint32_t start_cylinder;
668 uint32_t num_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000669 } partitions[8];
670 unsigned short magic; /* Magic number */
671 unsigned short csum; /* Label xor'd checksum */
Denys Vlasenko36659fd2010-02-05 14:40:23 +0100672} FIX_ALIASING;
673typedef struct sun_partition sun_partition;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000674#define sunlabel ((sun_partition *)MBRbuffer)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000675STATIC_OSF void bsd_select(void);
676STATIC_OSF void xbsd_print_disklabel(int);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000677#include "fdisk_osf.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000678
Denys Vlasenkod7559c22010-10-30 02:40:08 +0200679STATIC_GPT void gpt_list_table(int xtra);
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200680#include "fdisk_gpt.c"
681
Denis Vlasenko28703012006-12-19 20:32:02 +0000682#if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000683static uint16_t
Denis Vlasenko28703012006-12-19 20:32:02 +0000684fdisk_swap16(uint16_t x)
Rob Landleyb73451d2006-02-24 16:29:00 +0000685{
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000686 return (x << 8) | (x >> 8);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000687}
688
Rob Landley88621d72006-08-29 19:41:06 +0000689static uint32_t
Denis Vlasenko28703012006-12-19 20:32:02 +0000690fdisk_swap32(uint32_t x)
Rob Landleyb73451d2006-02-24 16:29:00 +0000691{
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000692 return (x << 24) |
693 ((x & 0xFF00) << 8) |
694 ((x & 0xFF0000) >> 8) |
695 (x >> 24);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000696}
697#endif
698
Denis Vlasenkobd852072007-03-19 14:43:38 +0000699STATIC_SGI const char *const sgi_sys_types[];
Denis Vlasenko834410a2006-11-29 12:00:28 +0000700STATIC_SGI unsigned sgi_get_num_sectors(int i);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000701STATIC_SGI int sgi_get_sysid(int i);
702STATIC_SGI void sgi_delete_partition(int i);
703STATIC_SGI void sgi_change_sysid(int i, int sys);
704STATIC_SGI void sgi_list_table(int xtra);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000705#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000706STATIC_SGI void sgi_set_xcyl(void);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000707#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000708STATIC_SGI int verify_sgi(int verbose);
709STATIC_SGI void sgi_add_partition(int n, int sys);
710STATIC_SGI void sgi_set_swappartition(int i);
711STATIC_SGI const char *sgi_get_bootfile(void);
712STATIC_SGI void sgi_set_bootfile(const char* aFile);
713STATIC_SGI void create_sgiinfo(void);
714STATIC_SGI void sgi_write_table(void);
715STATIC_SGI void sgi_set_bootpartition(int i);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000716#include "fdisk_sgi.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000717
Denis Vlasenkobd852072007-03-19 14:43:38 +0000718STATIC_SUN const char *const sun_sys_types[];
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000719STATIC_SUN void sun_delete_partition(int i);
720STATIC_SUN void sun_change_sysid(int i, int sys);
721STATIC_SUN void sun_list_table(int xtra);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000722STATIC_SUN void add_sun_partition(int n, int sys);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000723#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000724STATIC_SUN void sun_set_alt_cyl(void);
725STATIC_SUN void sun_set_ncyl(int cyl);
726STATIC_SUN void sun_set_xcyl(void);
727STATIC_SUN void sun_set_ilfact(void);
728STATIC_SUN void sun_set_rspeed(void);
729STATIC_SUN void sun_set_pcylcount(void);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000730#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000731STATIC_SUN void toggle_sunflags(int i, unsigned char mask);
732STATIC_SUN void verify_sun(void);
733STATIC_SUN void sun_write_table(void);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000734#include "fdisk_sun.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000735
Denis Vlasenko9764d692008-07-09 21:20:50 +0000736
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200737static inline_if_little_endian unsigned
Rob Landleyb73451d2006-02-24 16:29:00 +0000738read4_little_endian(const unsigned char *cp)
739{
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200740 uint32_t v;
741 move_from_unaligned32(v, cp);
742 return SWAP_LE32(v);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000743}
744
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200745static sector_t
Rob Landleyb73451d2006-02-24 16:29:00 +0000746get_start_sect(const struct partition *p)
747{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000748 return read4_little_endian(p->start4);
749}
750
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200751static sector_t
752get_nr_sects(const struct partition *p)
753{
754 return read4_little_endian(p->size4);
755}
756
Denis Vlasenko834410a2006-11-29 12:00:28 +0000757#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200758/* start_sect and nr_sects are stored little endian on all machines */
759/* moreover, they are not aligned correctly */
760static inline_if_little_endian void
761store4_little_endian(unsigned char *cp, unsigned val)
762{
763 uint32_t v = SWAP_LE32(val);
764 move_to_unaligned32(cp, v);
765}
766
767static void
768set_start_sect(struct partition *p, unsigned start_sect)
769{
770 store4_little_endian(p->start4, start_sect);
771}
772
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000773static void
Denis Vlasenko28703012006-12-19 20:32:02 +0000774set_nr_sects(struct partition *p, unsigned nr_sects)
Rob Landleyb73451d2006-02-24 16:29:00 +0000775{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000776 store4_little_endian(p->size4, nr_sects);
777}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000778#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000779
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000780/* Allocate a buffer and read a partition table sector */
781static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200782read_pte(struct pte *pe, sector_t offset)
Rob Landleyb73451d2006-02-24 16:29:00 +0000783{
Denys Vlasenkod958e902010-04-06 02:32:26 +0200784 pe->offset_from_dev_start = offset;
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000785 pe->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000786 seek_sector(offset);
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +0000787 /* xread would make us abort - bad for fdisk -l */
788 if (full_read(dev_fd, pe->sectorbuffer, sector_size) != sector_size)
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000789 fdisk_fatal(unable_to_read);
Denis Vlasenko834410a2006-11-29 12:00:28 +0000790#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000791 pe->changed = 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000792#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000793 pe->part_table = pe->ext_pointer = NULL;
794}
795
Denys Vlasenkoddf78502009-09-16 03:03:13 +0200796static sector_t
Denys Vlasenkod958e902010-04-06 02:32:26 +0200797get_partition_start_from_dev_start(const struct pte *pe)
Rob Landleyb73451d2006-02-24 16:29:00 +0000798{
Denys Vlasenkod958e902010-04-06 02:32:26 +0200799 return pe->offset_from_dev_start + get_start_sect(pe->part_table);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000800}
801
Denis Vlasenko834410a2006-11-29 12:00:28 +0000802#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000803/*
804 * Avoid warning about DOS partitions when no DOS partition was changed.
805 * Here a heuristic "is probably dos partition".
806 * We might also do the opposite and warn in all cases except
807 * for "is probably nondos partition".
808 */
Denis Vlasenko89398812008-01-25 20:18:46 +0000809#ifdef UNUSED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000810static int
Rob Landleyb73451d2006-02-24 16:29:00 +0000811is_dos_partition(int t)
812{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000813 return (t == 1 || t == 4 || t == 6 ||
814 t == 0x0b || t == 0x0c || t == 0x0e ||
815 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
816 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
817 t == 0xc1 || t == 0xc4 || t == 0xc6);
818}
Denis Vlasenko89398812008-01-25 20:18:46 +0000819#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000820
821static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000822menu(void)
823{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000824 puts("Command Action");
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000825 if (LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000826 puts("a\ttoggle a read only flag"); /* sun */
827 puts("b\tedit bsd disklabel");
828 puts("c\ttoggle the mountable flag"); /* sun */
829 puts("d\tdelete a partition");
830 puts("l\tlist known partition types");
831 puts("n\tadd a new partition");
832 puts("o\tcreate a new empty DOS partition table");
833 puts("p\tprint the partition table");
834 puts("q\tquit without saving changes");
835 puts("s\tcreate a new empty Sun disklabel"); /* sun */
836 puts("t\tchange a partition's system id");
837 puts("u\tchange display/entry units");
838 puts("v\tverify the partition table");
839 puts("w\twrite table to disk and exit");
Denis Vlasenko834410a2006-11-29 12:00:28 +0000840#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkobd852072007-03-19 14:43:38 +0000841 puts("x\textra functionality (experts only)");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000842#endif
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000843 } else if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000844 puts("a\tselect bootable partition"); /* sgi flavour */
845 puts("b\tedit bootfile entry"); /* sgi */
846 puts("c\tselect sgi swap partition"); /* sgi flavour */
847 puts("d\tdelete a partition");
848 puts("l\tlist known partition types");
849 puts("n\tadd a new partition");
850 puts("o\tcreate a new empty DOS partition table");
851 puts("p\tprint the partition table");
852 puts("q\tquit without saving changes");
853 puts("s\tcreate a new empty Sun disklabel"); /* sun */
854 puts("t\tchange a partition's system id");
855 puts("u\tchange display/entry units");
856 puts("v\tverify the partition table");
857 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000858 } else if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000859 puts("o\tcreate a new empty DOS partition table");
860 puts("q\tquit without saving changes");
861 puts("s\tcreate a new empty Sun disklabel"); /* sun */
Kevin Cernekeeccb07042010-10-25 02:00:24 +0200862 } else if (LABEL_IS_GPT) {
863 puts("o\tcreate a new empty DOS partition table");
864 puts("p\tprint the partition table");
865 puts("q\tquit without saving changes");
866 puts("s\tcreate a new empty Sun disklabel"); /* sun */
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000867 } else {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000868 puts("a\ttoggle a bootable flag");
869 puts("b\tedit bsd disklabel");
870 puts("c\ttoggle the dos compatibility flag");
871 puts("d\tdelete a partition");
872 puts("l\tlist known partition types");
873 puts("n\tadd a new partition");
874 puts("o\tcreate a new empty DOS partition table");
875 puts("p\tprint the partition table");
876 puts("q\tquit without saving changes");
877 puts("s\tcreate a new empty Sun disklabel"); /* sun */
878 puts("t\tchange a partition's system id");
879 puts("u\tchange display/entry units");
880 puts("v\tverify the partition table");
881 puts("w\twrite table to disk and exit");
Denis Vlasenko834410a2006-11-29 12:00:28 +0000882#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkobd852072007-03-19 14:43:38 +0000883 puts("x\textra functionality (experts only)");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000884#endif
885 }
886}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000887#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000888
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000889
Denis Vlasenko834410a2006-11-29 12:00:28 +0000890#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000891static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000892xmenu(void)
893{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000894 puts("Command Action");
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000895 if (LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000896 puts("a\tchange number of alternate cylinders"); /*sun*/
897 puts("c\tchange number of cylinders");
898 puts("d\tprint the raw data in the partition table");
899 puts("e\tchange number of extra sectors per cylinder");/*sun*/
900 puts("h\tchange number of heads");
901 puts("i\tchange interleave factor"); /*sun*/
902 puts("o\tchange rotation speed (rpm)"); /*sun*/
903 puts("p\tprint the partition table");
904 puts("q\tquit without saving changes");
905 puts("r\treturn to main menu");
906 puts("s\tchange number of sectors/track");
907 puts("v\tverify the partition table");
908 puts("w\twrite table to disk and exit");
909 puts("y\tchange number of physical cylinders"); /*sun*/
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000910 } else if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000911 puts("b\tmove beginning of data in a partition"); /* !sun */
912 puts("c\tchange number of cylinders");
913 puts("d\tprint the raw data in the partition table");
914 puts("e\tlist extended partitions"); /* !sun */
915 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
916 puts("h\tchange number of heads");
917 puts("p\tprint the partition table");
918 puts("q\tquit without saving changes");
919 puts("r\treturn to main menu");
920 puts("s\tchange number of sectors/track");
921 puts("v\tverify the partition table");
922 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000923 } else if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000924 puts("b\tmove beginning of data in a partition"); /* !sun */
925 puts("c\tchange number of cylinders");
926 puts("d\tprint the raw data in the partition table");
927 puts("e\tlist extended partitions"); /* !sun */
928 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
929 puts("h\tchange number of heads");
930 puts("p\tprint the partition table");
931 puts("q\tquit without saving changes");
932 puts("r\treturn to main menu");
933 puts("s\tchange number of sectors/track");
934 puts("v\tverify the partition table");
935 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000936 } else {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000937 puts("b\tmove beginning of data in a partition"); /* !sun */
938 puts("c\tchange number of cylinders");
939 puts("d\tprint the raw data in the partition table");
940 puts("e\tlist extended partitions"); /* !sun */
941 puts("f\tfix partition order"); /* !sun, !aix, !sgi */
Denis Vlasenko834410a2006-11-29 12:00:28 +0000942#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenkobd852072007-03-19 14:43:38 +0000943 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000944#endif
Denis Vlasenkobd852072007-03-19 14:43:38 +0000945 puts("h\tchange number of heads");
946 puts("p\tprint the partition table");
947 puts("q\tquit without saving changes");
948 puts("r\treturn to main menu");
949 puts("s\tchange number of sectors/track");
950 puts("v\tverify the partition table");
951 puts("w\twrite table to disk and exit");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000952 }
953}
954#endif /* ADVANCED mode */
955
Denis Vlasenko834410a2006-11-29 12:00:28 +0000956#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenkobd852072007-03-19 14:43:38 +0000957static const char *const *
Rob Landleyb73451d2006-02-24 16:29:00 +0000958get_sys_types(void)
959{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000960 return (
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000961 LABEL_IS_SUN ? sun_sys_types :
962 LABEL_IS_SGI ? sgi_sys_types :
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000963 i386_sys_types);
964}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000965#else
966#define get_sys_types() i386_sys_types
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200967#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000968
Denis Vlasenkobd852072007-03-19 14:43:38 +0000969static const char *
970partition_type(unsigned char type)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000971{
972 int i;
Denis Vlasenkobd852072007-03-19 14:43:38 +0000973 const char *const *types = get_sys_types();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000974
Denis Vlasenkobd852072007-03-19 14:43:38 +0000975 for (i = 0; types[i]; i++)
976 if ((unsigned char)types[i][0] == type)
977 return types[i] + 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000978
Denis Vlasenkobd852072007-03-19 14:43:38 +0000979 return "Unknown";
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000980}
981
Denys Vlasenko5ea1de22010-04-06 02:31:43 +0200982static int
983is_cleared_partition(const struct partition *p)
984{
985 /* We consider partition "cleared" only if it has only zeros */
986 const char *cp = (const char *)p;
987 int cnt = sizeof(*p);
988 char bits = 0;
989 while (--cnt >= 0)
990 bits |= *cp++;
991 return (bits == 0);
992}
993
994static void
995clear_partition(struct partition *p)
996{
997 if (p)
998 memset(p, 0, sizeof(*p));
999}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001000
Denis Vlasenko834410a2006-11-29 12:00:28 +00001001#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001002static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001003get_sysid(int i)
1004{
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001005 return LABEL_IS_SUN ? sunlabel->infos[i].id :
1006 (LABEL_IS_SGI ? sgi_get_sysid(i) :
1007 ptes[i].part_table->sys_ind);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001008}
1009
Denis Vlasenkobd852072007-03-19 14:43:38 +00001010static void
1011list_types(const char *const *sys)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001012{
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00001013 enum { COLS = 3 };
1014
1015 unsigned last[COLS];
1016 unsigned done, next, size;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001017 int i;
1018
Denis Vlasenko9764d692008-07-09 21:20:50 +00001019 for (size = 0; sys[size]; size++)
1020 continue;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001021
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00001022 done = 0;
1023 for (i = COLS-1; i >= 0; i--) {
1024 done += (size + i - done) / (i + 1);
1025 last[COLS-1 - i] = done;
1026 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001027
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00001028 i = done = next = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001029 do {
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00001030 printf("%c%2x %-22.22s", i ? ' ' : '\n',
Denis Vlasenkobd852072007-03-19 14:43:38 +00001031 (unsigned char)sys[next][0],
1032 sys[next] + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001033 next = last[i++] + done;
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00001034 if (i >= COLS || next >= last[i]) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001035 i = 0;
1036 next = ++done;
1037 }
1038 } while (done < last[0]);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001039 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001040}
1041
Denys Vlasenkod958e902010-04-06 02:32:26 +02001042#define set_hsc(h, s, c, sector) do \
1043{ \
1044 s = sector % g_sectors + 1; \
1045 sector /= g_sectors; \
1046 h = sector % g_heads; \
1047 sector /= g_heads; \
1048 c = sector & 0xff; \
1049 s |= (sector >> 2) & 0xc0; \
1050} while (0)
1051
1052static void set_hsc_start_end(struct partition *p, sector_t start, sector_t stop)
1053{
1054 if (dos_compatible_flag && (start / (g_sectors * g_heads) > 1023))
1055 start = g_heads * g_sectors * 1024 - 1;
1056 set_hsc(p->head, p->sector, p->cyl, start);
1057
1058 if (dos_compatible_flag && (stop / (g_sectors * g_heads) > 1023))
1059 stop = g_heads * g_sectors * 1024 - 1;
1060 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
1061}
1062
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001063static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001064set_partition(int i, int doext, sector_t start, sector_t stop, int sysid)
Rob Landleyb73451d2006-02-24 16:29:00 +00001065{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001066 struct partition *p;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001067 sector_t offset;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001068
1069 if (doext) {
1070 p = ptes[i].ext_pointer;
1071 offset = extended_offset;
1072 } else {
1073 p = ptes[i].part_table;
Denys Vlasenkod958e902010-04-06 02:32:26 +02001074 offset = ptes[i].offset_from_dev_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001075 }
1076 p->boot_ind = 0;
1077 p->sys_ind = sysid;
1078 set_start_sect(p, start - offset);
1079 set_nr_sects(p, stop - start + 1);
Denys Vlasenkod958e902010-04-06 02:32:26 +02001080 set_hsc_start_end(p, start, stop);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001081 ptes[i].changed = 1;
1082}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001083#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001084
1085static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001086warn_geometry(void)
1087{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001088 if (g_heads && g_sectors && g_cylinders)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001089 return 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001090
Denis Vlasenkobd852072007-03-19 14:43:38 +00001091 printf("Unknown value(s) for:");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001092 if (!g_heads)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001093 printf(" heads");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001094 if (!g_sectors)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001095 printf(" sectors");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001096 if (!g_cylinders)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001097 printf(" cylinders");
Denis Vlasenko834410a2006-11-29 12:00:28 +00001098#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001099 puts(" (settable in the extra functions menu)");
1100#else
1101 bb_putchar('\n');
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001102#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001103 return 1;
1104}
1105
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +00001106static void
1107update_units(void)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001108{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001109 int cyl_units = g_heads * g_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001110
1111 if (display_in_cyl_units && cyl_units)
1112 units_per_sector = cyl_units;
1113 else
1114 units_per_sector = 1; /* in sectors */
1115}
1116
Denis Vlasenko834410a2006-11-29 12:00:28 +00001117#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001118static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001119warn_cylinders(void)
1120{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001121 if (LABEL_IS_DOS && g_cylinders > 1024 && !nowarn)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001122 printf("\n"
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001123"The number of cylinders for this disk is set to %u.\n"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001124"There is nothing wrong with that, but this is larger than 1024,\n"
1125"and could in certain setups cause problems with:\n"
1126"1) software that runs at boot time (e.g., old versions of LILO)\n"
1127"2) booting and partitioning software from other OSs\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001128" (e.g., DOS FDISK, OS/2 FDISK)\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001129 g_cylinders);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001130}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001131#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001132
1133static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001134read_extended(int ext)
1135{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001136 int i;
1137 struct pte *pex;
1138 struct partition *p, *q;
1139
1140 ext_index = ext;
1141 pex = &ptes[ext];
1142 pex->ext_pointer = pex->part_table;
1143
1144 p = pex->part_table;
1145 if (!get_start_sect(p)) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001146 puts("Bad offset in primary extended partition");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001147 return;
1148 }
1149
Rob Landleyb73451d2006-02-24 16:29:00 +00001150 while (IS_EXTENDED(p->sys_ind)) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001151 struct pte *pe = &ptes[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001152
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001153 if (g_partitions >= MAXIMUM_PARTS) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001154 /* This is not a Linux restriction, but
1155 this program uses arrays of size MAXIMUM_PARTS.
Denis Vlasenko89f0b342006-11-18 22:04:09 +00001156 Do not try to 'improve' this test. */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001157 struct pte *pre = &ptes[g_partitions - 1];
Denis Vlasenko834410a2006-11-29 12:00:28 +00001158#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001159 printf("Warning: deleting partitions after %u\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001160 g_partitions);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001161 pre->changed = 1;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001162#endif
1163 clear_partition(pre->ext_pointer);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001164 return;
1165 }
1166
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001167 read_pte(pe, extended_offset + get_start_sect(p));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001168
1169 if (!extended_offset)
1170 extended_offset = get_start_sect(p);
1171
1172 q = p = pt_offset(pe->sectorbuffer, 0);
1173 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001174 if (IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001175 if (pe->ext_pointer)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001176 printf("Warning: extra link "
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001177 "pointer in partition table"
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001178 " %u\n", g_partitions + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001179 else
1180 pe->ext_pointer = p;
1181 } else if (p->sys_ind) {
1182 if (pe->part_table)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001183 printf("Warning: ignoring extra "
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001184 "data in partition table"
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001185 " %u\n", g_partitions + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001186 else
1187 pe->part_table = p;
1188 }
1189 }
1190
1191 /* very strange code here... */
1192 if (!pe->part_table) {
1193 if (q != pe->ext_pointer)
1194 pe->part_table = q;
1195 else
1196 pe->part_table = q + 1;
1197 }
1198 if (!pe->ext_pointer) {
1199 if (q != pe->part_table)
1200 pe->ext_pointer = q;
1201 else
1202 pe->ext_pointer = q + 1;
1203 }
1204
1205 p = pe->ext_pointer;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001206 g_partitions++;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001207 }
1208
Denis Vlasenko834410a2006-11-29 12:00:28 +00001209#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001210 /* remove empty links */
1211 remove:
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001212 for (i = 4; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001213 struct pte *pe = &ptes[i];
1214
Denis Vlasenkobd852072007-03-19 14:43:38 +00001215 if (!get_nr_sects(pe->part_table)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001216 && (g_partitions > 5 || ptes[4].part_table->sys_ind)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001217 ) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001218 printf("Omitting empty partition (%u)\n", i+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001219 delete_partition(i);
1220 goto remove; /* numbering changed */
1221 }
1222 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001223#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001224}
1225
Denis Vlasenko834410a2006-11-29 12:00:28 +00001226#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001227static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001228create_doslabel(void)
1229{
Denis Vlasenkobd852072007-03-19 14:43:38 +00001230 printf(msg_building_new_label, "DOS disklabel");
Rob Landley5527b912006-02-25 03:46:10 +00001231
Denis Vlasenko4437d192008-04-17 00:12:10 +00001232 current_label_type = LABEL_DOS;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001233#if ENABLE_FEATURE_OSF_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001234 possibly_osf_label = 0;
1235#endif
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001236 g_partitions = 4;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001237
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001238 memset(&MBRbuffer[510 - 4*16], 0, 4*16);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001239 write_part_table_flag(MBRbuffer);
1240 extended_offset = 0;
1241 set_all_unchanged();
1242 set_changed(0);
Denis Vlasenko4437d192008-04-17 00:12:10 +00001243 get_boot(CREATE_EMPTY_DOS);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001244}
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001245#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001246
1247static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001248get_sectorsize(void)
1249{
Rob Landley736e5252006-02-25 03:36:00 +00001250 if (!user_set_sector_size) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001251 int arg;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001252 if (ioctl(dev_fd, BLKSSZGET, &arg) == 0)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001253 sector_size = arg;
1254 if (sector_size != DEFAULT_SECTOR_SIZE)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001255 printf("Note: sector size is %u "
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +00001256 "(not " DEFAULT_SECTOR_SIZE_STR ")\n",
1257 sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001258 }
1259}
1260
Rob Landley88621d72006-08-29 19:41:06 +00001261static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001262get_kernel_geometry(void)
1263{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001264 struct hd_geometry geometry;
1265
Denis Vlasenko4437d192008-04-17 00:12:10 +00001266 if (!ioctl(dev_fd, HDIO_GETGEO, &geometry)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001267 kern_heads = geometry.heads;
1268 kern_sectors = geometry.sectors;
1269 /* never use geometry.cylinders - it is truncated */
1270 }
1271}
1272
1273static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001274get_partition_table_geometry(void)
1275{
"Vladimir N. Oleynik"a972c872005-12-02 10:06:04 +00001276 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001277 struct partition *p;
1278 int i, h, s, hh, ss;
1279 int first = 1;
1280 int bad = 0;
1281
Eric Andersen3496fdc2006-01-30 23:09:20 +00001282 if (!(valid_part_table_flag((char*)bufp)))
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001283 return;
1284
1285 hh = ss = 0;
Rob Landleyb73451d2006-02-24 16:29:00 +00001286 for (i = 0; i < 4; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001287 p = pt_offset(bufp, i);
1288 if (p->sys_ind != 0) {
1289 h = p->end_head + 1;
1290 s = (p->end_sector & 077);
1291 if (first) {
1292 hh = h;
1293 ss = s;
1294 first = 0;
1295 } else if (hh != h || ss != s)
1296 bad = 1;
1297 }
1298 }
1299
1300 if (!first && !bad) {
1301 pt_heads = hh;
1302 pt_sectors = ss;
1303 }
1304}
1305
Rob Landleyb73451d2006-02-24 16:29:00 +00001306static void
1307get_geometry(void)
1308{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001309 int sec_fac;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001310
1311 get_sectorsize();
1312 sec_fac = sector_size / 512;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001313#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001314 guess_device_type();
1315#endif
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001316 g_heads = g_cylinders = g_sectors = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001317 kern_heads = kern_sectors = 0;
1318 pt_heads = pt_sectors = 0;
1319
1320 get_kernel_geometry();
1321 get_partition_table_geometry();
1322
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001323 g_heads = user_heads ? user_heads :
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001324 pt_heads ? pt_heads :
1325 kern_heads ? kern_heads : 255;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001326 g_sectors = user_sectors ? user_sectors :
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001327 pt_sectors ? pt_sectors :
1328 kern_sectors ? kern_sectors : 63;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001329 total_number_of_sectors = bb_BLKGETSIZE_sectors(dev_fd);
Eric Andersen040f4402003-07-30 08:40:37 +00001330
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001331 sector_offset = 1;
1332 if (dos_compatible_flag)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001333 sector_offset = g_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001334
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001335 g_cylinders = total_number_of_sectors / (g_heads * g_sectors * sec_fac);
1336 if (!g_cylinders)
1337 g_cylinders = user_cylinders;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001338}
1339
1340/*
Denis Vlasenko4437d192008-04-17 00:12:10 +00001341 * Opens disk_device and optionally reads MBR.
Kevin Cernekeeccb07042010-10-25 02:00:24 +02001342 * If what == OPEN_MAIN:
1343 * Open device, read MBR. Abort program on short read. Create empty
1344 * disklabel if the on-disk structure is invalid (WRITABLE mode).
1345 * If what == TRY_ONLY:
1346 * Open device, read MBR. Return an error if anything is out of place.
1347 * Do not create an empty disklabel. This is used for the "list"
1348 * operations: "fdisk -l /dev/sda" and "fdisk -l" (all devices).
1349 * If what == CREATE_EMPTY_*:
1350 * This means that get_boot() was called recursively from create_*label().
1351 * Do not re-open the device; just set up the ptes array and print
1352 * geometry warnings.
1353 *
Denis Vlasenko4437d192008-04-17 00:12:10 +00001354 * Returns:
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001355 * -1: no 0xaa55 flag present (possibly entire disk BSD)
1356 * 0: found or created label
1357 * 1: I/O error
1358 */
Denis Vlasenko85c24712008-03-17 09:04:04 +00001359#if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE
1360static int get_boot(enum action what)
1361#else
1362static int get_boot(void)
1363#define get_boot(what) get_boot()
1364#endif
Rob Landleyb73451d2006-02-24 16:29:00 +00001365{
Denis Vlasenko4437d192008-04-17 00:12:10 +00001366 int i, fd;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001367
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001368 g_partitions = 4;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001369 for (i = 0; i < 4; i++) {
1370 struct pte *pe = &ptes[i];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001371 pe->part_table = pt_offset(MBRbuffer, i);
1372 pe->ext_pointer = NULL;
Denys Vlasenkod958e902010-04-06 02:32:26 +02001373 pe->offset_from_dev_start = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001374 pe->sectorbuffer = MBRbuffer;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001375#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko4437d192008-04-17 00:12:10 +00001376 pe->changed = (what == CREATE_EMPTY_DOS);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001377#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001378 }
1379
Denis Vlasenko834410a2006-11-29 12:00:28 +00001380#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko4437d192008-04-17 00:12:10 +00001381// ALERT! highly idiotic design!
1382// We end up here when we call get_boot() recursively
1383// via get_boot() [table is bad] -> create_doslabel() -> get_boot(CREATE_EMPTY_DOS).
1384// or get_boot() [table is bad] -> create_sunlabel() -> get_boot(CREATE_EMPTY_SUN).
1385// (just factor out re-init of ptes[0,1,2,3] in a separate fn instead?)
1386// So skip opening device _again_...
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001387 if (what == CREATE_EMPTY_DOS IF_FEATURE_SUN_LABEL(|| what == CREATE_EMPTY_SUN))
Denis Vlasenko4437d192008-04-17 00:12:10 +00001388 goto created_table;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001389
Denis Vlasenko4437d192008-04-17 00:12:10 +00001390 fd = open(disk_device, (option_mask32 & OPT_l) ? O_RDONLY : O_RDWR);
1391
Denis Vlasenkobd852072007-03-19 14:43:38 +00001392 if (fd < 0) {
1393 fd = open(disk_device, O_RDONLY);
1394 if (fd < 0) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001395 if (what == TRY_ONLY)
Rob Landleyb73451d2006-02-24 16:29:00 +00001396 return 1;
1397 fdisk_fatal(unable_to_open);
Denis Vlasenko4437d192008-04-17 00:12:10 +00001398 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00001399 printf("'%s' is opened for read only\n", disk_device);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001400 }
Denis Vlasenkoc033d512008-04-17 01:52:28 +00001401 xmove_fd(fd, dev_fd);
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +00001402 if (512 != full_read(dev_fd, MBRbuffer, 512)) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001403 if (what == TRY_ONLY) {
Denis Vlasenkoc033d512008-04-17 01:52:28 +00001404 close_dev_fd();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001405 return 1;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001406 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001407 fdisk_fatal(unable_to_read);
1408 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001409#else
Denis Vlasenkobd852072007-03-19 14:43:38 +00001410 fd = open(disk_device, O_RDONLY);
1411 if (fd < 0)
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001412 return 1;
Denis Vlasenko6eaf0a92008-06-29 05:10:47 +00001413 if (512 != full_read(fd, MBRbuffer, 512)) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001414 close(fd);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001415 return 1;
Denis Vlasenko4437d192008-04-17 00:12:10 +00001416 }
1417 xmove_fd(fd, dev_fd);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001418#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001419
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001420 get_geometry();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001421 update_units();
1422
Denis Vlasenko834410a2006-11-29 12:00:28 +00001423#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001424 if (check_sun_label())
1425 return 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001426#endif
Denis Vlasenko834410a2006-11-29 12:00:28 +00001427#if ENABLE_FEATURE_SGI_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001428 if (check_sgi_label())
1429 return 0;
1430#endif
Denis Vlasenko834410a2006-11-29 12:00:28 +00001431#if ENABLE_FEATURE_AIX_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001432 if (check_aix_label())
1433 return 0;
1434#endif
Kevin Cernekeeccb07042010-10-25 02:00:24 +02001435#if ENABLE_FEATURE_GPT_LABEL
1436 if (check_gpt_label())
1437 return 0;
1438#endif
Denis Vlasenko834410a2006-11-29 12:00:28 +00001439#if ENABLE_FEATURE_OSF_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001440 if (check_osf_label()) {
1441 possibly_osf_label = 1;
1442 if (!valid_part_table_flag(MBRbuffer)) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001443 current_label_type = LABEL_OSF;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001444 return 0;
1445 }
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001446 puts("This disk has both DOS and BSD magic.\n"
1447 "Give the 'b' command to go to BSD mode.");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001448 }
1449#endif
1450
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001451#if !ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko4437d192008-04-17 00:12:10 +00001452 if (!valid_part_table_flag(MBRbuffer))
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001453 return -1;
1454#else
Denis Vlasenko4437d192008-04-17 00:12:10 +00001455 if (!valid_part_table_flag(MBRbuffer)) {
1456 if (what == OPEN_MAIN) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001457 puts("Device contains neither a valid DOS "
1458 "partition table, nor Sun, SGI, OSF or GPT "
1459 "disklabel");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001460#ifdef __sparc__
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001461 IF_FEATURE_SUN_LABEL(create_sunlabel();)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001462#else
1463 create_doslabel();
1464#endif
1465 return 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001466 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00001467 /* TRY_ONLY: */
1468 return -1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001469 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00001470 created_table:
1471#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001472
Denis Vlasenko4437d192008-04-17 00:12:10 +00001473
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001474 IF_FEATURE_FDISK_WRITABLE(warn_cylinders();)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001475 warn_geometry();
1476
1477 for (i = 0; i < 4; i++) {
Denis Vlasenko4437d192008-04-17 00:12:10 +00001478 if (IS_EXTENDED(ptes[i].part_table->sys_ind)) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001479 if (g_partitions != 4)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001480 printf("Ignoring extra extended "
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001481 "partition %u\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001482 else
1483 read_extended(i);
1484 }
1485 }
1486
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001487 for (i = 3; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001488 struct pte *pe = &ptes[i];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001489 if (!valid_part_table_flag(pe->sectorbuffer)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001490 printf("Warning: invalid flag 0x%02x,0x%02x of partition "
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001491 "table %u will be corrected by w(rite)\n",
Denis Vlasenko834410a2006-11-29 12:00:28 +00001492 pe->sectorbuffer[510],
1493 pe->sectorbuffer[511],
1494 i + 1);
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00001495 IF_FEATURE_FDISK_WRITABLE(pe->changed = 1;)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001496 }
1497 }
1498
1499 return 0;
1500}
1501
Denis Vlasenko834410a2006-11-29 12:00:28 +00001502#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001503/*
1504 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
1505 * If the user hits Enter, DFLT is returned.
1506 * Answers like +10 are interpreted as offsets from BASE.
1507 *
1508 * There is no default if DFLT is not between LOW and HIGH.
1509 */
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001510static sector_t
1511read_int(sector_t low, sector_t dflt, sector_t high, sector_t base, const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001512{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001513 sector_t value;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001514 int default_ok = 1;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001515 const char *fmt = "%s (%u-%u, default %u): ";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001516
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001517 if (dflt < low || dflt > high) {
1518 fmt = "%s (%u-%u): ";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001519 default_ok = 0;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001520 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001521
1522 while (1) {
1523 int use_default = default_ok;
1524
1525 /* ask question and read answer */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001526 do {
1527 printf(fmt, mesg, low, high, dflt);
1528 read_maybe_empty("");
1529 } while (*line_ptr != '\n' && !isdigit(*line_ptr)
1530 && *line_ptr != '-' && *line_ptr != '+');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001531
Eric Andersen84bdea82004-05-19 10:49:17 +00001532 if (*line_ptr == '+' || *line_ptr == '-') {
Rob Landleyb73451d2006-02-24 16:29:00 +00001533 int minus = (*line_ptr == '-');
1534 int absolute = 0;
Eric Andersenc48d49a2003-07-03 10:02:32 +00001535
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001536 value = atoi(line_ptr + 1);
Eric Andersenc48d49a2003-07-03 10:02:32 +00001537
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001538 /* (1) if 2nd char is digit, use_default = 0.
1539 * (2) move line_ptr to first non-digit. */
Rob Landleyb73451d2006-02-24 16:29:00 +00001540 while (isdigit(*++line_ptr))
1541 use_default = 0;
Eric Andersen84bdea82004-05-19 10:49:17 +00001542
Rob Landleyb73451d2006-02-24 16:29:00 +00001543 switch (*line_ptr) {
1544 case 'c':
1545 case 'C':
1546 if (!display_in_cyl_units)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001547 value *= g_heads * g_sectors;
Rob Landleyb73451d2006-02-24 16:29:00 +00001548 break;
1549 case 'K':
1550 absolute = 1024;
1551 break;
1552 case 'k':
1553 absolute = 1000;
1554 break;
1555 case 'm':
1556 case 'M':
1557 absolute = 1000000;
1558 break;
1559 case 'g':
1560 case 'G':
1561 absolute = 1000000000;
1562 break;
1563 default:
1564 break;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001565 }
Rob Landleyb73451d2006-02-24 16:29:00 +00001566 if (absolute) {
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001567 ullong bytes;
Rob Landleyb73451d2006-02-24 16:29:00 +00001568 unsigned long unit;
1569
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001570 bytes = (ullong) value * absolute;
Rob Landleyb73451d2006-02-24 16:29:00 +00001571 unit = sector_size * units_per_sector;
1572 bytes += unit/2; /* round */
1573 bytes /= unit;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001574 value = bytes;
Rob Landleyb73451d2006-02-24 16:29:00 +00001575 }
1576 if (minus)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001577 value = -value;
1578 value += base;
Eric Andersen84bdea82004-05-19 10:49:17 +00001579 } else {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001580 value = atoi(line_ptr);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001581 while (isdigit(*line_ptr)) {
1582 line_ptr++;
1583 use_default = 0;
1584 }
1585 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001586 if (use_default) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001587 value = dflt;
1588 printf("Using default value %u\n", value);
Denis Vlasenkobd852072007-03-19 14:43:38 +00001589 }
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001590 if (value >= low && value <= high)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001591 break;
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001592 puts("Value is out of range");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001593 }
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001594 return value;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001595}
1596
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001597static unsigned
1598get_partition(int warn, unsigned max)
Rob Landleyb73451d2006-02-24 16:29:00 +00001599{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001600 struct pte *pe;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001601 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001602
Denis Vlasenkobd852072007-03-19 14:43:38 +00001603 i = read_int(1, 0, max, 0, "Partition number") - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001604 pe = &ptes[i];
1605
1606 if (warn) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001607 if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind)
1608 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
1609 || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
1610 ) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001611 printf("Warning: partition %u has empty type\n", i+1);
Rob Landley5527b912006-02-25 03:46:10 +00001612 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001613 }
1614 return i;
1615}
1616
1617static int
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001618get_existing_partition(int warn, unsigned max)
Rob Landleyb73451d2006-02-24 16:29:00 +00001619{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001620 int pno = -1;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001621 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001622
1623 for (i = 0; i < max; i++) {
1624 struct pte *pe = &ptes[i];
1625 struct partition *p = pe->part_table;
1626
1627 if (p && !is_cleared_partition(p)) {
1628 if (pno >= 0)
1629 goto not_unique;
1630 pno = i;
1631 }
1632 }
1633 if (pno >= 0) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001634 printf("Selected partition %u\n", pno+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001635 return pno;
1636 }
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001637 puts("No partition is defined yet!");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001638 return -1;
1639
1640 not_unique:
1641 return get_partition(warn, max);
1642}
1643
1644static int
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001645get_nonexisting_partition(int warn, unsigned max)
Rob Landleyb73451d2006-02-24 16:29:00 +00001646{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001647 int pno = -1;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001648 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001649
1650 for (i = 0; i < max; i++) {
1651 struct pte *pe = &ptes[i];
1652 struct partition *p = pe->part_table;
1653
1654 if (p && is_cleared_partition(p)) {
1655 if (pno >= 0)
1656 goto not_unique;
1657 pno = i;
1658 }
1659 }
1660 if (pno >= 0) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001661 printf("Selected partition %u\n", pno+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001662 return pno;
1663 }
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001664 puts("All primary partitions have been defined already!");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001665 return -1;
1666
1667 not_unique:
1668 return get_partition(warn, max);
1669}
1670
1671
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001672static void
1673change_units(void)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001674{
1675 display_in_cyl_units = !display_in_cyl_units;
1676 update_units();
Denis Vlasenkobd852072007-03-19 14:43:38 +00001677 printf("Changing display/entry units to %s\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001678 str_units(PLURAL));
1679}
1680
1681static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001682toggle_active(int i)
1683{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001684 struct pte *pe = &ptes[i];
1685 struct partition *p = pe->part_table;
1686
Rob Landleyb73451d2006-02-24 16:29:00 +00001687 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001688 printf("WARNING: Partition %u is an extended partition\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001689 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1690 pe->changed = 1;
1691}
1692
1693static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001694toggle_dos_compatibility_flag(void)
1695{
Denis Vlasenkocdf62772008-03-17 08:42:43 +00001696 dos_compatible_flag = 1 - dos_compatible_flag;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001697 if (dos_compatible_flag) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001698 sector_offset = g_sectors;
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001699 printf("DOS Compatibility flag is %sset\n", "");
Denis Vlasenkobd852072007-03-19 14:43:38 +00001700 } else {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001701 sector_offset = 1;
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001702 printf("DOS Compatibility flag is %sset\n", "not ");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001703 }
1704}
1705
1706static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001707delete_partition(int i)
1708{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001709 struct pte *pe = &ptes[i];
1710 struct partition *p = pe->part_table;
1711 struct partition *q = pe->ext_pointer;
1712
1713/* Note that for the fifth partition (i == 4) we don't actually
1714 * decrement partitions.
1715 */
1716
1717 if (warn_geometry())
1718 return; /* C/H/S not set */
1719 pe->changed = 1;
1720
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001721 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001722 sun_delete_partition(i);
1723 return;
1724 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001725 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001726 sgi_delete_partition(i);
1727 return;
1728 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001729
1730 if (i < 4) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001731 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001732 g_partitions = 4;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001733 ptes[ext_index].ext_pointer = NULL;
1734 extended_offset = 0;
1735 }
1736 clear_partition(p);
1737 return;
1738 }
1739
1740 if (!q->sys_ind && i > 4) {
1741 /* the last one in the chain - just delete */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001742 --g_partitions;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001743 --i;
1744 clear_partition(ptes[i].ext_pointer);
1745 ptes[i].changed = 1;
1746 } else {
1747 /* not the last one - further ones will be moved down */
1748 if (i > 4) {
1749 /* delete this link in the chain */
1750 p = ptes[i-1].ext_pointer;
1751 *p = *q;
1752 set_start_sect(p, get_start_sect(q));
1753 set_nr_sects(p, get_nr_sects(q));
1754 ptes[i-1].changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001755 } else if (g_partitions > 5) { /* 5 will be moved to 4 */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001756 /* the first logical in a longer chain */
1757 pe = &ptes[5];
1758
1759 if (pe->part_table) /* prevent SEGFAULT */
1760 set_start_sect(pe->part_table,
Denys Vlasenkod958e902010-04-06 02:32:26 +02001761 get_partition_start_from_dev_start(pe) -
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001762 extended_offset);
Denys Vlasenkod958e902010-04-06 02:32:26 +02001763 pe->offset_from_dev_start = extended_offset;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001764 pe->changed = 1;
1765 }
1766
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001767 if (g_partitions > 5) {
1768 g_partitions--;
1769 while (i < g_partitions) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001770 ptes[i] = ptes[i+1];
1771 i++;
1772 }
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001773 } else {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001774 /* the only logical: clear only */
1775 clear_partition(ptes[i].part_table);
Denys Vlasenko5ea1de22010-04-06 02:31:43 +02001776 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001777 }
1778}
1779
1780static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001781change_sysid(void)
1782{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001783 int i, sys, origsys;
1784 struct partition *p;
1785
Eric Andersen040f4402003-07-30 08:40:37 +00001786 /* If sgi_label then don't use get_existing_partition,
1787 let the user select a partition, since get_existing_partition()
1788 only works for Linux like partition tables. */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001789 if (!LABEL_IS_SGI) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001790 i = get_existing_partition(0, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00001791 } else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001792 i = get_partition(0, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00001793 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001794 if (i == -1)
1795 return;
1796 p = ptes[i].part_table;
1797 origsys = sys = get_sysid(i);
1798
1799 /* if changing types T to 0 is allowed, then
1800 the reverse change must be allowed, too */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001801 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001802 printf("Partition %u does not exist yet!\n", i + 1);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001803 return;
1804 }
1805 while (1) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001806 sys = read_hex(get_sys_types());
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001807
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001808 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001809 puts("Type 0 means free space to many systems\n"
1810 "(but not to Linux). Having partitions of\n"
1811 "type 0 is probably unwise.");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001812 /* break; */
1813 }
1814
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001815 if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001816 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001817 puts("You cannot change a partition into"
1818 " an extended one or vice versa");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001819 break;
1820 }
1821 }
1822
1823 if (sys < 256) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001824#if ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001825 if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001826 puts("Consider leaving partition 3 "
1827 "as Whole disk (5),\n"
1828 "as SunOS/Solaris expects it and "
1829 "even Linux likes it\n");
Denis Vlasenkobd852072007-03-19 14:43:38 +00001830#endif
1831#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001832 if (LABEL_IS_SGI &&
Rob Landley5527b912006-02-25 03:46:10 +00001833 (
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001834 (i == 10 && sys != SGI_ENTIRE_DISK) ||
Rob Landley5527b912006-02-25 03:46:10 +00001835 (i == 8 && sys != 0)
1836 )
Denis Vlasenkobd852072007-03-19 14:43:38 +00001837 ) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001838 puts("Consider leaving partition 9 "
1839 "as volume header (0),\nand "
1840 "partition 11 as entire volume (6)"
1841 "as IRIX expects it\n");
Rob Landley5527b912006-02-25 03:46:10 +00001842 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001843#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001844 if (sys == origsys)
1845 break;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001846 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001847 sun_change_sysid(i, sys);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001848 } else if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001849 sgi_change_sysid(i, sys);
1850 } else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001851 p->sys_ind = sys;
Rob Landley5527b912006-02-25 03:46:10 +00001852
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001853 printf("Changed system type of partition %u "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001854 "to %x (%s)\n", i + 1, sys,
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001855 partition_type(sys));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001856 ptes[i].changed = 1;
Denis Vlasenkoa5549c92008-01-24 22:49:15 +00001857 //if (is_dos_partition(origsys) || is_dos_partition(sys))
1858 // dos_changed = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001859 break;
1860 }
1861 }
1862}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001863#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001864
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001865
Denis Vlasenko28703012006-12-19 20:32:02 +00001866/* check_consistency() and linear2chs() added Sat Mar 6 12:28:16 1993,
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001867 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1868 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1869 * Lubkin Oct. 1991). */
1870
Rob Landleyb73451d2006-02-24 16:29:00 +00001871static void
Denis Vlasenko28703012006-12-19 20:32:02 +00001872linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
Rob Landleyb73451d2006-02-24 16:29:00 +00001873{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001874 int spc = g_heads * g_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001875
1876 *c = ls / spc;
1877 ls = ls % spc;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001878 *h = ls / g_sectors;
1879 *s = ls % g_sectors + 1; /* sectors count from 1 */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001880}
1881
Rob Landleyb73451d2006-02-24 16:29:00 +00001882static void
1883check_consistency(const struct partition *p, int partition)
1884{
Denis Vlasenko834410a2006-11-29 12:00:28 +00001885 unsigned pbc, pbh, pbs; /* physical beginning c, h, s */
1886 unsigned pec, peh, pes; /* physical ending c, h, s */
1887 unsigned lbc, lbh, lbs; /* logical beginning c, h, s */
1888 unsigned lec, leh, les; /* logical ending c, h, s */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001889
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001890 if (!g_heads || !g_sectors || (partition >= 4))
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001891 return; /* do not check extended partitions */
1892
1893/* physical beginning c, h, s */
Denys Vlasenko607f2b42016-08-23 16:13:33 +02001894 pbc = cylinder(p->sector, p->cyl);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001895 pbh = p->head;
Denys Vlasenko607f2b42016-08-23 16:13:33 +02001896 pbs = sector(p->sector);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001897
1898/* physical ending c, h, s */
Denys Vlasenko607f2b42016-08-23 16:13:33 +02001899 pec = cylinder(p->end_sector, p->end_cyl);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001900 peh = p->end_head;
Denys Vlasenko607f2b42016-08-23 16:13:33 +02001901 pes = sector(p->end_sector);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001902
1903/* compute logical beginning (c, h, s) */
Denis Vlasenko28703012006-12-19 20:32:02 +00001904 linear2chs(get_start_sect(p), &lbc, &lbh, &lbs);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001905
1906/* compute logical ending (c, h, s) */
Denis Vlasenko28703012006-12-19 20:32:02 +00001907 linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001908
1909/* Same physical / logical beginning? */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001910 if (g_cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001911 printf("Partition %u has different physical/logical "
Denys Vlasenko607f2b42016-08-23 16:13:33 +02001912 "start (non-Linux?):\n", partition + 1);
1913 printf(" phys=(%u,%u,%u) ", pbc, pbh, pbs);
1914 printf("logical=(%u,%u,%u)\n", lbc, lbh, lbs);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001915 }
1916
1917/* Same physical / logical ending? */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001918 if (g_cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001919 printf("Partition %u has different physical/logical "
Denys Vlasenko607f2b42016-08-23 16:13:33 +02001920 "end:\n", partition + 1);
1921 printf(" phys=(%u,%u,%u) ", pec, peh, pes);
1922 printf("logical=(%u,%u,%u)\n", lec, leh, les);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001923 }
1924
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001925/* Ending on cylinder boundary? */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001926 if (peh != (g_heads - 1) || pes != g_sectors) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001927 printf("Partition %u does not end on cylinder boundary\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001928 partition + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001929 }
1930}
1931
1932static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001933list_disk_geometry(void)
1934{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001935 ullong bytes = ((ullong)total_number_of_sectors << 9);
Denys Vlasenko29483ff2016-08-23 17:18:45 +02001936 ullong xbytes = bytes / (1024*1024);
1937 char x = 'M';
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001938
Denys Vlasenko29483ff2016-08-23 17:18:45 +02001939 if (xbytes >= 10000) {
1940 xbytes += 512; /* fdisk util-linux 2.28 does this */
1941 xbytes /= 1024;
1942 x = 'G';
1943 }
1944 printf("Disk %s: %llu %cB, %llu bytes, %"SECT_FMT"u sectors\n"
1945 "%u cylinders, %u heads, %u sectors/track\n"
1946 "Units: %s of %u * %u = %u bytes\n\n",
1947 disk_device, xbytes, x,
1948 bytes, total_number_of_sectors,
1949 g_cylinders, g_heads, g_sectors,
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001950 str_units(PLURAL),
Denys Vlasenko29483ff2016-08-23 17:18:45 +02001951 units_per_sector, sector_size, units_per_sector * sector_size
1952 );
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001953}
1954
1955/*
1956 * Check whether partition entries are ordered by their starting positions.
1957 * Return 0 if OK. Return i if partition i should have been earlier.
1958 * Two separate checks: primary and logical partitions.
1959 */
1960static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001961wrong_p_order(int *prev)
1962{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001963 const struct pte *pe;
1964 const struct partition *p;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02001965 sector_t last_p_start_pos = 0, p_start_pos;
1966 unsigned i, last_i = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001967
Denis Vlasenkof77f3692007-12-16 17:22:33 +00001968 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001969 if (i == 4) {
1970 last_i = 4;
1971 last_p_start_pos = 0;
1972 }
1973 pe = &ptes[i];
Denis Vlasenko6bef3d12007-11-06 03:05:54 +00001974 p = pe->part_table;
1975 if (p->sys_ind) {
Denys Vlasenkod958e902010-04-06 02:32:26 +02001976 p_start_pos = get_partition_start_from_dev_start(pe);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001977
1978 if (last_p_start_pos > p_start_pos) {
1979 if (prev)
1980 *prev = last_i;
1981 return i;
1982 }
1983
1984 last_p_start_pos = p_start_pos;
1985 last_i = i;
1986 }
1987 }
1988 return 0;
1989}
1990
Denis Vlasenko834410a2006-11-29 12:00:28 +00001991#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001992/*
1993 * Fix the chain of logicals.
1994 * extended_offset is unchanged, the set of sectors used is unchanged
1995 * The chain is sorted so that sectors increase, and so that
1996 * starting sectors increase.
1997 *
1998 * After this it may still be that cfdisk doesnt like the table.
1999 * (This is because cfdisk considers expanded parts, from link to
2000 * end of partition, and these may still overlap.)
2001 * Now
2002 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
2003 * may help.
2004 */
2005static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002006fix_chain_of_logicals(void)
2007{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002008 int j, oj, ojj, sj, sjj;
2009 struct partition *pj,*pjj,tmp;
2010
2011 /* Stage 1: sort sectors but leave sector of part 4 */
2012 /* (Its sector is the global extended_offset.) */
2013 stage1:
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002014 for (j = 5; j < g_partitions - 1; j++) {
Denys Vlasenkod958e902010-04-06 02:32:26 +02002015 oj = ptes[j].offset_from_dev_start;
2016 ojj = ptes[j+1].offset_from_dev_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002017 if (oj > ojj) {
Denys Vlasenkod958e902010-04-06 02:32:26 +02002018 ptes[j].offset_from_dev_start = ojj;
2019 ptes[j+1].offset_from_dev_start = oj;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002020 pj = ptes[j].part_table;
2021 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
2022 pjj = ptes[j+1].part_table;
2023 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
2024 set_start_sect(ptes[j-1].ext_pointer,
Rob Landleyb73451d2006-02-24 16:29:00 +00002025 ojj-extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002026 set_start_sect(ptes[j].ext_pointer,
Rob Landleyb73451d2006-02-24 16:29:00 +00002027 oj-extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002028 goto stage1;
2029 }
2030 }
2031
2032 /* Stage 2: sort starting sectors */
2033 stage2:
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002034 for (j = 4; j < g_partitions - 1; j++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002035 pj = ptes[j].part_table;
2036 pjj = ptes[j+1].part_table;
2037 sj = get_start_sect(pj);
2038 sjj = get_start_sect(pjj);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002039 oj = ptes[j].offset_from_dev_start;
2040 ojj = ptes[j+1].offset_from_dev_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002041 if (oj+sj > ojj+sjj) {
2042 tmp = *pj;
2043 *pj = *pjj;
2044 *pjj = tmp;
2045 set_start_sect(pj, ojj+sjj-oj);
2046 set_start_sect(pjj, oj+sj-ojj);
2047 goto stage2;
2048 }
2049 }
2050
2051 /* Probably something was changed */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002052 for (j = 4; j < g_partitions; j++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002053 ptes[j].changed = 1;
2054}
2055
2056
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002057static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002058fix_partition_table_order(void)
2059{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002060 struct pte *pei, *pek;
2061 int i,k;
2062
2063 if (!wrong_p_order(NULL)) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002064 puts("Ordering is already correct\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002065 return;
2066 }
2067
2068 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
2069 /* partition i should have come earlier, move it */
2070 /* We have to move data in the MBR */
2071 struct partition *pi, *pk, *pe, pbuf;
2072 pei = &ptes[i];
2073 pek = &ptes[k];
2074
2075 pe = pei->ext_pointer;
2076 pei->ext_pointer = pek->ext_pointer;
2077 pek->ext_pointer = pe;
2078
2079 pi = pei->part_table;
2080 pk = pek->part_table;
2081
2082 memmove(&pbuf, pi, sizeof(struct partition));
2083 memmove(pi, pk, sizeof(struct partition));
2084 memmove(pk, &pbuf, sizeof(struct partition));
2085
2086 pei->changed = pek->changed = 1;
2087 }
2088
2089 if (i)
2090 fix_chain_of_logicals();
2091
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002092 puts("Done");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002093}
2094#endif
2095
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002096static const char *
2097chs_string11(unsigned cyl, unsigned head, unsigned sect)
2098{
2099 char *buf = auto_string(xzalloc(sizeof(int)*3 * 3));
2100 sprintf(buf, "%u,%u,%u", cylinder(sect,cyl), head, sector(sect));
2101 return buf;
2102}
2103
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002104static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002105list_table(int xtra)
2106{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002107 int i, w;
2108
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002109 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002110 sun_list_table(xtra);
2111 return;
2112 }
Kevin Cernekeeccb07042010-10-25 02:00:24 +02002113 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002114 sgi_list_table(xtra);
2115 return;
2116 }
Kevin Cernekeeccb07042010-10-25 02:00:24 +02002117 if (LABEL_IS_GPT) {
2118 gpt_list_table(xtra);
2119 return;
2120 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002121
2122 list_disk_geometry();
2123
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002124 if (LABEL_IS_OSF) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002125 xbsd_print_disklabel(xtra);
2126 return;
2127 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002128
2129 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002130 * but if the device name ends in a digit, say /dev/foo1,
2131 * then the partition is called /dev/foo1p3.
2132 */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002133 w = strlen(disk_device);
2134 if (w && isdigit(disk_device[w-1]))
2135 w++;
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002136 if (w < 7)
2137 w = 7;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002138
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002139 printf("%-*s Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type\n",
2140 w-1, "Device");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002141
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002142 for (i = 0; i < g_partitions; i++) {
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002143 const struct partition *p;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002144 const struct pte *pe = &ptes[i];
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002145 char boot4[4];
2146 char numstr6[6];
2147 sector_t start_sect;
2148 sector_t end_sect;
2149 sector_t nr_sects;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002150
2151 p = pe->part_table;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002152 if (!p || is_cleared_partition(p))
2153 continue;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002154
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002155 sprintf(boot4, "%02x", p->boot_ind);
2156 if ((p->boot_ind & 0x7f) == 0) {
2157 /* 0x80 shown as '*', 0x00 is ' ' */
2158 boot4[0] = p->boot_ind ? '*' : ' ';
2159 boot4[1] = ' ';
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002160 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002161
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002162 start_sect = get_partition_start_from_dev_start(pe);
2163 end_sect = start_sect;
2164 nr_sects = get_nr_sects(p);
2165 if (nr_sects != 0)
2166 end_sect += nr_sects - 1;
2167
2168 smart_ulltoa5((ullong)nr_sects * sector_size,
2169 numstr6, " KMGTPEZY")[0] = '\0';
2170
2171#define SFMT SECT_FMT
2172 // Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type
2173 printf("%s%s %-11s"/**/" %-11s"/**/" %10"SFMT"u %10"SFMT"u %10"SFMT"u %s %2x %s\n",
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002174 partname(disk_device, i+1, w+2),
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002175 boot4,
2176 chs_string11(p->cyl, p->head, p->sector),
2177 chs_string11(p->end_cyl, p->end_head, p->end_sector),
2178 start_sect,
2179 end_sect,
2180 nr_sects,
2181 numstr6,
2182 p->sys_ind,
2183 partition_type(p->sys_ind)
2184 );
2185#undef SFMT
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002186 check_consistency(p, i);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002187 }
2188
2189 /* Is partition table in disk order? It need not be, but... */
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002190 /* partition table entries are not checked for correct order
2191 * if this is a sgi, sun or aix labeled disk... */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002192 if (LABEL_IS_DOS && wrong_p_order(NULL)) {
Rob Landley5527b912006-02-25 03:46:10 +00002193 /* FIXME */
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002194 puts("\nPartition table entries are not in disk order");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002195 }
2196}
2197
Denis Vlasenko834410a2006-11-29 12:00:28 +00002198#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002199static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002200x_list_table(int extend)
2201{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002202 const struct pte *pe;
2203 const struct partition *p;
2204 int i;
2205
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002206 printf("\nDisk %s: %u heads, %u sectors, %u cylinders\n\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002207 disk_device, g_heads, g_sectors, g_cylinders);
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002208 puts("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID");
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002209 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002210 pe = &ptes[i];
2211 p = (extend ? pe->ext_pointer : pe->part_table);
2212 if (p != NULL) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002213 printf("%2u %02x%4u%4u%5u%4u%4u%5u%11"SECT_FMT"u%11"SECT_FMT"u %02x\n",
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002214 i + 1, p->boot_ind,
2215 p->head,
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002216 sector(p->sector),
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002217 cylinder(p->sector, p->cyl),
2218 p->end_head,
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002219 sector(p->end_sector),
2220 cylinder(p->end_sector, p->end_cyl),
Denys Vlasenko607f2b42016-08-23 16:13:33 +02002221 get_start_sect(p),
2222 get_nr_sects(p),
2223 p->sys_ind
2224 );
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002225 if (p->sys_ind)
2226 check_consistency(p, i);
2227 }
2228 }
2229}
2230#endif
2231
Denis Vlasenko834410a2006-11-29 12:00:28 +00002232#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002233static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002234fill_bounds(sector_t *first, sector_t *last)
Rob Landleyb73451d2006-02-24 16:29:00 +00002235{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002236 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002237 const struct pte *pe = &ptes[0];
2238 const struct partition *p;
2239
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002240 for (i = 0; i < g_partitions; pe++,i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002241 p = pe->part_table;
Rob Landleyb73451d2006-02-24 16:29:00 +00002242 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002243 first[i] = 0xffffffff;
2244 last[i] = 0;
2245 } else {
Denys Vlasenkod958e902010-04-06 02:32:26 +02002246 first[i] = get_partition_start_from_dev_start(pe);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002247 last[i] = first[i] + get_nr_sects(p) - 1;
2248 }
2249 }
2250}
2251
2252static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002253check(int n, unsigned h, unsigned s, unsigned c, sector_t start)
Rob Landleyb73451d2006-02-24 16:29:00 +00002254{
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002255 sector_t total, real_s, real_c;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002256
2257 real_s = sector(s) - 1;
2258 real_c = cylinder(s, c);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002259 total = (real_c * g_sectors + real_s) * g_heads + h;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002260 if (!total)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002261 printf("Partition %u contains sector 0\n", n);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002262 if (h >= g_heads)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002263 printf("Partition %u: head %u greater than maximum %u\n",
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002264 n, h + 1, g_heads);
2265 if (real_s >= g_sectors)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002266 printf("Partition %u: sector %u greater than "
2267 "maximum %u\n", n, s, g_sectors);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002268 if (real_c >= g_cylinders)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002269 printf("Partition %u: cylinder %"SECT_FMT"u greater than "
2270 "maximum %u\n", n, real_c + 1, g_cylinders);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002271 if (g_cylinders <= 1024 && start != total)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002272 printf("Partition %u: previous sectors %"SECT_FMT"u disagrees with "
2273 "total %"SECT_FMT"u\n", n, start, total);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002274}
2275
2276static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002277verify(void)
2278{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002279 int i, j;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002280 sector_t total = 1;
Denys Vlasenko29483ff2016-08-23 17:18:45 +02002281 sector_t chs_size;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002282 sector_t first[g_partitions], last[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002283 struct partition *p;
2284
2285 if (warn_geometry())
2286 return;
2287
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002288 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002289 verify_sun();
2290 return;
2291 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002292 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002293 verify_sgi(1);
2294 return;
2295 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002296
2297 fill_bounds(first, last);
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002298 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002299 struct pte *pe = &ptes[i];
2300
2301 p = pe->part_table;
Rob Landleyb73451d2006-02-24 16:29:00 +00002302 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002303 check_consistency(p, i);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002304 if (get_partition_start_from_dev_start(pe) < first[i])
Denis Vlasenkobd852072007-03-19 14:43:38 +00002305 printf("Warning: bad start-of-data in "
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002306 "partition %u\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002307 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
2308 last[i]);
2309 total += last[i] + 1 - first[i];
Denis Vlasenkobd852072007-03-19 14:43:38 +00002310 for (j = 0; j < i; j++) {
2311 if ((first[i] >= first[j] && first[i] <= last[j])
2312 || ((last[i] <= last[j] && last[i] >= first[j]))) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002313 printf("Warning: partition %u overlaps "
2314 "partition %u\n", j + 1, i + 1);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002315 total += first[i] >= first[j] ?
2316 first[i] : first[j];
2317 total -= last[i] <= last[j] ?
2318 last[i] : last[j];
2319 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002320 }
2321 }
2322 }
2323
2324 if (extended_offset) {
2325 struct pte *pex = &ptes[ext_index];
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002326 sector_t e_last = get_start_sect(pex->part_table) +
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002327 get_nr_sects(pex->part_table) - 1;
2328
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002329 for (i = 4; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002330 total++;
2331 p = ptes[i].part_table;
2332 if (!p->sys_ind) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002333 if (i != 4 || i + 1 < g_partitions)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002334 printf("Warning: partition %u "
Denis Vlasenkobd852072007-03-19 14:43:38 +00002335 "is empty\n", i + 1);
2336 } else if (first[i] < extended_offset || last[i] > e_last) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002337 printf("Logical partition %u not entirely in "
2338 "partition %u\n", i + 1, ext_index + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002339 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002340 }
2341 }
2342
Denys Vlasenko29483ff2016-08-23 17:18:45 +02002343 chs_size = (sector_t)g_heads * g_sectors * g_cylinders;
2344 if (total > chs_size)
2345 printf("Total allocated sectors %u"
2346 " greater than CHS size %"SECT_FMT"u\n",
2347 total, chs_size
2348 );
Denis Vlasenkobd852072007-03-19 14:43:38 +00002349 else {
Denys Vlasenko29483ff2016-08-23 17:18:45 +02002350 total = chs_size - total;
Denis Vlasenkobd852072007-03-19 14:43:38 +00002351 if (total != 0)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002352 printf("%"SECT_FMT"u unallocated sectors\n", total);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002353 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002354}
2355
2356static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002357add_partition(int n, int sys)
2358{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002359 char mesg[256]; /* 48 does not suffice in Japanese */
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002360 int i, num_read = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002361 struct partition *p = ptes[n].part_table;
2362 struct partition *q = ptes[ext_index].part_table;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002363 sector_t limit, temp;
2364 sector_t start, stop = 0;
2365 sector_t first[g_partitions], last[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002366
2367 if (p && p->sys_ind) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002368 printf(msg_part_already_defined, n + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002369 return;
2370 }
2371 fill_bounds(first, last);
2372 if (n < 4) {
2373 start = sector_offset;
Eric Andersen040f4402003-07-30 08:40:37 +00002374 if (display_in_cyl_units || !total_number_of_sectors)
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002375 limit = (sector_t) g_heads * g_sectors * g_cylinders - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002376 else
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002377 limit = total_number_of_sectors - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002378 if (extended_offset) {
2379 first[ext_index] = extended_offset;
2380 last[ext_index] = get_start_sect(q) +
2381 get_nr_sects(q) - 1;
2382 }
2383 } else {
2384 start = extended_offset + sector_offset;
2385 limit = get_start_sect(q) + get_nr_sects(q) - 1;
2386 }
2387 if (display_in_cyl_units)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002388 for (i = 0; i < g_partitions; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002389 first[i] = (cround(first[i]) - 1) * units_per_sector;
2390
Denis Vlasenkobd852072007-03-19 14:43:38 +00002391 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002392 do {
2393 temp = start;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002394 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002395 int lastplusoff;
2396
Denys Vlasenkod958e902010-04-06 02:32:26 +02002397 if (start == ptes[i].offset_from_dev_start)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002398 start += sector_offset;
Rob Landleyb73451d2006-02-24 16:29:00 +00002399 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002400 if (start >= first[i] && start <= lastplusoff)
2401 start = lastplusoff + 1;
2402 }
2403 if (start > limit)
2404 break;
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002405 if (start >= temp+units_per_sector && num_read) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002406 printf("Sector %"SECT_FMT"u is already allocated\n", temp);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002407 temp = start;
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002408 num_read = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002409 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002410 if (!num_read && start == temp) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002411 sector_t saved_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002412
2413 saved_start = start;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002414 start = read_int(cround(saved_start), cround(saved_start), cround(limit), 0, mesg);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002415 if (display_in_cyl_units) {
2416 start = (start - 1) * units_per_sector;
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002417 if (start < saved_start)
2418 start = saved_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002419 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002420 num_read = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002421 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002422 } while (start != temp || !num_read);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002423 if (n > 4) { /* NOT for fifth partition */
2424 struct pte *pe = &ptes[n];
2425
Denys Vlasenkod958e902010-04-06 02:32:26 +02002426 pe->offset_from_dev_start = start - sector_offset;
2427 if (pe->offset_from_dev_start == extended_offset) { /* must be corrected */
2428 pe->offset_from_dev_start++;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002429 if (sector_offset == 1)
2430 start++;
2431 }
2432 }
2433
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002434 for (i = 0; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002435 struct pte *pe = &ptes[i];
2436
Denys Vlasenkod958e902010-04-06 02:32:26 +02002437 if (start < pe->offset_from_dev_start && limit >= pe->offset_from_dev_start)
2438 limit = pe->offset_from_dev_start - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002439 if (start < first[i] && limit >= first[i])
2440 limit = first[i] - 1;
2441 }
2442 if (start > limit) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002443 puts("No free sectors available");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002444 if (n > 4)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002445 g_partitions--;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002446 return;
2447 }
2448 if (cround(start) == cround(limit)) {
2449 stop = limit;
2450 } else {
2451 snprintf(mesg, sizeof(mesg),
Denis Vlasenkobd852072007-03-19 14:43:38 +00002452 "Last %s or +size or +sizeM or +sizeK",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002453 str_units(SINGULAR));
Denys Vlasenkod958e902010-04-06 02:32:26 +02002454 stop = read_int(cround(start), cround(limit), cround(limit), cround(start), mesg);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002455 if (display_in_cyl_units) {
2456 stop = stop * units_per_sector - 1;
2457 if (stop >limit)
2458 stop = limit;
2459 }
2460 }
2461
2462 set_partition(n, 0, start, stop, sys);
2463 if (n > 4)
Denys Vlasenkod958e902010-04-06 02:32:26 +02002464 set_partition(n - 1, 1, ptes[n].offset_from_dev_start, stop, EXTENDED);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002465
Rob Landleyb73451d2006-02-24 16:29:00 +00002466 if (IS_EXTENDED(sys)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002467 struct pte *pe4 = &ptes[4];
2468 struct pte *pen = &ptes[n];
2469
2470 ext_index = n;
2471 pen->ext_pointer = p;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002472 pe4->offset_from_dev_start = extended_offset = start;
Rob Landley081e3842006-08-03 20:07:35 +00002473 pe4->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002474 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2475 pe4->ext_pointer = pe4->part_table + 1;
2476 pe4->changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002477 g_partitions = 5;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002478 }
2479}
2480
2481static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002482add_logical(void)
2483{
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002484 if (g_partitions > 5 || ptes[4].part_table->sys_ind) {
2485 struct pte *pe = &ptes[g_partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002486
Rob Landley081e3842006-08-03 20:07:35 +00002487 pe->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002488 pe->part_table = pt_offset(pe->sectorbuffer, 0);
2489 pe->ext_pointer = pe->part_table + 1;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002490 pe->offset_from_dev_start = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002491 pe->changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002492 g_partitions++;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002493 }
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002494 add_partition(g_partitions - 1, LINUX_NATIVE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002495}
2496
2497static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002498new_partition(void)
2499{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002500 int i, free_primary = 0;
2501
2502 if (warn_geometry())
2503 return;
2504
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002505 if (LABEL_IS_SUN) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002506 add_sun_partition(get_partition(0, g_partitions), LINUX_NATIVE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002507 return;
2508 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002509 if (LABEL_IS_SGI) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002510 sgi_add_partition(get_partition(0, g_partitions), LINUX_NATIVE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002511 return;
2512 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002513 if (LABEL_IS_AIX) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002514 puts("Sorry - this fdisk cannot handle AIX disk labels.\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +00002515"If you want to add DOS-type partitions, create a new empty DOS partition\n"
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002516"table first (use 'o'). This will destroy the present disk contents.");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002517 return;
2518 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002519
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002520 for (i = 0; i < 4; i++)
2521 free_primary += !ptes[i].part_table->sys_ind;
Eric Andersenc48d49a2003-07-03 10:02:32 +00002522
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002523 if (!free_primary && g_partitions >= MAXIMUM_PARTS) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002524 puts("The maximum number of partitions has been created");
Eric Andersen84bdea82004-05-19 10:49:17 +00002525 return;
Rob Landleyb73451d2006-02-24 16:29:00 +00002526 }
Eric Andersenc48d49a2003-07-03 10:02:32 +00002527
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002528 if (!free_primary) {
2529 if (extended_offset)
2530 add_logical();
2531 else
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002532 puts("You must delete some partition and add "
2533 "an extended partition first");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002534 } else {
Denis Vlasenkodfce08f2007-03-19 14:45:10 +00002535 char c, line[80];
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00002536 snprintf(line, sizeof(line),
2537 "Command action\n"
2538 " %s\n"
2539 " p primary partition (1-4)\n",
2540 (extended_offset ?
2541 "l logical (5 or over)" : "e extended"));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002542 while (1) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002543 c = read_nonempty(line);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002544 if ((c | 0x20) == 'p') {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002545 i = get_nonexisting_partition(0, 4);
2546 if (i >= 0)
2547 add_partition(i, LINUX_NATIVE);
2548 return;
2549 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002550 if (c == 'l' && extended_offset) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002551 add_logical();
2552 return;
2553 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002554 if (c == 'e' && !extended_offset) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002555 i = get_nonexisting_partition(0, 4);
2556 if (i >= 0)
2557 add_partition(i, EXTENDED);
2558 return;
2559 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002560 printf("Invalid partition number "
2561 "for type '%c'\n", c);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002562 }
2563 }
2564}
2565
2566static void
Denys Vlasenkob347df92011-08-09 22:49:15 +02002567reread_partition_table(int leave)
2568{
2569 int i;
2570
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002571 puts("Calling ioctl() to re-read partition table");
Denys Vlasenkob347df92011-08-09 22:49:15 +02002572 sync();
2573 /* Users with slow external USB disks on a 320MHz ARM system (year 2011)
2574 * report that sleep is needed, otherwise BLKRRPART may fail with -EIO:
2575 */
2576 sleep(1);
2577 i = ioctl_or_perror(dev_fd, BLKRRPART, NULL,
2578 "WARNING: rereading partition table "
2579 "failed, kernel still uses old table");
2580#if 0
2581 if (dos_changed)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002582 puts(
Denys Vlasenkob347df92011-08-09 22:49:15 +02002583 "\nWARNING: If you have created or modified any DOS 6.x\n"
2584 "partitions, please see the fdisk manual page for additional\n"
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002585 "information");
Denys Vlasenkob347df92011-08-09 22:49:15 +02002586#endif
2587
2588 if (leave) {
2589 if (ENABLE_FEATURE_CLEAN_UP)
2590 close_dev_fd();
2591 exit(i != 0);
2592 }
2593}
2594
2595static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002596write_table(void)
2597{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002598 int i;
2599
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002600 if (LABEL_IS_DOS) {
Rob Landleyb73451d2006-02-24 16:29:00 +00002601 for (i = 0; i < 3; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002602 if (ptes[i].changed)
2603 ptes[3].changed = 1;
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002604 for (i = 3; i < g_partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002605 struct pte *pe = &ptes[i];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002606 if (pe->changed) {
2607 write_part_table_flag(pe->sectorbuffer);
Denys Vlasenkod958e902010-04-06 02:32:26 +02002608 write_sector(pe->offset_from_dev_start, pe->sectorbuffer);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002609 }
2610 }
2611 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002612 else if (LABEL_IS_SGI) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002613 /* no test on change? the "altered" msg below might be mistaken */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002614 sgi_write_table();
2615 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002616 else if (LABEL_IS_SUN) {
Denys Vlasenko80856b32011-07-13 09:06:32 +02002617 for (i = 0; i < 8; i++) {
2618 if (ptes[i].changed) {
2619 sun_write_table();
2620 break;
2621 }
2622 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002623 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002624
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002625 puts("The partition table has been altered.");
Denys Vlasenkob347df92011-08-09 22:49:15 +02002626 reread_partition_table(1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002627}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00002628#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002629
Denis Vlasenko834410a2006-11-29 12:00:28 +00002630#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002631#define MAX_PER_LINE 16
2632static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002633print_buffer(char *pbuffer)
2634{
2635 int i,l;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002636
2637 for (i = 0, l = 0; i < sector_size; i++, l++) {
2638 if (l == 0)
2639 printf("0x%03X:", i);
2640 printf(" %02X", (unsigned char) pbuffer[i]);
2641 if (l == MAX_PER_LINE - 1) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002642 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002643 l = -1;
2644 }
2645 }
2646 if (l > 0)
Denis Vlasenko4daad902007-09-27 10:20:47 +00002647 bb_putchar('\n');
2648 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002649}
2650
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002651static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002652print_raw(void)
2653{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002654 int i;
2655
Denis Vlasenkobd852072007-03-19 14:43:38 +00002656 printf("Device: %s\n", disk_device);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002657 if (LABEL_IS_SGI || LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002658 print_buffer(MBRbuffer);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002659 else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002660 for (i = 3; i < g_partitions; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002661 print_buffer(ptes[i].sectorbuffer);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002662 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002663}
2664
2665static void
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002666move_begin(unsigned i)
Rob Landleyb73451d2006-02-24 16:29:00 +00002667{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002668 struct pte *pe = &ptes[i];
2669 struct partition *p = pe->part_table;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002670 sector_t new, first, nr_sects;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002671
2672 if (warn_geometry())
2673 return;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002674 nr_sects = get_nr_sects(p);
2675 if (!p->sys_ind || !nr_sects || IS_EXTENDED(p->sys_ind)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002676 printf("Partition %u has no data area\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002677 return;
2678 }
Denys Vlasenkofcad7682010-04-06 16:56:33 +02002679 first = get_partition_start_from_dev_start(pe); /* == pe->offset_from_dev_start + get_start_sect(p) */
Denys Vlasenkod958e902010-04-06 02:32:26 +02002680 new = read_int(0 /*was:first*/, first, first + nr_sects - 1, first, "New beginning of data");
2681 if (new != first) {
2682 sector_t new_relative = new - pe->offset_from_dev_start;
2683 nr_sects += (get_start_sect(p) - new_relative);
2684 set_start_sect(p, new_relative);
2685 set_nr_sects(p, nr_sects);
2686 read_nonempty("Recalculate C/H/S values? (Y/N): ");
2687 if ((line_ptr[0] | 0x20) == 'y')
2688 set_hsc_start_end(p, new, new + nr_sects - 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002689 pe->changed = 1;
2690 }
2691}
2692
2693static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002694xselect(void)
2695{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002696 char c;
2697
Rob Landleyb73451d2006-02-24 16:29:00 +00002698 while (1) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00002699 bb_putchar('\n');
Denys Vlasenkod958e902010-04-06 02:32:26 +02002700 c = 0x20 | read_nonempty("Expert command (m for help): ");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002701 switch (c) {
2702 case 'a':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002703 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002704 sun_set_alt_cyl();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002705 break;
2706 case 'b':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002707 if (LABEL_IS_DOS)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002708 move_begin(get_partition(0, g_partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002709 break;
2710 case 'c':
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002711 user_cylinders = g_cylinders =
2712 read_int(1, g_cylinders, 1048576, 0,
Denis Vlasenkobd852072007-03-19 14:43:38 +00002713 "Number of cylinders");
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002714 if (LABEL_IS_SUN)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002715 sun_set_ncyl(g_cylinders);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002716 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002717 warn_cylinders();
2718 break;
2719 case 'd':
2720 print_raw();
2721 break;
2722 case 'e':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002723 if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002724 sgi_set_xcyl();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002725 else if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002726 sun_set_xcyl();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002727 else if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002728 x_list_table(1);
2729 break;
2730 case 'f':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002731 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002732 fix_partition_table_order();
2733 break;
2734 case 'g':
Denis Vlasenko834410a2006-11-29 12:00:28 +00002735#if ENABLE_FEATURE_SGI_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002736 create_sgilabel();
2737#endif
2738 break;
2739 case 'h':
Denys Vlasenkod958e902010-04-06 02:32:26 +02002740 user_heads = g_heads = read_int(1, g_heads, 256, 0, "Number of heads");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002741 update_units();
2742 break;
2743 case 'i':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002744 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002745 sun_set_ilfact();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002746 break;
2747 case 'o':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002748 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002749 sun_set_rspeed();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002750 break;
2751 case 'p':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002752 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002753 list_table(1);
2754 else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002755 x_list_table(0);
2756 break;
2757 case 'q':
Denis Vlasenko4437d192008-04-17 00:12:10 +00002758 if (ENABLE_FEATURE_CLEAN_UP)
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002759 close_dev_fd();
Denis Vlasenko4daad902007-09-27 10:20:47 +00002760 bb_putchar('\n');
Bernhard Reutner-Fischer636a1f82008-05-19 09:29:47 +00002761 exit(EXIT_SUCCESS);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002762 case 'r':
2763 return;
2764 case 's':
Denys Vlasenkod958e902010-04-06 02:32:26 +02002765 user_sectors = g_sectors = read_int(1, g_sectors, 63, 0, "Number of sectors");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002766 if (dos_compatible_flag) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002767 sector_offset = g_sectors;
Denys Vlasenkod60752f2015-10-07 22:42:45 +02002768 puts("Warning: setting sector offset for DOS "
2769 "compatiblity");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002770 }
2771 update_units();
2772 break;
2773 case 'v':
2774 verify();
2775 break;
2776 case 'w':
2777 write_table(); /* does not return */
2778 break;
2779 case 'y':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002780 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002781 sun_set_pcylcount();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002782 break;
2783 default:
2784 xmenu();
2785 }
2786 }
2787}
2788#endif /* ADVANCED mode */
2789
2790static int
Rob Landleyb73451d2006-02-24 16:29:00 +00002791is_ide_cdrom_or_tape(const char *device)
2792{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002793 FILE *procf;
2794 char buf[100];
2795 struct stat statbuf;
2796 int is_ide = 0;
2797
2798 /* No device was given explicitly, and we are trying some
2799 likely things. But opening /dev/hdc may produce errors like
2800 "hdc: tray open or drive not ready"
2801 if it happens to be a CD-ROM drive. It even happens that
2802 the process hangs on the attempt to read a music CD.
2803 So try to be careful. This only works since 2.1.73. */
2804
Denys Vlasenko8dff01d2015-03-12 17:48:34 +01002805 if (!is_prefixed_with(device, "/dev/hd"))
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002806 return 0;
2807
2808 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
Denis Vlasenko5415c852008-07-21 23:05:26 +00002809 procf = fopen_for_read(buf);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002810 if (procf != NULL && fgets(buf, sizeof(buf), procf))
Denys Vlasenko8dff01d2015-03-12 17:48:34 +01002811 is_ide = (is_prefixed_with(buf, "cdrom") ||
2812 is_prefixed_with(buf, "tape"));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002813 else
2814 /* Now when this proc file does not exist, skip the
2815 device when it is read-only. */
2816 if (stat(device, &statbuf) == 0)
2817 is_ide = ((statbuf.st_mode & 0222) == 0);
2818
2819 if (procf)
2820 fclose(procf);
2821 return is_ide;
2822}
2823
Rob Landley5527b912006-02-25 03:46:10 +00002824
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002825static void
Denis Vlasenko4437d192008-04-17 00:12:10 +00002826open_list_and_close(const char *device, int user_specified)
Rob Landleyb73451d2006-02-24 16:29:00 +00002827{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002828 int gb;
2829
2830 disk_device = device;
2831 if (setjmp(listingbuf))
2832 return;
2833 if (!user_specified)
2834 if (is_ide_cdrom_or_tape(device))
2835 return;
Denis Vlasenko4437d192008-04-17 00:12:10 +00002836
2837 /* Open disk_device, save file descriptor to dev_fd */
2838 errno = 0;
2839 gb = get_boot(TRY_ONLY);
2840 if (gb > 0) { /* I/O error */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002841 /* Ignore other errors, since we try IDE
2842 and SCSI hard disks which may not be
2843 installed on the system. */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002844 if (user_specified || errno == EACCES)
2845 bb_perror_msg("can't open '%s'", device);
2846 return;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002847 }
Denis Vlasenko4437d192008-04-17 00:12:10 +00002848
2849 if (gb < 0) { /* no DOS signature */
2850 list_disk_geometry();
2851 if (LABEL_IS_AIX)
2852 goto ret;
2853#if ENABLE_FEATURE_OSF_LABEL
2854 if (bsd_trydev(device) < 0)
2855#endif
2856 printf("Disk %s doesn't contain a valid "
2857 "partition table\n", device);
2858 } else {
2859 list_table(0);
2860#if ENABLE_FEATURE_FDISK_WRITABLE
2861 if (!LABEL_IS_SUN && g_partitions > 4) {
2862 delete_partition(ext_index);
2863 }
2864#endif
2865 }
2866 ret:
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002867 close_dev_fd();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002868}
2869
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002870/* Is it a whole disk? The digit check is still useful
2871 for Xen devices for example. */
2872static int is_whole_disk(const char *disk)
2873{
2874 unsigned len;
2875 int fd = open(disk, O_RDONLY);
2876
2877 if (fd != -1) {
2878 struct hd_geometry geometry;
2879 int err = ioctl(fd, HDIO_GETGEO, &geometry);
2880 close(fd);
2881 if (!err)
2882 return (geometry.start == 0);
2883 }
2884
2885 /* Treat "nameN" as a partition name, not whole disk */
2886 /* note: mmcblk0 should work from the geometry check above */
2887 len = strlen(disk);
2888 if (len != 0 && isdigit(disk[len - 1]))
2889 return 0;
2890
2891 return 1;
2892}
2893
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002894/* for fdisk -l: try all things in /proc/partitions
2895 that look like a partition name (do not end in a digit) */
2896static void
Denis Vlasenko4437d192008-04-17 00:12:10 +00002897list_devs_in_proc_partititons(void)
Rob Landleyb73451d2006-02-24 16:29:00 +00002898{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002899 FILE *procpt;
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002900 char line[100], ptname[100], devname[120];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002901 int ma, mi, sz;
2902
Denis Vlasenkoddec5af2006-10-26 23:25:17 +00002903 procpt = fopen_or_warn("/proc/partitions", "r");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002904
2905 while (fgets(line, sizeof(line), procpt)) {
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002906 if (sscanf(line, " %u %u %u %[^\n ]",
Rob Landleyb73451d2006-02-24 16:29:00 +00002907 &ma, &mi, &sz, ptname) != 4)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002908 continue;
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002909
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002910 sprintf(devname, "/dev/%s", ptname);
Lauri Kasanen9cfcc4d2011-04-30 21:31:05 +02002911 if (is_whole_disk(devname))
2912 open_list_and_close(devname, 0);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002913 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002914#if ENABLE_FEATURE_CLEAN_UP
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002915 fclose(procpt);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002916#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002917}
2918
Denis Vlasenko834410a2006-11-29 12:00:28 +00002919#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002920static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002921unknown_command(int c)
2922{
Denis Vlasenkobd852072007-03-19 14:43:38 +00002923 printf("%c: unknown command\n", c);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002924}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002925#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002926
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00002927int fdisk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002928int fdisk_main(int argc UNUSED_PARAM, char **argv)
Rob Landleyb73451d2006-02-24 16:29:00 +00002929{
Denis Vlasenko834410a2006-11-29 12:00:28 +00002930 unsigned opt;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002931 /*
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002932 * fdisk -v
2933 * fdisk -l [-b sectorsize] [-u] device ...
2934 * fdisk -s [partition] ...
2935 * fdisk [-b sectorsize] [-u] device
2936 *
2937 * Options -C, -H, -S set the geometry.
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002938 */
Denis Vlasenkof77f3692007-12-16 17:22:33 +00002939 INIT_G();
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +00002940
Denis Vlasenkoc033d512008-04-17 01:52:28 +00002941 close_dev_fd(); /* needed: fd 3 must not stay closed */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002942
Denys Vlasenko237bedd2016-07-06 21:58:02 +02002943 opt = getopt32(argv, "b:+C:+H:+lS:+u" IF_FEATURE_FDISK_BLKSIZE("s"),
Denis Vlasenko04e11c92008-02-10 19:44:20 +00002944 &sector_size, &user_cylinders, &user_heads, &user_sectors);
Denis Vlasenko834410a2006-11-29 12:00:28 +00002945 argv += optind;
Denys Vlasenkod958e902010-04-06 02:32:26 +02002946 if (opt & OPT_b) {
Denis Vlasenko834410a2006-11-29 12:00:28 +00002947 /* Ugly: this sector size is really per device,
Denys Vlasenkod958e902010-04-06 02:32:26 +02002948 * so cannot be combined with multiple disks,
2949 * and the same goes for the C/H/S options.
2950 */
2951 if (sector_size < 512
2952 || sector_size > 0x10000
2953 || (sector_size & (sector_size-1)) /* not power of 2 */
2954 ) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002955 bb_show_usage();
Denys Vlasenkod958e902010-04-06 02:32:26 +02002956 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002957 sector_offset = 2;
2958 user_set_sector_size = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002959 }
Denis Vlasenko04e11c92008-02-10 19:44:20 +00002960 if (user_heads <= 0 || user_heads >= 256)
2961 user_heads = 0;
2962 if (user_sectors <= 0 || user_sectors >= 64)
2963 user_sectors = 0;
2964 if (opt & OPT_u)
2965 display_in_cyl_units = 0; // -u
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002966
Denis Vlasenko834410a2006-11-29 12:00:28 +00002967#if ENABLE_FEATURE_FDISK_WRITABLE
2968 if (opt & OPT_l) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002969 nowarn = 1;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002970#endif
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002971 if (*argv) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002972 listing = 1;
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002973 do {
Denis Vlasenko4437d192008-04-17 00:12:10 +00002974 open_list_and_close(*argv, 1);
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002975 } while (*++argv);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002976 } else {
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002977 /* we don't have device names, */
2978 /* use /proc/partitions instead */
Denis Vlasenko4437d192008-04-17 00:12:10 +00002979 list_devs_in_proc_partititons();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002980 }
2981 return 0;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002982#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002983 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002984#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002985
Denis Vlasenko834410a2006-11-29 12:00:28 +00002986#if ENABLE_FEATURE_FDISK_BLKSIZE
2987 if (opt & OPT_s) {
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002988 int j;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002989
2990 nowarn = 1;
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002991 if (!argv[0])
Manuel Novoa III cad53642003-03-19 09:13:01 +00002992 bb_show_usage();
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002993 for (j = 0; argv[j]; j++) {
Denis Vlasenkocdf62772008-03-17 08:42:43 +00002994 unsigned long long size;
2995 fd = xopen(argv[j], O_RDONLY);
Denis Vlasenko4437d192008-04-17 00:12:10 +00002996 size = bb_BLKGETSIZE_sectors(fd) / 2;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002997 close(fd);
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01002998 if (argv[1])
Denys Vlasenkoddf78502009-09-16 03:03:13 +02002999 printf("%llu\n", size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003000 else
Denys Vlasenkoddf78502009-09-16 03:03:13 +02003001 printf("%s: %llu\n", argv[j], size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003002 }
3003 return 0;
3004 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00003005#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003006
Denis Vlasenko834410a2006-11-29 12:00:28 +00003007#if ENABLE_FEATURE_FDISK_WRITABLE
Denys Vlasenkoe992bae2009-11-28 15:18:53 +01003008 if (!argv[0] || argv[1])
Manuel Novoa III cad53642003-03-19 09:13:01 +00003009 bb_show_usage();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003010
Denis Vlasenko834410a2006-11-29 12:00:28 +00003011 disk_device = argv[0];
Denis Vlasenko4437d192008-04-17 00:12:10 +00003012 get_boot(OPEN_MAIN);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003013
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003014 if (LABEL_IS_OSF) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003015 /* OSF label, and no DOS label */
Denis Vlasenkobd852072007-03-19 14:43:38 +00003016 printf("Detected an OSF/1 disklabel on %s, entering "
3017 "disklabel mode\n", disk_device);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +00003018 bsd_select();
Rob Landley5527b912006-02-25 03:46:10 +00003019 /*Why do we do this? It seems to be counter-intuitive*/
Denis Vlasenko4437d192008-04-17 00:12:10 +00003020 current_label_type = LABEL_DOS;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003021 /* If we return we may want to make an empty DOS label? */
3022 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003023
3024 while (1) {
Denis Vlasenko3bba5452006-12-30 17:57:03 +00003025 int c;
Denis Vlasenko4daad902007-09-27 10:20:47 +00003026 bb_putchar('\n');
Denys Vlasenkod958e902010-04-06 02:32:26 +02003027 c = 0x20 | read_nonempty("Command (m for help): ");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003028 switch (c) {
3029 case 'a':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003030 if (LABEL_IS_DOS)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003031 toggle_active(get_partition(1, g_partitions));
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003032 else if (LABEL_IS_SUN)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003033 toggle_sunflags(get_partition(1, g_partitions),
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003034 0x01);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003035 else if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003036 sgi_set_bootpartition(
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003037 get_partition(1, g_partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003038 else
3039 unknown_command(c);
3040 break;
3041 case 'b':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003042 if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00003043 printf("\nThe current boot file is: %s\n",
Rob Landleyb73451d2006-02-24 16:29:00 +00003044 sgi_get_bootfile());
Denis Vlasenkobd852072007-03-19 14:43:38 +00003045 if (read_maybe_empty("Please enter the name of the "
Denys Vlasenko69675782013-01-14 01:34:48 +01003046 "new boot file: ") == '\n')
Denys Vlasenkod60752f2015-10-07 22:42:45 +02003047 puts("Boot file unchanged");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003048 else
3049 sgi_set_bootfile(line_ptr);
Denis Vlasenko834410a2006-11-29 12:00:28 +00003050 }
3051#if ENABLE_FEATURE_OSF_LABEL
3052 else
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +00003053 bsd_select();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003054#endif
3055 break;
3056 case 'c':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003057 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003058 toggle_dos_compatibility_flag();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003059 else if (LABEL_IS_SUN)
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003060 toggle_sunflags(get_partition(1, g_partitions),
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003061 0x10);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003062 else if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003063 sgi_set_swappartition(
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003064 get_partition(1, g_partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003065 else
3066 unknown_command(c);
3067 break;
3068 case 'd':
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00003069 {
Eric Andersen040f4402003-07-30 08:40:37 +00003070 int j;
Eric Andersen040f4402003-07-30 08:40:37 +00003071 /* If sgi_label then don't use get_existing_partition,
3072 let the user select a partition, since
3073 get_existing_partition() only works for Linux-like
3074 partition tables */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003075 if (!LABEL_IS_SGI) {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003076 j = get_existing_partition(1, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00003077 } else {
Denis Vlasenkof77f3692007-12-16 17:22:33 +00003078 j = get_partition(1, g_partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00003079 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00003080 if (j >= 0)
3081 delete_partition(j);
3082 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003083 break;
3084 case 'i':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003085 if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003086 create_sgiinfo();
3087 else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003088 unknown_command(c);
3089 case 'l':
3090 list_types(get_sys_types());
3091 break;
3092 case 'm':
3093 menu();
3094 break;
3095 case 'n':
3096 new_partition();
3097 break;
3098 case 'o':
3099 create_doslabel();
3100 break;
3101 case 'p':
3102 list_table(0);
3103 break;
3104 case 'q':
Denis Vlasenkoc033d512008-04-17 01:52:28 +00003105 if (ENABLE_FEATURE_CLEAN_UP)
3106 close_dev_fd();
Denis Vlasenko4daad902007-09-27 10:20:47 +00003107 bb_putchar('\n');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003108 return 0;
3109 case 's':
Denis Vlasenko834410a2006-11-29 12:00:28 +00003110#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003111 create_sunlabel();
3112#endif
3113 break;
3114 case 't':
3115 change_sysid();
3116 break;
3117 case 'u':
3118 change_units();
3119 break;
3120 case 'v':
3121 verify();
3122 break;
3123 case 'w':
Denys Vlasenko80856b32011-07-13 09:06:32 +02003124 write_table(); /* does not return */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003125 break;
Denis Vlasenko834410a2006-11-29 12:00:28 +00003126#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003127 case 'x':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00003128 if (LABEL_IS_SGI) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02003129 puts("\n\tSorry, no experts menu for SGI "
3130 "partition tables available\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003131 } else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003132 xselect();
3133 break;
3134#endif
3135 default:
3136 unknown_command(c);
3137 menu();
3138 }
3139 }
3140 return 0;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003141#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00003142}