blob: 4ecbadf7862f4976c241b3d75dec90619feb1e8c [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 *
Rob Landleyb73451d2006-02-24 16:29:00 +00007 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00008 */
9
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +000010#ifndef _LARGEFILE64_SOURCE
11/* For lseek64 */
12#define _LARGEFILE64_SOURCE
13#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000014#include <assert.h> /* assert */
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000015#include "libbb.h"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000016
Denis Vlasenko834410a2006-11-29 12:00:28 +000017/* Looks like someone forgot to add this to config system */
18#ifndef ENABLE_FEATURE_FDISK_BLKSIZE
19# define ENABLE_FEATURE_FDISK_BLKSIZE 0
20# define USE_FEATURE_FDISK_BLKSIZE(a)
21#endif
22
Denis Vlasenkodfce08f2007-03-19 14:45:10 +000023#define SIZE(a) (sizeof(a)/sizeof((a)[0]))
24
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000025#define DEFAULT_SECTOR_SIZE 512
26#define MAX_SECTOR_SIZE 2048
Denis Vlasenko98ae2162006-10-12 19:30:44 +000027#define SECTOR_SIZE 512 /* still used in osf/sgi/sun code */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000028#define MAXIMUM_PARTS 60
29
30#define ACTIVE_FLAG 0x80
31
32#define EXTENDED 0x05
33#define WIN98_EXTENDED 0x0f
34#define LINUX_PARTITION 0x81
35#define LINUX_SWAP 0x82
36#define LINUX_NATIVE 0x83
37#define LINUX_EXTENDED 0x85
38#define LINUX_LVM 0x8e
39#define LINUX_RAID 0xfd
40
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +000041/* Used for sector numbers. Today's disk sizes make it necessary */
42typedef unsigned long long ullong;
43
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000044struct hd_geometry {
Rob Landleyb73451d2006-02-24 16:29:00 +000045 unsigned char heads;
46 unsigned char sectors;
47 unsigned short cylinders;
48 unsigned long start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000049};
50
Denis Vlasenko98ae2162006-10-12 19:30:44 +000051#define HDIO_GETGEO 0x0301 /* get device geometry */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000052
Denis Vlasenkobd852072007-03-19 14:43:38 +000053static const char msg_building_new_label[] =
54"Building a new %s. Changes will remain in memory only,\n"
55"until you decide to write them. After that the previous content\n"
56"won't be recoverable.\n\n";
57
58static const char msg_part_already_defined[] =
59"Partition %d is already defined, delete it before re-adding\n";
60
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000061
Denis Vlasenko834410a2006-11-29 12:00:28 +000062static unsigned sector_size = DEFAULT_SECTOR_SIZE;
63static unsigned user_set_sector_size;
64static unsigned sector_offset = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000065
Denis Vlasenko834410a2006-11-29 12:00:28 +000066#if ENABLE_FEATURE_OSF_LABEL
Rob Landleyb73451d2006-02-24 16:29:00 +000067static int possibly_osf_label;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000068#endif
69
Denis Vlasenko834410a2006-11-29 12:00:28 +000070static unsigned heads, sectors, cylinders;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000071static void update_units(void);
72
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000073
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000074struct partition {
75 unsigned char boot_ind; /* 0x80 - active */
76 unsigned char head; /* starting head */
77 unsigned char sector; /* starting sector */
78 unsigned char cyl; /* starting cylinder */
79 unsigned char sys_ind; /* What partition type */
80 unsigned char end_head; /* end head */
81 unsigned char end_sector; /* end sector */
82 unsigned char end_cyl; /* end cylinder */
83 unsigned char start4[4]; /* starting sector counting from 0 */
84 unsigned char size4[4]; /* nr of sectors in partition */
Bernhard Reutner-Fischer86f5c992006-01-22 22:55:11 +000085} ATTRIBUTE_PACKED;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000086
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +000087static const char unable_to_open[] = "cannot open %s";
88static const char unable_to_read[] = "cannot read from %s";
89static const char unable_to_seek[] = "cannot seek on %s";
90static const char unable_to_write[] = "cannot write to %s";
91static const char ioctl_error[] = "BLKGETSIZE ioctl failed on %s";
92static void fdisk_fatal(const char *why) ATTRIBUTE_NORETURN;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000093
Denis Vlasenko98ae2162006-10-12 19:30:44 +000094enum label_type {
Rob Landley5527b912006-02-25 03:46:10 +000095 label_dos, label_sun, label_sgi, label_aix, label_osf
96};
Denis Vlasenkodfce08f2007-03-19 14:45:10 +000097
Denis Vlasenko98ae2162006-10-12 19:30:44 +000098#define LABEL_IS_DOS (label_dos == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +000099
Denis Vlasenko834410a2006-11-29 12:00:28 +0000100#if ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000101#define LABEL_IS_SUN (label_sun == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000102#define STATIC_SUN static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000103#else
104#define LABEL_IS_SUN 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000105#define STATIC_SUN extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000106#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000107
Denis Vlasenko834410a2006-11-29 12:00:28 +0000108#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000109#define LABEL_IS_SGI (label_sgi == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000110#define STATIC_SGI static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000111#else
112#define LABEL_IS_SGI 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000113#define STATIC_SGI extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000114#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000115
Denis Vlasenko834410a2006-11-29 12:00:28 +0000116#if ENABLE_FEATURE_AIX_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000117#define LABEL_IS_AIX (label_aix == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000118#define STATIC_AIX static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000119#else
120#define LABEL_IS_AIX 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000121#define STATIC_AIX extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000122#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000123
Denis Vlasenko834410a2006-11-29 12:00:28 +0000124#if ENABLE_FEATURE_OSF_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000125#define LABEL_IS_OSF (label_osf == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000126#define STATIC_OSF static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000127#else
128#define LABEL_IS_OSF 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000129#define STATIC_OSF extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000130#endif
Rob Landley5527b912006-02-25 03:46:10 +0000131
Rob Landleyb73451d2006-02-24 16:29:00 +0000132enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000133
Rob Landley5527b912006-02-25 03:46:10 +0000134static enum label_type current_label_type;
135
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000136static const char *disk_device;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000137static int fd; /* the disk */
138static int partitions = 4; /* maximum partition + 1 */
Denis Vlasenko834410a2006-11-29 12:00:28 +0000139static int display_in_cyl_units = 1;
140static unsigned units_per_sector = 1;
141#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000142static void change_units(void);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000143static void reread_partition_table(int leave);
144static void delete_partition(int i);
Rob Landleyb73451d2006-02-24 16:29:00 +0000145static int get_partition(int warn, int max);
Denis Vlasenkobd852072007-03-19 14:43:38 +0000146static void list_types(const char *const *sys);
Denis Vlasenko06c0a712007-01-29 22:51:44 +0000147static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000148#endif
149static const char *partition_type(unsigned char type);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000150static void get_geometry(void);
151static int get_boot(enum action what);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000152
153#define PLURAL 0
154#define SINGULAR 1
155
Denis Vlasenko28703012006-12-19 20:32:02 +0000156static unsigned get_start_sect(const struct partition *p);
157static unsigned get_nr_sects(const struct partition *p);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000158
159/*
160 * per partition table entry data
161 *
162 * The four primary partitions have the same sectorbuffer (MBRbuffer)
163 * and have NULL ext_pointer.
164 * Each logical partition table entry has two pointers, one for the
165 * partition and one link to the next one.
166 */
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000167struct pte {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000168 struct partition *part_table; /* points into sectorbuffer */
169 struct partition *ext_pointer; /* points into sectorbuffer */
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000170 ullong offset; /* disk sector number */
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000171 char *sectorbuffer; /* disk sector contents */
Denis Vlasenko834410a2006-11-29 12:00:28 +0000172#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000173 char changed; /* boolean */
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000174#endif
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000175};
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000176
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000177/* DOS partition types */
178
179static const char *const i386_sys_types[] = {
180 "\x00" "Empty",
181 "\x01" "FAT12",
182 "\x04" "FAT16 <32M",
183 "\x05" "Extended", /* DOS 3.3+ extended partition */
184 "\x06" "FAT16", /* DOS 16-bit >=32M */
185 "\x07" "HPFS/NTFS", /* OS/2 IFS, eg, HPFS or NTFS or QNX */
186 "\x0a" "OS/2 Boot Manager",/* OS/2 Boot Manager */
187 "\x0b" "Win95 FAT32",
188 "\x0c" "Win95 FAT32 (LBA)",/* LBA really is 'Extended Int 13h' */
189 "\x0e" "Win95 FAT16 (LBA)",
190 "\x0f" "Win95 Ext'd (LBA)",
191 "\x11" "Hidden FAT12",
192 "\x12" "Compaq diagnostics",
193 "\x14" "Hidden FAT16 <32M",
194 "\x16" "Hidden FAT16",
195 "\x17" "Hidden HPFS/NTFS",
196 "\x1b" "Hidden Win95 FAT32",
197 "\x1c" "Hidden W95 FAT32 (LBA)",
198 "\x1e" "Hidden W95 FAT16 (LBA)",
199 "\x3c" "Part.Magic recovery",
200 "\x41" "PPC PReP Boot",
201 "\x42" "SFS",
202 "\x63" "GNU HURD or SysV", /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
203 "\x80" "Old Minix", /* Minix 1.4a and earlier */
204 "\x81" "Minix / old Linux",/* Minix 1.4b and later */
205 "\x82" "Linux swap", /* also Solaris */
206 "\x83" "Linux",
207 "\x84" "OS/2 hidden C: drive",
208 "\x85" "Linux extended",
209 "\x86" "NTFS volume set",
210 "\x87" "NTFS volume set",
211 "\x8e" "Linux LVM",
212 "\x9f" "BSD/OS", /* BSDI */
213 "\xa0" "Thinkpad hibernation",
214 "\xa5" "FreeBSD", /* various BSD flavours */
215 "\xa6" "OpenBSD",
216 "\xa8" "Darwin UFS",
217 "\xa9" "NetBSD",
218 "\xab" "Darwin boot",
219 "\xb7" "BSDI fs",
220 "\xb8" "BSDI swap",
221 "\xbe" "Solaris boot",
222 "\xeb" "BeOS fs",
223 "\xee" "EFI GPT", /* Intel EFI GUID Partition Table */
224 "\xef" "EFI (FAT-12/16/32)", /* Intel EFI System Partition */
225 "\xf0" "Linux/PA-RISC boot", /* Linux/PA-RISC boot loader */
226 "\xf2" "DOS secondary", /* DOS 3.3+ secondary */
227 "\xfd" "Linux raid autodetect", /* New (2.2.x) raid partition with
228 autodetect using persistent
229 superblock */
230#if 0 /* ENABLE_WEIRD_PARTITION_TYPES */
231 "\x02" "XENIX root",
232 "\x03" "XENIX usr",
233 "\x08" "AIX", /* AIX boot (AIX -- PS/2 port) or SplitDrive */
234 "\x09" "AIX bootable", /* AIX data or Coherent */
235 "\x10" "OPUS",
236 "\x18" "AST SmartSleep",
237 "\x24" "NEC DOS",
238 "\x39" "Plan 9",
239 "\x40" "Venix 80286",
240 "\x4d" "QNX4.x",
241 "\x4e" "QNX4.x 2nd part",
242 "\x4f" "QNX4.x 3rd part",
243 "\x50" "OnTrack DM",
244 "\x51" "OnTrack DM6 Aux1", /* (or Novell) */
245 "\x52" "CP/M", /* CP/M or Microport SysV/AT */
246 "\x53" "OnTrack DM6 Aux3",
247 "\x54" "OnTrackDM6",
248 "\x55" "EZ-Drive",
249 "\x56" "Golden Bow",
250 "\x5c" "Priam Edisk",
251 "\x61" "SpeedStor",
252 "\x64" "Novell Netware 286",
253 "\x65" "Novell Netware 386",
254 "\x70" "DiskSecure Multi-Boot",
255 "\x75" "PC/IX",
256 "\x93" "Amoeba",
257 "\x94" "Amoeba BBT", /* (bad block table) */
258 "\xa7" "NeXTSTEP",
259 "\xbb" "Boot Wizard hidden",
260 "\xc1" "DRDOS/sec (FAT-12)",
261 "\xc4" "DRDOS/sec (FAT-16 < 32M)",
262 "\xc6" "DRDOS/sec (FAT-16)",
263 "\xc7" "Syrinx",
264 "\xda" "Non-FS data",
265 "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or
266 Concurrent DOS or CTOS */
267 "\xde" "Dell Utility", /* Dell PowerEdge Server utilities */
268 "\xdf" "BootIt", /* BootIt EMBRM */
269 "\xe1" "DOS access", /* DOS access or SpeedStor 12-bit FAT
270 extended partition */
271 "\xe3" "DOS R/O", /* DOS R/O or SpeedStor */
272 "\xe4" "SpeedStor", /* SpeedStor 16-bit FAT extended
273 partition < 1024 cyl. */
274 "\xf1" "SpeedStor",
275 "\xf4" "SpeedStor", /* SpeedStor large partition */
276 "\xfe" "LANstep", /* SpeedStor >1024 cyl. or LANstep */
277 "\xff" "BBT", /* Xenix Bad Block Table */
278#endif
279 NULL
280};
281
282
283/* Globals */
284
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000285struct globals {
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000286 char *line_ptr;
287 char line_buffer[80];
288 char partname_buffer[80];
289 jmp_buf listingbuf;
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000290 /* Raw disk label. For DOS-type partition tables the MBR,
291 * with descriptions of the primary partitions. */
292 char MBRbuffer[MAX_SECTOR_SIZE];
293 /* Partition tables */
294 struct pte ptes[MAXIMUM_PARTS];
295};
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000296/* bb_common_bufsiz1 is too small for this on 64 bit CPUs */
297#define G (*ptr_to_globals)
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000298
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000299#define line_ptr (G.line_ptr)
300#define listingbuf (G.listingbuf)
301#define line_buffer (G.line_buffer)
302#define partname_buffer (G.partname_buffer)
303#define MBRbuffer (G.MBRbuffer)
304#define ptes (G.ptes)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000305
Denis Vlasenkobd852072007-03-19 14:43:38 +0000306
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000307/* Code */
308
309#define IS_EXTENDED(i) \
310 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
311
312#define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
313
314#define scround(x) (((x)+units_per_sector-1)/units_per_sector)
315
316#define pt_offset(b, n) \
317 ((struct partition *)((b) + 0x1be + (n) * sizeof(struct partition)))
318
319#define sector(s) ((s) & 0x3f)
320
321#define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
322
323#define hsc2sector(h,s,c) \
324 (sector(s) - 1 + sectors * ((h) + heads * cylinder(s,c)))
325
326#define set_hsc(h,s,c,sector) \
327 do { \
328 s = sector % sectors + 1; \
329 sector /= sectors; \
330 h = sector % heads; \
331 sector /= heads; \
332 c = sector & 0xff; \
333 s |= (sector >> 2) & 0xc0; \
334 } while (0)
335
Denis Vlasenko58875ae2007-03-22 22:22:10 +0000336#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000337/* read line; return 0 or first printable char */
338static int
339read_line(const char *prompt)
340{
341 int sz;
342
343 sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
344 if (sz <= 0)
345 exit(0); /* Ctrl-D or Ctrl-C */
346
347 if (line_buffer[sz-1] == '\n')
348 line_buffer[--sz] = '\0';
349
350 line_ptr = line_buffer;
351 while (*line_ptr && !isgraph(*line_ptr))
352 line_ptr++;
353 return *line_ptr;
354}
Denis Vlasenko58875ae2007-03-22 22:22:10 +0000355#endif
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000356
Denis Vlasenkobd852072007-03-19 14:43:38 +0000357/*
358 * return partition name - uses static storage
359 */
360static const char *
361partname(const char *dev, int pno, int lth)
362{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000363 const char *p;
364 int w, wp;
365 int bufsiz;
366 char *bufp;
367
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000368 bufp = partname_buffer;
369 bufsiz = sizeof(partname_buffer);
Denis Vlasenkobd852072007-03-19 14:43:38 +0000370
371 w = strlen(dev);
372 p = "";
373
374 if (isdigit(dev[w-1]))
375 p = "p";
376
377 /* devfs kludge - note: fdisk partition names are not supposed
378 to equal kernel names, so there is no reason to do this */
379 if (strcmp(dev + w - 4, "disc") == 0) {
380 w -= 4;
381 p = "part";
382 }
383
384 wp = strlen(p);
385
386 if (lth) {
387 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
388 lth-wp-2, w, dev, p, pno);
389 } else {
390 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
391 }
392 return bufp;
393}
394
Denis Vlasenko834410a2006-11-29 12:00:28 +0000395#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000396static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000397set_all_unchanged(void)
398{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000399 int i;
400
401 for (i = 0; i < MAXIMUM_PARTS; i++)
402 ptes[i].changed = 0;
403}
404
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000405static ALWAYS_INLINE void
Rob Landleyb73451d2006-02-24 16:29:00 +0000406set_changed(int i)
407{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000408 ptes[i].changed = 1;
409}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000410#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000411
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000412static ALWAYS_INLINE struct partition *
Rob Landleyb73451d2006-02-24 16:29:00 +0000413get_part_table(int i)
414{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000415 return ptes[i].part_table;
416}
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000417
418static const char *
Rob Landleyb73451d2006-02-24 16:29:00 +0000419str_units(int n)
420{ /* n==1: use singular */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000421 if (n == 1)
Denis Vlasenkobd852072007-03-19 14:43:38 +0000422 return display_in_cyl_units ? "cylinder" : "sector";
423 return display_in_cyl_units ? "cylinders" : "sectors";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000424}
425
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000426static int
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000427valid_part_table_flag(const char *mbuffer)
428{
Denis Vlasenko834410a2006-11-29 12:00:28 +0000429 return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000430}
431
Denis Vlasenko834410a2006-11-29 12:00:28 +0000432#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000433static ALWAYS_INLINE void
Denis Vlasenko834410a2006-11-29 12:00:28 +0000434write_part_table_flag(char *b)
435{
436 b[510] = 0x55;
437 b[511] = 0xaa;
438}
439
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000440static char
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000441read_nonempty(const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000442{
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000443 while (!read_line(mesg)) /* repeat */;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000444 return *line_ptr;
445}
446
447static char
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000448read_maybe_empty(const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000449{
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000450 if (!read_line(mesg)) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000451 line_ptr = line_buffer;
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000452 line_ptr[0] = '\n';
453 line_ptr[1] = '\0';
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000454 }
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000455 return line_ptr[0];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000456}
457
458static int
Denis Vlasenkobd852072007-03-19 14:43:38 +0000459read_hex(const char *const *sys)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000460{
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000461 unsigned long v;
Rob Landleyb73451d2006-02-24 16:29:00 +0000462 while (1) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000463 read_nonempty("Hex code (type L to list codes): ");
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000464 if (*line_ptr == 'l' || *line_ptr == 'L') {
Rob Landleyb73451d2006-02-24 16:29:00 +0000465 list_types(sys);
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000466 continue;
Rob Landleyb73451d2006-02-24 16:29:00 +0000467 }
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000468 v = bb_strtoul(line_ptr, NULL, 16);
Denis Vlasenko28703012006-12-19 20:32:02 +0000469 if (v > 0xff)
470 /* Bad input also triggers this */
471 continue;
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000472 return v;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000473 }
474}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000475#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000476
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000477#include "fdisk_aix.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000478
479typedef struct {
480 unsigned char info[128]; /* Informative text string */
481 unsigned char spare0[14];
482 struct sun_info {
483 unsigned char spare1;
484 unsigned char id;
485 unsigned char spare2;
486 unsigned char flags;
487 } infos[8];
488 unsigned char spare1[246]; /* Boot information etc. */
489 unsigned short rspeed; /* Disk rotational speed */
490 unsigned short pcylcount; /* Physical cylinder count */
491 unsigned short sparecyl; /* extra sects per cylinder */
492 unsigned char spare2[4]; /* More magic... */
493 unsigned short ilfact; /* Interleave factor */
494 unsigned short ncyl; /* Data cylinder count */
495 unsigned short nacyl; /* Alt. cylinder count */
496 unsigned short ntrks; /* Tracks per cylinder */
497 unsigned short nsect; /* Sectors per track */
498 unsigned char spare3[4]; /* Even more magic... */
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000499 struct sun_partinfo {
Eric Andersenacd244a2002-12-11 03:49:33 +0000500 uint32_t start_cylinder;
501 uint32_t num_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000502 } partitions[8];
503 unsigned short magic; /* Magic number */
504 unsigned short csum; /* Label xor'd checksum */
505} sun_partition;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000506#define sunlabel ((sun_partition *)MBRbuffer)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000507STATIC_OSF void bsd_select(void);
508STATIC_OSF void xbsd_print_disklabel(int);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000509#include "fdisk_osf.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000510
Denis Vlasenko28703012006-12-19 20:32:02 +0000511#if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000512static uint16_t
Denis Vlasenko28703012006-12-19 20:32:02 +0000513fdisk_swap16(uint16_t x)
Rob Landleyb73451d2006-02-24 16:29:00 +0000514{
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000515 return (x << 8) | (x >> 8);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000516}
517
Rob Landley88621d72006-08-29 19:41:06 +0000518static uint32_t
Denis Vlasenko28703012006-12-19 20:32:02 +0000519fdisk_swap32(uint32_t x)
Rob Landleyb73451d2006-02-24 16:29:00 +0000520{
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000521 return (x << 24) |
522 ((x & 0xFF00) << 8) |
523 ((x & 0xFF0000) >> 8) |
524 (x >> 24);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000525}
526#endif
527
Denis Vlasenkobd852072007-03-19 14:43:38 +0000528STATIC_SGI const char *const sgi_sys_types[];
Denis Vlasenko834410a2006-11-29 12:00:28 +0000529STATIC_SGI unsigned sgi_get_num_sectors(int i);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000530STATIC_SGI int sgi_get_sysid(int i);
531STATIC_SGI void sgi_delete_partition(int i);
532STATIC_SGI void sgi_change_sysid(int i, int sys);
533STATIC_SGI void sgi_list_table(int xtra);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000534#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000535STATIC_SGI void sgi_set_xcyl(void);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000536#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000537STATIC_SGI int verify_sgi(int verbose);
538STATIC_SGI void sgi_add_partition(int n, int sys);
539STATIC_SGI void sgi_set_swappartition(int i);
540STATIC_SGI const char *sgi_get_bootfile(void);
541STATIC_SGI void sgi_set_bootfile(const char* aFile);
542STATIC_SGI void create_sgiinfo(void);
543STATIC_SGI void sgi_write_table(void);
544STATIC_SGI void sgi_set_bootpartition(int i);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000545#include "fdisk_sgi.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000546
Denis Vlasenkobd852072007-03-19 14:43:38 +0000547STATIC_SUN const char *const sun_sys_types[];
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000548STATIC_SUN void sun_delete_partition(int i);
549STATIC_SUN void sun_change_sysid(int i, int sys);
550STATIC_SUN void sun_list_table(int xtra);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000551STATIC_SUN void add_sun_partition(int n, int sys);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000552#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000553STATIC_SUN void sun_set_alt_cyl(void);
554STATIC_SUN void sun_set_ncyl(int cyl);
555STATIC_SUN void sun_set_xcyl(void);
556STATIC_SUN void sun_set_ilfact(void);
557STATIC_SUN void sun_set_rspeed(void);
558STATIC_SUN void sun_set_pcylcount(void);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000559#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000560STATIC_SUN void toggle_sunflags(int i, unsigned char mask);
561STATIC_SUN void verify_sun(void);
562STATIC_SUN void sun_write_table(void);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000563#include "fdisk_sun.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000564
Denis Vlasenko834410a2006-11-29 12:00:28 +0000565#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000566/* start_sect and nr_sects are stored little endian on all machines */
567/* moreover, they are not aligned correctly */
568static void
Denis Vlasenko834410a2006-11-29 12:00:28 +0000569store4_little_endian(unsigned char *cp, unsigned val)
Rob Landleyb73451d2006-02-24 16:29:00 +0000570{
Denis Vlasenko834410a2006-11-29 12:00:28 +0000571 cp[0] = val;
572 cp[1] = val >> 8;
573 cp[2] = val >> 16;
574 cp[3] = val >> 24;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000575}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000576#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000577
Denis Vlasenko834410a2006-11-29 12:00:28 +0000578static unsigned
Rob Landleyb73451d2006-02-24 16:29:00 +0000579read4_little_endian(const unsigned char *cp)
580{
Denis Vlasenko834410a2006-11-29 12:00:28 +0000581 return cp[0] + (cp[1] << 8) + (cp[2] << 16) + (cp[3] << 24);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000582}
583
Denis Vlasenko834410a2006-11-29 12:00:28 +0000584#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000585static void
Denis Vlasenko834410a2006-11-29 12:00:28 +0000586set_start_sect(struct partition *p, unsigned start_sect)
Rob Landleyb73451d2006-02-24 16:29:00 +0000587{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000588 store4_little_endian(p->start4, start_sect);
589}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000590#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000591
Denis Vlasenko28703012006-12-19 20:32:02 +0000592static unsigned
Rob Landleyb73451d2006-02-24 16:29:00 +0000593get_start_sect(const struct partition *p)
594{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000595 return read4_little_endian(p->start4);
596}
597
Denis Vlasenko834410a2006-11-29 12:00:28 +0000598#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000599static void
Denis Vlasenko28703012006-12-19 20:32:02 +0000600set_nr_sects(struct partition *p, unsigned nr_sects)
Rob Landleyb73451d2006-02-24 16:29:00 +0000601{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000602 store4_little_endian(p->size4, nr_sects);
603}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000604#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000605
Denis Vlasenko28703012006-12-19 20:32:02 +0000606static unsigned
Rob Landleyb73451d2006-02-24 16:29:00 +0000607get_nr_sects(const struct partition *p)
608{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000609 return read4_little_endian(p->size4);
610}
611
612/* normally O_RDWR, -l option gives O_RDONLY */
613static int type_open = O_RDWR;
614
Rob Landleyb73451d2006-02-24 16:29:00 +0000615static int ext_index; /* the prime extended partition */
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000616static int listing; /* no aborts for fdisk -l */
Rob Landleyb73451d2006-02-24 16:29:00 +0000617static int dos_compatible_flag = ~0;
Denis Vlasenko834410a2006-11-29 12:00:28 +0000618#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000619static int dos_changed;
620static int nowarn; /* no warnings for fdisk -l/-s */
621#endif
622
Denis Vlasenko834410a2006-11-29 12:00:28 +0000623static unsigned user_cylinders, user_heads, user_sectors;
624static unsigned pt_heads, pt_sectors;
625static unsigned kern_heads, kern_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000626
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000627static ullong extended_offset; /* offset of link pointers */
628static ullong total_number_of_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000629
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000630static void fdisk_fatal(const char *why)
Rob Landleyb73451d2006-02-24 16:29:00 +0000631{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000632 if (listing) {
633 close(fd);
634 longjmp(listingbuf, 1);
635 }
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000636 bb_error_msg_and_die(why, disk_device);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000637}
638
639static void
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000640seek_sector(ullong secno)
Rob Landleyb73451d2006-02-24 16:29:00 +0000641{
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000642 secno *= sector_size;
643 if (lseek64(fd, (off64_t)secno, SEEK_SET) == (off64_t) -1)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000644 fdisk_fatal(unable_to_seek);
645}
646
Denis Vlasenko834410a2006-11-29 12:00:28 +0000647#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000648static void
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000649write_sector(ullong secno, char *buf)
Rob Landleyb73451d2006-02-24 16:29:00 +0000650{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000651 seek_sector(secno);
652 if (write(fd, buf, sector_size) != sector_size)
653 fdisk_fatal(unable_to_write);
654}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000655#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000656
657/* Allocate a buffer and read a partition table sector */
658static void
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000659read_pte(struct pte *pe, ullong offset)
Rob Landleyb73451d2006-02-24 16:29:00 +0000660{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000661 pe->offset = offset;
Denis Vlasenkob95636c2006-12-19 23:36:04 +0000662 pe->sectorbuffer = xmalloc(sector_size);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000663 seek_sector(offset);
664 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
665 fdisk_fatal(unable_to_read);
Denis Vlasenko834410a2006-11-29 12:00:28 +0000666#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000667 pe->changed = 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000668#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000669 pe->part_table = pe->ext_pointer = NULL;
670}
671
Denis Vlasenko834410a2006-11-29 12:00:28 +0000672static unsigned
Rob Landleyb73451d2006-02-24 16:29:00 +0000673get_partition_start(const struct pte *pe)
674{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000675 return pe->offset + get_start_sect(pe->part_table);
676}
677
Denis Vlasenko834410a2006-11-29 12:00:28 +0000678#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000679/*
680 * Avoid warning about DOS partitions when no DOS partition was changed.
681 * Here a heuristic "is probably dos partition".
682 * We might also do the opposite and warn in all cases except
683 * for "is probably nondos partition".
684 */
685static int
Rob Landleyb73451d2006-02-24 16:29:00 +0000686is_dos_partition(int t)
687{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000688 return (t == 1 || t == 4 || t == 6 ||
689 t == 0x0b || t == 0x0c || t == 0x0e ||
690 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
691 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
692 t == 0xc1 || t == 0xc4 || t == 0xc6);
693}
694
695static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000696menu(void)
697{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000698 puts("Command Action");
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000699 if (LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000700 puts("a\ttoggle a read only flag"); /* sun */
701 puts("b\tedit bsd disklabel");
702 puts("c\ttoggle the mountable flag"); /* sun */
703 puts("d\tdelete a partition");
704 puts("l\tlist known partition types");
705 puts("n\tadd a new partition");
706 puts("o\tcreate a new empty DOS partition table");
707 puts("p\tprint the partition table");
708 puts("q\tquit without saving changes");
709 puts("s\tcreate a new empty Sun disklabel"); /* sun */
710 puts("t\tchange a partition's system id");
711 puts("u\tchange display/entry units");
712 puts("v\tverify the partition table");
713 puts("w\twrite table to disk and exit");
Denis Vlasenko834410a2006-11-29 12:00:28 +0000714#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkobd852072007-03-19 14:43:38 +0000715 puts("x\textra functionality (experts only)");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000716#endif
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000717 } else if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000718 puts("a\tselect bootable partition"); /* sgi flavour */
719 puts("b\tedit bootfile entry"); /* sgi */
720 puts("c\tselect sgi swap partition"); /* sgi flavour */
721 puts("d\tdelete a partition");
722 puts("l\tlist known partition types");
723 puts("n\tadd a new partition");
724 puts("o\tcreate a new empty DOS partition table");
725 puts("p\tprint the partition table");
726 puts("q\tquit without saving changes");
727 puts("s\tcreate a new empty Sun disklabel"); /* sun */
728 puts("t\tchange a partition's system id");
729 puts("u\tchange display/entry units");
730 puts("v\tverify the partition table");
731 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000732 } else if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000733 puts("o\tcreate a new empty DOS partition table");
734 puts("q\tquit without saving changes");
735 puts("s\tcreate a new empty Sun disklabel"); /* sun */
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000736 } else {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000737 puts("a\ttoggle a bootable flag");
738 puts("b\tedit bsd disklabel");
739 puts("c\ttoggle the dos compatibility flag");
740 puts("d\tdelete a partition");
741 puts("l\tlist known partition types");
742 puts("n\tadd a new partition");
743 puts("o\tcreate a new empty DOS partition table");
744 puts("p\tprint the partition table");
745 puts("q\tquit without saving changes");
746 puts("s\tcreate a new empty Sun disklabel"); /* sun */
747 puts("t\tchange a partition's system id");
748 puts("u\tchange display/entry units");
749 puts("v\tverify the partition table");
750 puts("w\twrite table to disk and exit");
Denis Vlasenko834410a2006-11-29 12:00:28 +0000751#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkobd852072007-03-19 14:43:38 +0000752 puts("x\textra functionality (experts only)");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000753#endif
754 }
755}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000756#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000757
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000758
Denis Vlasenko834410a2006-11-29 12:00:28 +0000759#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000760static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000761xmenu(void)
762{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000763 puts("Command Action");
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000764 if (LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000765 puts("a\tchange number of alternate cylinders"); /*sun*/
766 puts("c\tchange number of cylinders");
767 puts("d\tprint the raw data in the partition table");
768 puts("e\tchange number of extra sectors per cylinder");/*sun*/
769 puts("h\tchange number of heads");
770 puts("i\tchange interleave factor"); /*sun*/
771 puts("o\tchange rotation speed (rpm)"); /*sun*/
772 puts("p\tprint the partition table");
773 puts("q\tquit without saving changes");
774 puts("r\treturn to main menu");
775 puts("s\tchange number of sectors/track");
776 puts("v\tverify the partition table");
777 puts("w\twrite table to disk and exit");
778 puts("y\tchange number of physical cylinders"); /*sun*/
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000779 } else if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000780 puts("b\tmove beginning of data in a partition"); /* !sun */
781 puts("c\tchange number of cylinders");
782 puts("d\tprint the raw data in the partition table");
783 puts("e\tlist extended partitions"); /* !sun */
784 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
785 puts("h\tchange number of heads");
786 puts("p\tprint the partition table");
787 puts("q\tquit without saving changes");
788 puts("r\treturn to main menu");
789 puts("s\tchange number of sectors/track");
790 puts("v\tverify the partition table");
791 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000792 } else if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000793 puts("b\tmove beginning of data in a partition"); /* !sun */
794 puts("c\tchange number of cylinders");
795 puts("d\tprint the raw data in the partition table");
796 puts("e\tlist extended partitions"); /* !sun */
797 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
798 puts("h\tchange number of heads");
799 puts("p\tprint the partition table");
800 puts("q\tquit without saving changes");
801 puts("r\treturn to main menu");
802 puts("s\tchange number of sectors/track");
803 puts("v\tverify the partition table");
804 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000805 } else {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000806 puts("b\tmove beginning of data in a partition"); /* !sun */
807 puts("c\tchange number of cylinders");
808 puts("d\tprint the raw data in the partition table");
809 puts("e\tlist extended partitions"); /* !sun */
810 puts("f\tfix partition order"); /* !sun, !aix, !sgi */
Denis Vlasenko834410a2006-11-29 12:00:28 +0000811#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenkobd852072007-03-19 14:43:38 +0000812 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000813#endif
Denis Vlasenkobd852072007-03-19 14:43:38 +0000814 puts("h\tchange number of heads");
815 puts("p\tprint the partition table");
816 puts("q\tquit without saving changes");
817 puts("r\treturn to main menu");
818 puts("s\tchange number of sectors/track");
819 puts("v\tverify the partition table");
820 puts("w\twrite table to disk and exit");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000821 }
822}
823#endif /* ADVANCED mode */
824
Denis Vlasenko834410a2006-11-29 12:00:28 +0000825#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenkobd852072007-03-19 14:43:38 +0000826static const char *const *
Rob Landleyb73451d2006-02-24 16:29:00 +0000827get_sys_types(void)
828{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000829 return (
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000830 LABEL_IS_SUN ? sun_sys_types :
831 LABEL_IS_SGI ? sgi_sys_types :
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000832 i386_sys_types);
833}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000834#else
835#define get_sys_types() i386_sys_types
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000836#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000837
Denis Vlasenkobd852072007-03-19 14:43:38 +0000838static const char *
839partition_type(unsigned char type)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000840{
841 int i;
Denis Vlasenkobd852072007-03-19 14:43:38 +0000842 const char *const *types = get_sys_types();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000843
Denis Vlasenkobd852072007-03-19 14:43:38 +0000844 for (i = 0; types[i]; i++)
845 if ((unsigned char)types[i][0] == type)
846 return types[i] + 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000847
Denis Vlasenkobd852072007-03-19 14:43:38 +0000848 return "Unknown";
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000849}
850
851
Denis Vlasenko834410a2006-11-29 12:00:28 +0000852#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000853static int
Rob Landleyb73451d2006-02-24 16:29:00 +0000854get_sysid(int i)
855{
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000856 return LABEL_IS_SUN ? sunlabel->infos[i].id :
857 (LABEL_IS_SGI ? sgi_get_sysid(i) :
858 ptes[i].part_table->sys_ind);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000859}
860
Denis Vlasenkobd852072007-03-19 14:43:38 +0000861static void
862list_types(const char *const *sys)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000863{
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000864 enum { COLS = 3 };
865
866 unsigned last[COLS];
867 unsigned done, next, size;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000868 int i;
869
Denis Vlasenkobd852072007-03-19 14:43:38 +0000870 for (size = 0; sys[size]; size++) /* */;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000871
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000872 done = 0;
873 for (i = COLS-1; i >= 0; i--) {
874 done += (size + i - done) / (i + 1);
875 last[COLS-1 - i] = done;
876 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000877
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000878 i = done = next = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000879 do {
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000880 printf("%c%2x %-22.22s", i ? ' ' : '\n',
Denis Vlasenkobd852072007-03-19 14:43:38 +0000881 (unsigned char)sys[next][0],
882 sys[next] + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000883 next = last[i++] + done;
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000884 if (i >= COLS || next >= last[i]) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000885 i = 0;
886 next = ++done;
887 }
888 } while (done < last[0]);
889 putchar('\n');
890}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000891#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000892
893static int
Rob Landleyb73451d2006-02-24 16:29:00 +0000894is_cleared_partition(const struct partition *p)
895{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000896 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
897 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
898 get_start_sect(p) || get_nr_sects(p));
899}
900
901static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000902clear_partition(struct partition *p)
903{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000904 if (!p)
905 return;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000906 memset(p, 0, sizeof(struct partition));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000907}
908
Denis Vlasenko834410a2006-11-29 12:00:28 +0000909#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000910static void
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000911set_partition(int i, int doext, ullong start, ullong stop, int sysid)
Rob Landleyb73451d2006-02-24 16:29:00 +0000912{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000913 struct partition *p;
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000914 ullong offset;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000915
916 if (doext) {
917 p = ptes[i].ext_pointer;
918 offset = extended_offset;
919 } else {
920 p = ptes[i].part_table;
921 offset = ptes[i].offset;
922 }
923 p->boot_ind = 0;
924 p->sys_ind = sysid;
925 set_start_sect(p, start - offset);
926 set_nr_sects(p, stop - start + 1);
927 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
928 start = heads*sectors*1024 - 1;
929 set_hsc(p->head, p->sector, p->cyl, start);
930 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
931 stop = heads*sectors*1024 - 1;
932 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
933 ptes[i].changed = 1;
934}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000935#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000936
937static int
Rob Landleyb73451d2006-02-24 16:29:00 +0000938warn_geometry(void)
939{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000940 if (heads && sectors && cylinders)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000941 return 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000942
Denis Vlasenkobd852072007-03-19 14:43:38 +0000943 printf("Unknown value(s) for:");
944 if (!heads)
945 printf(" heads");
946 if (!sectors)
947 printf(" sectors");
948 if (!cylinders)
949 printf(" cylinders");
950 printf(
Denis Vlasenko834410a2006-11-29 12:00:28 +0000951#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenkobd852072007-03-19 14:43:38 +0000952 " (settable in the extra functions menu)"
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000953#endif
Denis Vlasenkobd852072007-03-19 14:43:38 +0000954 "\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000955 return 1;
956}
957
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000958static void
959update_units(void)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000960{
961 int cyl_units = heads * sectors;
962
963 if (display_in_cyl_units && cyl_units)
964 units_per_sector = cyl_units;
965 else
966 units_per_sector = 1; /* in sectors */
967}
968
Denis Vlasenko834410a2006-11-29 12:00:28 +0000969#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000970static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000971warn_cylinders(void)
972{
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000973 if (LABEL_IS_DOS && cylinders > 1024 && !nowarn)
Denis Vlasenkobd852072007-03-19 14:43:38 +0000974 printf("\n"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000975"The number of cylinders for this disk is set to %d.\n"
976"There is nothing wrong with that, but this is larger than 1024,\n"
977"and could in certain setups cause problems with:\n"
978"1) software that runs at boot time (e.g., old versions of LILO)\n"
979"2) booting and partitioning software from other OSs\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +0000980" (e.g., DOS FDISK, OS/2 FDISK)\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000981 cylinders);
982}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000983#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000984
985static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000986read_extended(int ext)
987{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000988 int i;
989 struct pte *pex;
990 struct partition *p, *q;
991
992 ext_index = ext;
993 pex = &ptes[ext];
994 pex->ext_pointer = pex->part_table;
995
996 p = pex->part_table;
997 if (!get_start_sect(p)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000998 printf("Bad offset in primary extended partition\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000999 return;
1000 }
1001
Rob Landleyb73451d2006-02-24 16:29:00 +00001002 while (IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001003 struct pte *pe = &ptes[partitions];
1004
1005 if (partitions >= MAXIMUM_PARTS) {
1006 /* This is not a Linux restriction, but
1007 this program uses arrays of size MAXIMUM_PARTS.
Denis Vlasenko89f0b342006-11-18 22:04:09 +00001008 Do not try to 'improve' this test. */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001009 struct pte *pre = &ptes[partitions-1];
Denis Vlasenko834410a2006-11-29 12:00:28 +00001010#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenkobd852072007-03-19 14:43:38 +00001011 printf("Warning: deleting partitions after %d\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001012 partitions);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001013 pre->changed = 1;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001014#endif
1015 clear_partition(pre->ext_pointer);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001016 return;
1017 }
1018
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001019 read_pte(pe, extended_offset + get_start_sect(p));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001020
1021 if (!extended_offset)
1022 extended_offset = get_start_sect(p);
1023
1024 q = p = pt_offset(pe->sectorbuffer, 0);
1025 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001026 if (IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001027 if (pe->ext_pointer)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001028 printf("Warning: extra link "
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001029 "pointer in partition table"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001030 " %d\n", partitions + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001031 else
1032 pe->ext_pointer = p;
1033 } else if (p->sys_ind) {
1034 if (pe->part_table)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001035 printf("Warning: ignoring extra "
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001036 "data in partition table"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001037 " %d\n", partitions + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001038 else
1039 pe->part_table = p;
1040 }
1041 }
1042
1043 /* very strange code here... */
1044 if (!pe->part_table) {
1045 if (q != pe->ext_pointer)
1046 pe->part_table = q;
1047 else
1048 pe->part_table = q + 1;
1049 }
1050 if (!pe->ext_pointer) {
1051 if (q != pe->part_table)
1052 pe->ext_pointer = q;
1053 else
1054 pe->ext_pointer = q + 1;
1055 }
1056
1057 p = pe->ext_pointer;
1058 partitions++;
1059 }
1060
Denis Vlasenko834410a2006-11-29 12:00:28 +00001061#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001062 /* remove empty links */
1063 remove:
1064 for (i = 4; i < partitions; i++) {
1065 struct pte *pe = &ptes[i];
1066
Denis Vlasenkobd852072007-03-19 14:43:38 +00001067 if (!get_nr_sects(pe->part_table)
1068 && (partitions > 5 || ptes[4].part_table->sys_ind)
1069 ) {
1070 printf("Omitting empty partition (%d)\n", i+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001071 delete_partition(i);
1072 goto remove; /* numbering changed */
1073 }
1074 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001075#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001076}
1077
Denis Vlasenko834410a2006-11-29 12:00:28 +00001078#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001079static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001080create_doslabel(void)
1081{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001082 int i;
1083
Denis Vlasenkobd852072007-03-19 14:43:38 +00001084 printf(msg_building_new_label, "DOS disklabel");
Rob Landley5527b912006-02-25 03:46:10 +00001085
1086 current_label_type = label_dos;
1087
Denis Vlasenko834410a2006-11-29 12:00:28 +00001088#if ENABLE_FEATURE_OSF_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001089 possibly_osf_label = 0;
1090#endif
1091 partitions = 4;
1092
1093 for (i = 510-64; i < 510; i++)
1094 MBRbuffer[i] = 0;
1095 write_part_table_flag(MBRbuffer);
1096 extended_offset = 0;
1097 set_all_unchanged();
1098 set_changed(0);
1099 get_boot(create_empty_dos);
1100}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001101#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001102
1103static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001104get_sectorsize(void)
1105{
Rob Landley736e5252006-02-25 03:36:00 +00001106 if (!user_set_sector_size) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001107 int arg;
1108 if (ioctl(fd, BLKSSZGET, &arg) == 0)
1109 sector_size = arg;
1110 if (sector_size != DEFAULT_SECTOR_SIZE)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001111 printf("Note: sector size is %d (not %d)\n",
Rob Landleyb73451d2006-02-24 16:29:00 +00001112 sector_size, DEFAULT_SECTOR_SIZE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001113 }
1114}
1115
Rob Landley88621d72006-08-29 19:41:06 +00001116static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001117get_kernel_geometry(void)
1118{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001119 struct hd_geometry geometry;
1120
1121 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
1122 kern_heads = geometry.heads;
1123 kern_sectors = geometry.sectors;
1124 /* never use geometry.cylinders - it is truncated */
1125 }
1126}
1127
1128static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001129get_partition_table_geometry(void)
1130{
"Vladimir N. Oleynik"a972c872005-12-02 10:06:04 +00001131 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001132 struct partition *p;
1133 int i, h, s, hh, ss;
1134 int first = 1;
1135 int bad = 0;
1136
Eric Andersen3496fdc2006-01-30 23:09:20 +00001137 if (!(valid_part_table_flag((char*)bufp)))
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001138 return;
1139
1140 hh = ss = 0;
Rob Landleyb73451d2006-02-24 16:29:00 +00001141 for (i = 0; i < 4; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001142 p = pt_offset(bufp, i);
1143 if (p->sys_ind != 0) {
1144 h = p->end_head + 1;
1145 s = (p->end_sector & 077);
1146 if (first) {
1147 hh = h;
1148 ss = s;
1149 first = 0;
1150 } else if (hh != h || ss != s)
1151 bad = 1;
1152 }
1153 }
1154
1155 if (!first && !bad) {
1156 pt_heads = hh;
1157 pt_sectors = ss;
1158 }
1159}
1160
Rob Landleyb73451d2006-02-24 16:29:00 +00001161static void
1162get_geometry(void)
1163{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001164 int sec_fac;
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001165 uint64_t v64;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001166
1167 get_sectorsize();
1168 sec_fac = sector_size / 512;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001169#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001170 guess_device_type();
1171#endif
1172 heads = cylinders = sectors = 0;
1173 kern_heads = kern_sectors = 0;
1174 pt_heads = pt_sectors = 0;
1175
1176 get_kernel_geometry();
1177 get_partition_table_geometry();
1178
1179 heads = user_heads ? user_heads :
1180 pt_heads ? pt_heads :
1181 kern_heads ? kern_heads : 255;
1182 sectors = user_sectors ? user_sectors :
1183 pt_sectors ? pt_sectors :
1184 kern_sectors ? kern_sectors : 63;
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001185 if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
1186 /* got bytes, convert to 512 byte sectors */
1187 total_number_of_sectors = (v64 >> 9);
Eric Andersen040f4402003-07-30 08:40:37 +00001188 } else {
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001189 unsigned long longsectors; /* need temp of type long */
1190 if (ioctl(fd, BLKGETSIZE, &longsectors))
1191 longsectors = 0;
1192 total_number_of_sectors = longsectors;
Eric Andersen040f4402003-07-30 08:40:37 +00001193 }
1194
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001195 sector_offset = 1;
1196 if (dos_compatible_flag)
1197 sector_offset = sectors;
1198
Eric Andersen040f4402003-07-30 08:40:37 +00001199 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001200 if (!cylinders)
1201 cylinders = user_cylinders;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001202}
1203
1204/*
1205 * Read MBR. Returns:
1206 * -1: no 0xaa55 flag present (possibly entire disk BSD)
1207 * 0: found or created label
1208 * 1: I/O error
1209 */
Rob Landleyb73451d2006-02-24 16:29:00 +00001210static int
1211get_boot(enum action what)
1212{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001213 int i;
1214
1215 partitions = 4;
1216
1217 for (i = 0; i < 4; i++) {
1218 struct pte *pe = &ptes[i];
1219
1220 pe->part_table = pt_offset(MBRbuffer, i);
1221 pe->ext_pointer = NULL;
1222 pe->offset = 0;
1223 pe->sectorbuffer = MBRbuffer;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001224#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001225 pe->changed = (what == create_empty_dos);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001226#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001227 }
1228
Denis Vlasenko834410a2006-11-29 12:00:28 +00001229#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001230 if (what == create_empty_sun && check_sun_label())
1231 return 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001232#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001233
1234 memset(MBRbuffer, 0, 512);
1235
Denis Vlasenko834410a2006-11-29 12:00:28 +00001236#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001237 if (what == create_empty_dos)
1238 goto got_dos_table; /* skip reading disk */
1239
Denis Vlasenkobd852072007-03-19 14:43:38 +00001240 fd = open(disk_device, type_open);
1241 if (fd < 0) {
1242 fd = open(disk_device, O_RDONLY);
1243 if (fd < 0) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001244 if (what == try_only)
1245 return 1;
1246 fdisk_fatal(unable_to_open);
1247 } else
Denis Vlasenkobd852072007-03-19 14:43:38 +00001248 printf("You will not be able to write "
1249 "the partition table\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001250 }
1251
1252 if (512 != read(fd, MBRbuffer, 512)) {
1253 if (what == try_only)
1254 return 1;
1255 fdisk_fatal(unable_to_read);
1256 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001257#else
Denis Vlasenkobd852072007-03-19 14:43:38 +00001258 fd = open(disk_device, O_RDONLY);
1259 if (fd < 0)
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001260 return 1;
1261 if (512 != read(fd, MBRbuffer, 512))
1262 return 1;
1263#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001264
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001265 get_geometry();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001266
1267 update_units();
1268
Denis Vlasenko834410a2006-11-29 12:00:28 +00001269#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001270 if (check_sun_label())
1271 return 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001272#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001273
Denis Vlasenko834410a2006-11-29 12:00:28 +00001274#if ENABLE_FEATURE_SGI_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001275 if (check_sgi_label())
1276 return 0;
1277#endif
1278
Denis Vlasenko834410a2006-11-29 12:00:28 +00001279#if ENABLE_FEATURE_AIX_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001280 if (check_aix_label())
1281 return 0;
1282#endif
1283
Denis Vlasenko834410a2006-11-29 12:00:28 +00001284#if ENABLE_FEATURE_OSF_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001285 if (check_osf_label()) {
1286 possibly_osf_label = 1;
1287 if (!valid_part_table_flag(MBRbuffer)) {
Rob Landley5527b912006-02-25 03:46:10 +00001288 current_label_type = label_osf;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001289 return 0;
1290 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001291 printf("This disk has both DOS and BSD magic.\n"
1292 "Give the 'b' command to go to BSD mode.\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001293 }
1294#endif
1295
Denis Vlasenko834410a2006-11-29 12:00:28 +00001296#if ENABLE_FEATURE_FDISK_WRITABLE
Rob Landleyb73451d2006-02-24 16:29:00 +00001297 got_dos_table:
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001298#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001299
1300 if (!valid_part_table_flag(MBRbuffer)) {
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001301#if !ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001302 return -1;
1303#else
Rob Landleyb73451d2006-02-24 16:29:00 +00001304 switch (what) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001305 case fdisk:
Denis Vlasenkobd852072007-03-19 14:43:38 +00001306 printf("Device contains neither a valid DOS "
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001307 "partition table, nor Sun, SGI or OSF "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001308 "disklabel\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001309#ifdef __sparc__
Denis Vlasenko834410a2006-11-29 12:00:28 +00001310#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001311 create_sunlabel();
1312#endif
1313#else
1314 create_doslabel();
1315#endif
1316 return 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001317 case try_only:
1318 return -1;
1319 case create_empty_dos:
Denis Vlasenko834410a2006-11-29 12:00:28 +00001320#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001321 case create_empty_sun:
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001322#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001323 break;
1324 default:
Denis Vlasenkobd852072007-03-19 14:43:38 +00001325 bb_error_msg_and_die("internal error");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001326 }
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001327#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001328 }
1329
Denis Vlasenko834410a2006-11-29 12:00:28 +00001330#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001331 warn_cylinders();
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001332#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001333 warn_geometry();
1334
1335 for (i = 0; i < 4; i++) {
1336 struct pte *pe = &ptes[i];
1337
Rob Landleyb73451d2006-02-24 16:29:00 +00001338 if (IS_EXTENDED(pe->part_table->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001339 if (partitions != 4)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001340 printf("Ignoring extra extended "
1341 "partition %d\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001342 else
1343 read_extended(i);
1344 }
1345 }
1346
1347 for (i = 3; i < partitions; i++) {
1348 struct pte *pe = &ptes[i];
1349
1350 if (!valid_part_table_flag(pe->sectorbuffer)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001351 printf("Warning: invalid flag 0x%02x,0x%02x of partition "
1352 "table %d will be corrected by w(rite)\n",
Denis Vlasenko834410a2006-11-29 12:00:28 +00001353 pe->sectorbuffer[510],
1354 pe->sectorbuffer[511],
1355 i + 1);
1356#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001357 pe->changed = 1;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001358#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001359 }
1360 }
1361
1362 return 0;
1363}
1364
Denis Vlasenko834410a2006-11-29 12:00:28 +00001365#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001366/*
1367 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
1368 * If the user hits Enter, DFLT is returned.
1369 * Answers like +10 are interpreted as offsets from BASE.
1370 *
1371 * There is no default if DFLT is not between LOW and HIGH.
1372 */
Denis Vlasenko834410a2006-11-29 12:00:28 +00001373static unsigned
Denis Vlasenko06c0a712007-01-29 22:51:44 +00001374read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001375{
Denis Vlasenko834410a2006-11-29 12:00:28 +00001376 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001377 int default_ok = 1;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001378 const char *fmt = "%s (%u-%u, default %u): ";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001379
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001380 if (dflt < low || dflt > high) {
1381 fmt = "%s (%u-%u): ";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001382 default_ok = 0;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001383 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001384
1385 while (1) {
1386 int use_default = default_ok;
1387
1388 /* ask question and read answer */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001389 do {
1390 printf(fmt, mesg, low, high, dflt);
1391 read_maybe_empty("");
1392 } while (*line_ptr != '\n' && !isdigit(*line_ptr)
1393 && *line_ptr != '-' && *line_ptr != '+');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001394
Eric Andersen84bdea82004-05-19 10:49:17 +00001395 if (*line_ptr == '+' || *line_ptr == '-') {
Rob Landleyb73451d2006-02-24 16:29:00 +00001396 int minus = (*line_ptr == '-');
1397 int absolute = 0;
Eric Andersenc48d49a2003-07-03 10:02:32 +00001398
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001399 i = atoi(line_ptr + 1);
Eric Andersenc48d49a2003-07-03 10:02:32 +00001400
Rob Landleyb73451d2006-02-24 16:29:00 +00001401 while (isdigit(*++line_ptr))
1402 use_default = 0;
Eric Andersen84bdea82004-05-19 10:49:17 +00001403
Rob Landleyb73451d2006-02-24 16:29:00 +00001404 switch (*line_ptr) {
1405 case 'c':
1406 case 'C':
1407 if (!display_in_cyl_units)
1408 i *= heads * sectors;
1409 break;
1410 case 'K':
1411 absolute = 1024;
1412 break;
1413 case 'k':
1414 absolute = 1000;
1415 break;
1416 case 'm':
1417 case 'M':
1418 absolute = 1000000;
1419 break;
1420 case 'g':
1421 case 'G':
1422 absolute = 1000000000;
1423 break;
1424 default:
1425 break;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001426 }
Rob Landleyb73451d2006-02-24 16:29:00 +00001427 if (absolute) {
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001428 ullong bytes;
Rob Landleyb73451d2006-02-24 16:29:00 +00001429 unsigned long unit;
1430
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001431 bytes = (ullong) i * absolute;
Rob Landleyb73451d2006-02-24 16:29:00 +00001432 unit = sector_size * units_per_sector;
1433 bytes += unit/2; /* round */
1434 bytes /= unit;
1435 i = bytes;
1436 }
1437 if (minus)
1438 i = -i;
1439 i += base;
Eric Andersen84bdea82004-05-19 10:49:17 +00001440 } else {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001441 i = atoi(line_ptr);
1442 while (isdigit(*line_ptr)) {
1443 line_ptr++;
1444 use_default = 0;
1445 }
1446 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001447 if (use_default) {
1448 i = dflt;
1449 printf("Using default value %u\n", i);
1450 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001451 if (i >= low && i <= high)
1452 break;
Denis Vlasenkobd852072007-03-19 14:43:38 +00001453 printf("Value is out of range\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001454 }
1455 return i;
1456}
1457
Rob Landleyb73451d2006-02-24 16:29:00 +00001458static int
1459get_partition(int warn, int max)
1460{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001461 struct pte *pe;
1462 int i;
1463
Denis Vlasenkobd852072007-03-19 14:43:38 +00001464 i = read_int(1, 0, max, 0, "Partition number") - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001465 pe = &ptes[i];
1466
1467 if (warn) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001468 if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind)
1469 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
1470 || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
1471 ) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001472 printf("Warning: partition %d has empty type\n", i+1);
Rob Landley5527b912006-02-25 03:46:10 +00001473 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001474 }
1475 return i;
1476}
1477
1478static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001479get_existing_partition(int warn, int max)
1480{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001481 int pno = -1;
1482 int i;
1483
1484 for (i = 0; i < max; i++) {
1485 struct pte *pe = &ptes[i];
1486 struct partition *p = pe->part_table;
1487
1488 if (p && !is_cleared_partition(p)) {
1489 if (pno >= 0)
1490 goto not_unique;
1491 pno = i;
1492 }
1493 }
1494 if (pno >= 0) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001495 printf("Selected partition %d\n", pno+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001496 return pno;
1497 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001498 printf("No partition is defined yet!\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001499 return -1;
1500
1501 not_unique:
1502 return get_partition(warn, max);
1503}
1504
1505static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001506get_nonexisting_partition(int warn, int max)
1507{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001508 int pno = -1;
1509 int i;
1510
1511 for (i = 0; i < max; i++) {
1512 struct pte *pe = &ptes[i];
1513 struct partition *p = pe->part_table;
1514
1515 if (p && is_cleared_partition(p)) {
1516 if (pno >= 0)
1517 goto not_unique;
1518 pno = i;
1519 }
1520 }
1521 if (pno >= 0) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001522 printf("Selected partition %d\n", pno+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001523 return pno;
1524 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001525 printf("All primary partitions have been defined already!\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001526 return -1;
1527
1528 not_unique:
1529 return get_partition(warn, max);
1530}
1531
1532
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001533static void
1534change_units(void)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001535{
1536 display_in_cyl_units = !display_in_cyl_units;
1537 update_units();
Denis Vlasenkobd852072007-03-19 14:43:38 +00001538 printf("Changing display/entry units to %s\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001539 str_units(PLURAL));
1540}
1541
1542static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001543toggle_active(int i)
1544{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001545 struct pte *pe = &ptes[i];
1546 struct partition *p = pe->part_table;
1547
Rob Landleyb73451d2006-02-24 16:29:00 +00001548 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001549 printf("WARNING: Partition %d is an extended partition\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001550 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1551 pe->changed = 1;
1552}
1553
1554static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001555toggle_dos_compatibility_flag(void)
1556{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001557 dos_compatible_flag = ~dos_compatible_flag;
1558 if (dos_compatible_flag) {
1559 sector_offset = sectors;
Denis Vlasenkobd852072007-03-19 14:43:38 +00001560 printf("DOS Compatibility flag is set\n");
1561 } else {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001562 sector_offset = 1;
Denis Vlasenkobd852072007-03-19 14:43:38 +00001563 printf("DOS Compatibility flag is not set\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001564 }
1565}
1566
1567static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001568delete_partition(int i)
1569{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001570 struct pte *pe = &ptes[i];
1571 struct partition *p = pe->part_table;
1572 struct partition *q = pe->ext_pointer;
1573
1574/* Note that for the fifth partition (i == 4) we don't actually
1575 * decrement partitions.
1576 */
1577
1578 if (warn_geometry())
1579 return; /* C/H/S not set */
1580 pe->changed = 1;
1581
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001582 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001583 sun_delete_partition(i);
1584 return;
1585 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001586 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001587 sgi_delete_partition(i);
1588 return;
1589 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001590
1591 if (i < 4) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001592 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001593 partitions = 4;
1594 ptes[ext_index].ext_pointer = NULL;
1595 extended_offset = 0;
1596 }
1597 clear_partition(p);
1598 return;
1599 }
1600
1601 if (!q->sys_ind && i > 4) {
1602 /* the last one in the chain - just delete */
1603 --partitions;
1604 --i;
1605 clear_partition(ptes[i].ext_pointer);
1606 ptes[i].changed = 1;
1607 } else {
1608 /* not the last one - further ones will be moved down */
1609 if (i > 4) {
1610 /* delete this link in the chain */
1611 p = ptes[i-1].ext_pointer;
1612 *p = *q;
1613 set_start_sect(p, get_start_sect(q));
1614 set_nr_sects(p, get_nr_sects(q));
1615 ptes[i-1].changed = 1;
1616 } else if (partitions > 5) { /* 5 will be moved to 4 */
1617 /* the first logical in a longer chain */
1618 pe = &ptes[5];
1619
1620 if (pe->part_table) /* prevent SEGFAULT */
1621 set_start_sect(pe->part_table,
Rob Landleyb73451d2006-02-24 16:29:00 +00001622 get_partition_start(pe) -
1623 extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001624 pe->offset = extended_offset;
1625 pe->changed = 1;
1626 }
1627
1628 if (partitions > 5) {
1629 partitions--;
1630 while (i < partitions) {
1631 ptes[i] = ptes[i+1];
1632 i++;
1633 }
1634 } else
1635 /* the only logical: clear only */
1636 clear_partition(ptes[i].part_table);
1637 }
1638}
1639
1640static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001641change_sysid(void)
1642{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001643 int i, sys, origsys;
1644 struct partition *p;
1645
Eric Andersen040f4402003-07-30 08:40:37 +00001646 /* If sgi_label then don't use get_existing_partition,
1647 let the user select a partition, since get_existing_partition()
1648 only works for Linux like partition tables. */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001649 if (!LABEL_IS_SGI) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001650 i = get_existing_partition(0, partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00001651 } else {
1652 i = get_partition(0, partitions);
1653 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001654 if (i == -1)
1655 return;
1656 p = ptes[i].part_table;
1657 origsys = sys = get_sysid(i);
1658
1659 /* if changing types T to 0 is allowed, then
1660 the reverse change must be allowed, too */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001661 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001662 printf("Partition %d does not exist yet!\n", i + 1);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001663 return;
1664 }
1665 while (1) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001666 sys = read_hex(get_sys_types());
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001667
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001668 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001669 printf("Type 0 means free space to many systems\n"
Rob Landleyb73451d2006-02-24 16:29:00 +00001670 "(but not to Linux). Having partitions of\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001671 "type 0 is probably unwise.\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001672 /* break; */
1673 }
1674
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001675 if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001676 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001677 printf("You cannot change a partition into"
1678 " an extended one or vice versa\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001679 break;
1680 }
1681 }
1682
1683 if (sys < 256) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001684#if ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001685 if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001686 printf("Consider leaving partition 3 "
Rob Landleyb73451d2006-02-24 16:29:00 +00001687 "as Whole disk (5),\n"
1688 "as SunOS/Solaris expects it and "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001689 "even Linux likes it\n\n");
1690#endif
1691#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001692 if (LABEL_IS_SGI &&
Rob Landley5527b912006-02-25 03:46:10 +00001693 (
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001694 (i == 10 && sys != SGI_ENTIRE_DISK) ||
Rob Landley5527b912006-02-25 03:46:10 +00001695 (i == 8 && sys != 0)
1696 )
Denis Vlasenkobd852072007-03-19 14:43:38 +00001697 ) {
1698 printf("Consider leaving partition 9 "
Rob Landleyb73451d2006-02-24 16:29:00 +00001699 "as volume header (0),\nand "
1700 "partition 11 as entire volume (6)"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001701 "as IRIX expects it\n\n");
Rob Landley5527b912006-02-25 03:46:10 +00001702 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001703#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001704 if (sys == origsys)
1705 break;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001706 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001707 sun_change_sysid(i, sys);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001708 } else if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001709 sgi_change_sysid(i, sys);
1710 } else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001711 p->sys_ind = sys;
Rob Landley5527b912006-02-25 03:46:10 +00001712
Denis Vlasenkobd852072007-03-19 14:43:38 +00001713 printf("Changed system type of partition %d "
1714 "to %x (%s)\n", i + 1, sys,
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001715 partition_type(sys));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001716 ptes[i].changed = 1;
1717 if (is_dos_partition(origsys) ||
Rob Landleyb73451d2006-02-24 16:29:00 +00001718 is_dos_partition(sys))
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001719 dos_changed = 1;
1720 break;
1721 }
1722 }
1723}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001724#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001725
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001726
Denis Vlasenko28703012006-12-19 20:32:02 +00001727/* check_consistency() and linear2chs() added Sat Mar 6 12:28:16 1993,
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001728 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1729 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1730 * Lubkin Oct. 1991). */
1731
Rob Landleyb73451d2006-02-24 16:29:00 +00001732static void
Denis Vlasenko28703012006-12-19 20:32:02 +00001733linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
Rob Landleyb73451d2006-02-24 16:29:00 +00001734{
1735 int spc = heads * sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001736
1737 *c = ls / spc;
1738 ls = ls % spc;
1739 *h = ls / sectors;
1740 *s = ls % sectors + 1; /* sectors count from 1 */
1741}
1742
Rob Landleyb73451d2006-02-24 16:29:00 +00001743static void
1744check_consistency(const struct partition *p, int partition)
1745{
Denis Vlasenko834410a2006-11-29 12:00:28 +00001746 unsigned pbc, pbh, pbs; /* physical beginning c, h, s */
1747 unsigned pec, peh, pes; /* physical ending c, h, s */
1748 unsigned lbc, lbh, lbs; /* logical beginning c, h, s */
1749 unsigned lec, leh, les; /* logical ending c, h, s */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001750
1751 if (!heads || !sectors || (partition >= 4))
1752 return; /* do not check extended partitions */
1753
1754/* physical beginning c, h, s */
1755 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
1756 pbh = p->head;
1757 pbs = p->sector & 0x3f;
1758
1759/* physical ending c, h, s */
1760 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
1761 peh = p->end_head;
1762 pes = p->end_sector & 0x3f;
1763
1764/* compute logical beginning (c, h, s) */
Denis Vlasenko28703012006-12-19 20:32:02 +00001765 linear2chs(get_start_sect(p), &lbc, &lbh, &lbs);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001766
1767/* compute logical ending (c, h, s) */
Denis Vlasenko28703012006-12-19 20:32:02 +00001768 linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001769
1770/* Same physical / logical beginning? */
1771 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001772 printf("Partition %d has different physical/logical "
1773 "beginnings (non-Linux?):\n", partition + 1);
1774 printf(" phys=(%d, %d, %d) ", pbc, pbh, pbs);
1775 printf("logical=(%d, %d, %d)\n",lbc, lbh, lbs);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001776 }
1777
1778/* Same physical / logical ending? */
1779 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001780 printf("Partition %d has different physical/logical "
1781 "endings:\n", partition + 1);
1782 printf(" phys=(%d, %d, %d) ", pec, peh, pes);
1783 printf("logical=(%d, %d, %d)\n", lec, leh, les);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001784 }
1785
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001786/* Ending on cylinder boundary? */
1787 if (peh != (heads - 1) || pes != sectors) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001788 printf("Partition %i does not end on cylinder boundary\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001789 partition + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001790 }
1791}
1792
1793static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001794list_disk_geometry(void)
1795{
Eric Andersen040f4402003-07-30 08:40:37 +00001796 long long bytes = (total_number_of_sectors << 9);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001797 long megabytes = bytes/1000000;
1798
1799 if (megabytes < 10000)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001800 printf("\nDisk %s: %ld MB, %lld bytes\n",
Rob Landleyb73451d2006-02-24 16:29:00 +00001801 disk_device, megabytes, bytes);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001802 else
Denis Vlasenkobd852072007-03-19 14:43:38 +00001803 printf("\nDisk %s: %ld.%ld GB, %lld bytes\n",
Rob Landleyb73451d2006-02-24 16:29:00 +00001804 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
Denis Vlasenkobd852072007-03-19 14:43:38 +00001805 printf("%d heads, %d sectors/track, %d cylinders",
Rob Landleyb73451d2006-02-24 16:29:00 +00001806 heads, sectors, cylinders);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001807 if (units_per_sector == 1)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001808 printf(", total %llu sectors",
Rob Landleyb73451d2006-02-24 16:29:00 +00001809 total_number_of_sectors / (sector_size/512));
Denis Vlasenkobd852072007-03-19 14:43:38 +00001810 printf("\nUnits = %s of %d * %d = %d bytes\n\n",
Rob Landleyb73451d2006-02-24 16:29:00 +00001811 str_units(PLURAL),
1812 units_per_sector, sector_size, units_per_sector * sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001813}
1814
1815/*
1816 * Check whether partition entries are ordered by their starting positions.
1817 * Return 0 if OK. Return i if partition i should have been earlier.
1818 * Two separate checks: primary and logical partitions.
1819 */
1820static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001821wrong_p_order(int *prev)
1822{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001823 const struct pte *pe;
1824 const struct partition *p;
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001825 ullong last_p_start_pos = 0, p_start_pos;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001826 int i, last_i = 0;
1827
1828 for (i = 0 ; i < partitions; i++) {
1829 if (i == 4) {
1830 last_i = 4;
1831 last_p_start_pos = 0;
1832 }
1833 pe = &ptes[i];
1834 if ((p = pe->part_table)->sys_ind) {
1835 p_start_pos = get_partition_start(pe);
1836
1837 if (last_p_start_pos > p_start_pos) {
1838 if (prev)
1839 *prev = last_i;
1840 return i;
1841 }
1842
1843 last_p_start_pos = p_start_pos;
1844 last_i = i;
1845 }
1846 }
1847 return 0;
1848}
1849
Denis Vlasenko834410a2006-11-29 12:00:28 +00001850#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001851/*
1852 * Fix the chain of logicals.
1853 * extended_offset is unchanged, the set of sectors used is unchanged
1854 * The chain is sorted so that sectors increase, and so that
1855 * starting sectors increase.
1856 *
1857 * After this it may still be that cfdisk doesnt like the table.
1858 * (This is because cfdisk considers expanded parts, from link to
1859 * end of partition, and these may still overlap.)
1860 * Now
1861 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
1862 * may help.
1863 */
1864static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001865fix_chain_of_logicals(void)
1866{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001867 int j, oj, ojj, sj, sjj;
1868 struct partition *pj,*pjj,tmp;
1869
1870 /* Stage 1: sort sectors but leave sector of part 4 */
1871 /* (Its sector is the global extended_offset.) */
1872 stage1:
1873 for (j = 5; j < partitions-1; j++) {
1874 oj = ptes[j].offset;
1875 ojj = ptes[j+1].offset;
1876 if (oj > ojj) {
1877 ptes[j].offset = ojj;
1878 ptes[j+1].offset = oj;
1879 pj = ptes[j].part_table;
1880 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
1881 pjj = ptes[j+1].part_table;
1882 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
1883 set_start_sect(ptes[j-1].ext_pointer,
Rob Landleyb73451d2006-02-24 16:29:00 +00001884 ojj-extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001885 set_start_sect(ptes[j].ext_pointer,
Rob Landleyb73451d2006-02-24 16:29:00 +00001886 oj-extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001887 goto stage1;
1888 }
1889 }
1890
1891 /* Stage 2: sort starting sectors */
1892 stage2:
1893 for (j = 4; j < partitions-1; j++) {
1894 pj = ptes[j].part_table;
1895 pjj = ptes[j+1].part_table;
1896 sj = get_start_sect(pj);
1897 sjj = get_start_sect(pjj);
1898 oj = ptes[j].offset;
1899 ojj = ptes[j+1].offset;
1900 if (oj+sj > ojj+sjj) {
1901 tmp = *pj;
1902 *pj = *pjj;
1903 *pjj = tmp;
1904 set_start_sect(pj, ojj+sjj-oj);
1905 set_start_sect(pjj, oj+sj-ojj);
1906 goto stage2;
1907 }
1908 }
1909
1910 /* Probably something was changed */
1911 for (j = 4; j < partitions; j++)
1912 ptes[j].changed = 1;
1913}
1914
1915
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001916static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001917fix_partition_table_order(void)
1918{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001919 struct pte *pei, *pek;
1920 int i,k;
1921
1922 if (!wrong_p_order(NULL)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001923 printf("Ordering is already correct\n\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001924 return;
1925 }
1926
1927 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
1928 /* partition i should have come earlier, move it */
1929 /* We have to move data in the MBR */
1930 struct partition *pi, *pk, *pe, pbuf;
1931 pei = &ptes[i];
1932 pek = &ptes[k];
1933
1934 pe = pei->ext_pointer;
1935 pei->ext_pointer = pek->ext_pointer;
1936 pek->ext_pointer = pe;
1937
1938 pi = pei->part_table;
1939 pk = pek->part_table;
1940
1941 memmove(&pbuf, pi, sizeof(struct partition));
1942 memmove(pi, pk, sizeof(struct partition));
1943 memmove(pk, &pbuf, sizeof(struct partition));
1944
1945 pei->changed = pek->changed = 1;
1946 }
1947
1948 if (i)
1949 fix_chain_of_logicals();
1950
1951 printf("Done.\n");
1952
1953}
1954#endif
1955
1956static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001957list_table(int xtra)
1958{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001959 const struct partition *p;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001960 int i, w;
1961
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001962 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001963 sun_list_table(xtra);
1964 return;
1965 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001966 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001967 sgi_list_table(xtra);
1968 return;
1969 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001970
1971 list_disk_geometry();
1972
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001973 if (LABEL_IS_OSF) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001974 xbsd_print_disklabel(xtra);
1975 return;
1976 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001977
1978 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
1979 but if the device name ends in a digit, say /dev/foo1,
1980 then the partition is called /dev/foo1p3. */
1981 w = strlen(disk_device);
1982 if (w && isdigit(disk_device[w-1]))
1983 w++;
1984 if (w < 5)
1985 w = 5;
1986
Denis Vlasenkobd852072007-03-19 14:43:38 +00001987 // 1 12345678901 12345678901 12345678901 12
1988 printf("%*s Boot Start End Blocks Id System\n",
1989 w+1, "Device");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001990
1991 for (i = 0; i < partitions; i++) {
1992 const struct pte *pe = &ptes[i];
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001993 ullong psects;
1994 ullong pblocks;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001995 unsigned podd;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001996
1997 p = pe->part_table;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001998 if (!p || is_cleared_partition(p))
1999 continue;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002000
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002001 psects = get_nr_sects(p);
2002 pblocks = psects;
2003 podd = 0;
2004
2005 if (sector_size < 1024) {
2006 pblocks /= (1024 / sector_size);
2007 podd = psects % (1024 / sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002008 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002009 if (sector_size > 1024)
2010 pblocks *= (sector_size / 1024);
2011
2012 printf("%s %c %11llu %11llu %11llu%c %2x %s\n",
2013 partname(disk_device, i+1, w+2),
2014 !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
2015 ? '*' : '?',
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002016 (ullong) cround(get_partition_start(pe)), /* start */
2017 (ullong) cround(get_partition_start(pe) + psects /* end */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002018 - (psects ? 1 : 0)),
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002019 (ullong) pblocks, podd ? '+' : ' ', /* odd flag on end */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002020 p->sys_ind, /* type id */
2021 partition_type(p->sys_ind)); /* type name */
2022
2023 check_consistency(p, i);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002024 }
2025
2026 /* Is partition table in disk order? It need not be, but... */
2027 /* partition table entries are not checked for correct order if this
2028 is a sgi, sun or aix labeled disk... */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002029 if (LABEL_IS_DOS && wrong_p_order(NULL)) {
Rob Landley5527b912006-02-25 03:46:10 +00002030 /* FIXME */
Denis Vlasenkobd852072007-03-19 14:43:38 +00002031 printf("\nPartition table entries are not in disk order\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002032 }
2033}
2034
Denis Vlasenko834410a2006-11-29 12:00:28 +00002035#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002036static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002037x_list_table(int extend)
2038{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002039 const struct pte *pe;
2040 const struct partition *p;
2041 int i;
2042
Denis Vlasenkobd852072007-03-19 14:43:38 +00002043 printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002044 disk_device, heads, sectors, cylinders);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002045 printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002046 for (i = 0 ; i < partitions; i++) {
2047 pe = &ptes[i];
2048 p = (extend ? pe->ext_pointer : pe->part_table);
2049 if (p != NULL) {
Eric Andersen040f4402003-07-30 08:40:37 +00002050 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002051 i + 1, p->boot_ind, p->head,
2052 sector(p->sector),
2053 cylinder(p->sector, p->cyl), p->end_head,
2054 sector(p->end_sector),
2055 cylinder(p->end_sector, p->end_cyl),
2056 get_start_sect(p), get_nr_sects(p), p->sys_ind);
2057 if (p->sys_ind)
2058 check_consistency(p, i);
2059 }
2060 }
2061}
2062#endif
2063
Denis Vlasenko834410a2006-11-29 12:00:28 +00002064#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002065static void
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002066fill_bounds(ullong *first, ullong *last)
Rob Landleyb73451d2006-02-24 16:29:00 +00002067{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002068 int i;
2069 const struct pte *pe = &ptes[0];
2070 const struct partition *p;
2071
2072 for (i = 0; i < partitions; pe++,i++) {
2073 p = pe->part_table;
Rob Landleyb73451d2006-02-24 16:29:00 +00002074 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002075 first[i] = 0xffffffff;
2076 last[i] = 0;
2077 } else {
2078 first[i] = get_partition_start(pe);
2079 last[i] = first[i] + get_nr_sects(p) - 1;
2080 }
2081 }
2082}
2083
2084static void
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002085check(int n, unsigned h, unsigned s, unsigned c, ullong start)
Rob Landleyb73451d2006-02-24 16:29:00 +00002086{
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002087 ullong total, real_s, real_c;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002088
2089 real_s = sector(s) - 1;
2090 real_c = cylinder(s, c);
2091 total = (real_c * sectors + real_s) * heads + h;
2092 if (!total)
Denis Vlasenkobd852072007-03-19 14:43:38 +00002093 printf("Partition %d contains sector 0\n", n);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002094 if (h >= heads)
Denis Vlasenkobd852072007-03-19 14:43:38 +00002095 printf("Partition %d: head %d greater than maximum %d\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002096 n, h + 1, heads);
2097 if (real_s >= sectors)
Denis Vlasenkobd852072007-03-19 14:43:38 +00002098 printf("Partition %d: sector %d greater than "
2099 "maximum %d\n", n, s, sectors);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002100 if (real_c >= cylinders)
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002101 printf("Partition %d: cylinder %llu greater than "
Denis Vlasenkobd852072007-03-19 14:43:38 +00002102 "maximum %d\n", n, real_c + 1, cylinders);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002103 if (cylinders <= 1024 && start != total)
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002104 printf("Partition %d: previous sectors %llu disagrees with "
2105 "total %llu\n", n, start, total);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002106}
2107
2108static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002109verify(void)
2110{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002111 int i, j;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002112 unsigned total = 1;
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002113 ullong first[partitions], last[partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002114 struct partition *p;
2115
2116 if (warn_geometry())
2117 return;
2118
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002119 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002120 verify_sun();
2121 return;
2122 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002123 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002124 verify_sgi(1);
2125 return;
2126 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002127
2128 fill_bounds(first, last);
2129 for (i = 0; i < partitions; i++) {
2130 struct pte *pe = &ptes[i];
2131
2132 p = pe->part_table;
Rob Landleyb73451d2006-02-24 16:29:00 +00002133 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002134 check_consistency(p, i);
2135 if (get_partition_start(pe) < first[i])
Denis Vlasenkobd852072007-03-19 14:43:38 +00002136 printf("Warning: bad start-of-data in "
2137 "partition %d\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002138 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
2139 last[i]);
2140 total += last[i] + 1 - first[i];
Denis Vlasenkobd852072007-03-19 14:43:38 +00002141 for (j = 0; j < i; j++) {
2142 if ((first[i] >= first[j] && first[i] <= last[j])
2143 || ((last[i] <= last[j] && last[i] >= first[j]))) {
2144 printf("Warning: partition %d overlaps "
2145 "partition %d\n", j + 1, i + 1);
2146 total += first[i] >= first[j] ?
2147 first[i] : first[j];
2148 total -= last[i] <= last[j] ?
2149 last[i] : last[j];
2150 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002151 }
2152 }
2153 }
2154
2155 if (extended_offset) {
2156 struct pte *pex = &ptes[ext_index];
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002157 ullong e_last = get_start_sect(pex->part_table) +
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002158 get_nr_sects(pex->part_table) - 1;
2159
2160 for (i = 4; i < partitions; i++) {
2161 total++;
2162 p = ptes[i].part_table;
2163 if (!p->sys_ind) {
2164 if (i != 4 || i + 1 < partitions)
Denis Vlasenkobd852072007-03-19 14:43:38 +00002165 printf("Warning: partition %d "
2166 "is empty\n", i + 1);
2167 } else if (first[i] < extended_offset || last[i] > e_last) {
2168 printf("Logical partition %d not entirely in "
2169 "partition %d\n", i + 1, ext_index + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002170 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002171 }
2172 }
2173
2174 if (total > heads * sectors * cylinders)
Denis Vlasenkobd852072007-03-19 14:43:38 +00002175 printf("Total allocated sectors %d greater than the maximum "
2176 "%d\n", total, heads * sectors * cylinders);
2177 else {
2178 total = heads * sectors * cylinders - total;
2179 if (total != 0)
2180 printf("%d unallocated sectors\n", total);
2181 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002182}
2183
2184static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002185add_partition(int n, int sys)
2186{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002187 char mesg[256]; /* 48 does not suffice in Japanese */
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002188 int i, num_read = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002189 struct partition *p = ptes[n].part_table;
2190 struct partition *q = ptes[ext_index].part_table;
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002191 ullong limit, temp;
2192 ullong start, stop = 0;
2193 ullong first[partitions], last[partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002194
2195 if (p && p->sys_ind) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002196 printf(msg_part_already_defined, n + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002197 return;
2198 }
2199 fill_bounds(first, last);
2200 if (n < 4) {
2201 start = sector_offset;
Eric Andersen040f4402003-07-30 08:40:37 +00002202 if (display_in_cyl_units || !total_number_of_sectors)
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002203 limit = (ullong) heads * sectors * cylinders - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002204 else
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002205 limit = total_number_of_sectors - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002206 if (extended_offset) {
2207 first[ext_index] = extended_offset;
2208 last[ext_index] = get_start_sect(q) +
2209 get_nr_sects(q) - 1;
2210 }
2211 } else {
2212 start = extended_offset + sector_offset;
2213 limit = get_start_sect(q) + get_nr_sects(q) - 1;
2214 }
2215 if (display_in_cyl_units)
2216 for (i = 0; i < partitions; i++)
2217 first[i] = (cround(first[i]) - 1) * units_per_sector;
2218
Denis Vlasenkobd852072007-03-19 14:43:38 +00002219 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002220 do {
2221 temp = start;
2222 for (i = 0; i < partitions; i++) {
2223 int lastplusoff;
2224
2225 if (start == ptes[i].offset)
2226 start += sector_offset;
Rob Landleyb73451d2006-02-24 16:29:00 +00002227 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002228 if (start >= first[i] && start <= lastplusoff)
2229 start = lastplusoff + 1;
2230 }
2231 if (start > limit)
2232 break;
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002233 if (start >= temp+units_per_sector && num_read) {
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002234 printf("Sector %lld is already allocated\n", temp);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002235 temp = start;
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002236 num_read = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002237 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002238 if (!num_read && start == temp) {
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002239 ullong saved_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002240
2241 saved_start = start;
2242 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
2243 0, mesg);
2244 if (display_in_cyl_units) {
2245 start = (start - 1) * units_per_sector;
2246 if (start < saved_start) start = saved_start;
2247 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002248 num_read = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002249 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002250 } while (start != temp || !num_read);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002251 if (n > 4) { /* NOT for fifth partition */
2252 struct pte *pe = &ptes[n];
2253
2254 pe->offset = start - sector_offset;
2255 if (pe->offset == extended_offset) { /* must be corrected */
2256 pe->offset++;
2257 if (sector_offset == 1)
2258 start++;
2259 }
2260 }
2261
2262 for (i = 0; i < partitions; i++) {
2263 struct pte *pe = &ptes[i];
2264
2265 if (start < pe->offset && limit >= pe->offset)
2266 limit = pe->offset - 1;
2267 if (start < first[i] && limit >= first[i])
2268 limit = first[i] - 1;
2269 }
2270 if (start > limit) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002271 printf("No free sectors available\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002272 if (n > 4)
2273 partitions--;
2274 return;
2275 }
2276 if (cround(start) == cround(limit)) {
2277 stop = limit;
2278 } else {
2279 snprintf(mesg, sizeof(mesg),
Denis Vlasenkobd852072007-03-19 14:43:38 +00002280 "Last %s or +size or +sizeM or +sizeK",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002281 str_units(SINGULAR));
2282 stop = read_int(cround(start), cround(limit), cround(limit),
2283 cround(start), mesg);
2284 if (display_in_cyl_units) {
2285 stop = stop * units_per_sector - 1;
2286 if (stop >limit)
2287 stop = limit;
2288 }
2289 }
2290
2291 set_partition(n, 0, start, stop, sys);
2292 if (n > 4)
2293 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
2294
Rob Landleyb73451d2006-02-24 16:29:00 +00002295 if (IS_EXTENDED(sys)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002296 struct pte *pe4 = &ptes[4];
2297 struct pte *pen = &ptes[n];
2298
2299 ext_index = n;
2300 pen->ext_pointer = p;
2301 pe4->offset = extended_offset = start;
Rob Landley081e3842006-08-03 20:07:35 +00002302 pe4->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002303 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2304 pe4->ext_pointer = pe4->part_table + 1;
2305 pe4->changed = 1;
2306 partitions = 5;
2307 }
2308}
2309
2310static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002311add_logical(void)
2312{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002313 if (partitions > 5 || ptes[4].part_table->sys_ind) {
2314 struct pte *pe = &ptes[partitions];
2315
Rob Landley081e3842006-08-03 20:07:35 +00002316 pe->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002317 pe->part_table = pt_offset(pe->sectorbuffer, 0);
2318 pe->ext_pointer = pe->part_table + 1;
2319 pe->offset = 0;
2320 pe->changed = 1;
2321 partitions++;
2322 }
2323 add_partition(partitions - 1, LINUX_NATIVE);
2324}
2325
2326static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002327new_partition(void)
2328{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002329 int i, free_primary = 0;
2330
2331 if (warn_geometry())
2332 return;
2333
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002334 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002335 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
2336 return;
2337 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002338 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002339 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
2340 return;
2341 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002342 if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002343 printf("Sorry - this fdisk cannot handle AIX disk labels.\n"
2344"If you want to add DOS-type partitions, create a new empty DOS partition\n"
2345"table first (use 'o'). This will destroy the present disk contents.\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002346 return;
2347 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002348
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002349 for (i = 0; i < 4; i++)
2350 free_primary += !ptes[i].part_table->sys_ind;
Eric Andersenc48d49a2003-07-03 10:02:32 +00002351
Rob Landleyb73451d2006-02-24 16:29:00 +00002352 if (!free_primary && partitions >= MAXIMUM_PARTS) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002353 printf("The maximum number of partitions has been created\n");
Eric Andersen84bdea82004-05-19 10:49:17 +00002354 return;
Rob Landleyb73451d2006-02-24 16:29:00 +00002355 }
Eric Andersenc48d49a2003-07-03 10:02:32 +00002356
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002357 if (!free_primary) {
2358 if (extended_offset)
2359 add_logical();
2360 else
Denis Vlasenkobd852072007-03-19 14:43:38 +00002361 printf("You must delete some partition and add "
2362 "an extended partition first\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002363 } else {
Denis Vlasenkodfce08f2007-03-19 14:45:10 +00002364 char c, line[80];
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00002365 snprintf(line, sizeof(line),
2366 "Command action\n"
2367 " %s\n"
2368 " p primary partition (1-4)\n",
2369 (extended_offset ?
2370 "l logical (5 or over)" : "e extended"));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002371 while (1) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002372 c = read_nonempty(line);
2373 if (c == 'p' || c == 'P') {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002374 i = get_nonexisting_partition(0, 4);
2375 if (i >= 0)
2376 add_partition(i, LINUX_NATIVE);
2377 return;
2378 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002379 if (c == 'l' && extended_offset) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002380 add_logical();
2381 return;
2382 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002383 if (c == 'e' && !extended_offset) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002384 i = get_nonexisting_partition(0, 4);
2385 if (i >= 0)
2386 add_partition(i, EXTENDED);
2387 return;
2388 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002389 printf("Invalid partition number "
2390 "for type '%c'\n", c);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002391 }
2392 }
2393}
2394
2395static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002396write_table(void)
2397{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002398 int i;
2399
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002400 if (LABEL_IS_DOS) {
Rob Landleyb73451d2006-02-24 16:29:00 +00002401 for (i = 0; i < 3; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002402 if (ptes[i].changed)
2403 ptes[3].changed = 1;
2404 for (i = 3; i < partitions; i++) {
2405 struct pte *pe = &ptes[i];
2406
2407 if (pe->changed) {
2408 write_part_table_flag(pe->sectorbuffer);
2409 write_sector(pe->offset, pe->sectorbuffer);
2410 }
2411 }
2412 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002413 else if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002414 /* no test on change? the printf below might be mistaken */
2415 sgi_write_table();
2416 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002417 else if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002418 int needw = 0;
2419
Rob Landleyb73451d2006-02-24 16:29:00 +00002420 for (i = 0; i < 8; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002421 if (ptes[i].changed)
2422 needw = 1;
2423 if (needw)
2424 sun_write_table();
2425 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002426
Denis Vlasenkobd852072007-03-19 14:43:38 +00002427 printf("The partition table has been altered!\n\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002428 reread_partition_table(1);
2429}
2430
Rob Landleyb73451d2006-02-24 16:29:00 +00002431static void
2432reread_partition_table(int leave)
2433{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002434 int i;
2435
Denis Vlasenkobd852072007-03-19 14:43:38 +00002436 printf("Calling ioctl() to re-read partition table\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002437 sync();
Denis Vlasenkobd852072007-03-19 14:43:38 +00002438 /* sleep(2); Huh? */
Denis Vlasenko28703012006-12-19 20:32:02 +00002439 i = ioctl(fd, BLKRRPART);
2440#if 0
2441 else {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002442 /* some kernel versions (1.2.x) seem to have trouble
2443 rereading the partition table, but if asked to do it
2444 twice, the second time works. - biro@yggdrasil.com */
2445 sync();
2446 sleep(2);
Denis Vlasenko28703012006-12-19 20:32:02 +00002447 i = ioctl(fd, BLKRRPART);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002448 }
Denis Vlasenko28703012006-12-19 20:32:02 +00002449#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002450
2451 if (i) {
Denis Vlasenko28703012006-12-19 20:32:02 +00002452 bb_perror_msg("WARNING: rereading partition table "
2453 "failed, kernel still uses old table");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002454 }
2455
Denis Vlasenko28703012006-12-19 20:32:02 +00002456#if 0
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002457 if (dos_changed)
Rob Landleyb73451d2006-02-24 16:29:00 +00002458 printf(
Denis Vlasenkobd852072007-03-19 14:43:38 +00002459 "\nWARNING: If you have created or modified any DOS 6.x\n"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002460 "partitions, please see the fdisk manual page for additional\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +00002461 "information\n");
Denis Vlasenko28703012006-12-19 20:32:02 +00002462#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002463
2464 if (leave) {
Denis Vlasenko28703012006-12-19 20:32:02 +00002465 if (ENABLE_FEATURE_CLEAN_UP)
2466 close(fd);
2467 exit(i != 0);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002468 }
2469}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00002470#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002471
Denis Vlasenko834410a2006-11-29 12:00:28 +00002472#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002473#define MAX_PER_LINE 16
2474static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002475print_buffer(char *pbuffer)
2476{
2477 int i,l;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002478
2479 for (i = 0, l = 0; i < sector_size; i++, l++) {
2480 if (l == 0)
2481 printf("0x%03X:", i);
2482 printf(" %02X", (unsigned char) pbuffer[i]);
2483 if (l == MAX_PER_LINE - 1) {
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00002484 puts("");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002485 l = -1;
2486 }
2487 }
2488 if (l > 0)
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00002489 puts("");
2490 puts("");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002491}
2492
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002493static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002494print_raw(void)
2495{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002496 int i;
2497
Denis Vlasenkobd852072007-03-19 14:43:38 +00002498 printf("Device: %s\n", disk_device);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002499 if (LABEL_IS_SGI || LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002500 print_buffer(MBRbuffer);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002501 else {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002502 for (i = 3; i < partitions; i++)
2503 print_buffer(ptes[i].sectorbuffer);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002504 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002505}
2506
2507static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002508move_begin(int i)
2509{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002510 struct pte *pe = &ptes[i];
2511 struct partition *p = pe->part_table;
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002512 ullong new, first;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002513
2514 if (warn_geometry())
2515 return;
Rob Landleyb73451d2006-02-24 16:29:00 +00002516 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002517 printf("Partition %d has no data area\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002518 return;
2519 }
2520 first = get_partition_start(pe);
2521 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
Denis Vlasenkobd852072007-03-19 14:43:38 +00002522 "New beginning of data") - pe->offset;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002523
2524 if (new != get_nr_sects(p)) {
2525 first = get_nr_sects(p) + get_start_sect(p) - new;
2526 set_nr_sects(p, first);
2527 set_start_sect(p, new);
2528 pe->changed = 1;
2529 }
2530}
2531
2532static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002533xselect(void)
2534{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002535 char c;
2536
Rob Landleyb73451d2006-02-24 16:29:00 +00002537 while (1) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002538 putchar('\n');
Denis Vlasenkobd852072007-03-19 14:43:38 +00002539 c = tolower(read_nonempty("Expert command (m for help): "));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002540 switch (c) {
2541 case 'a':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002542 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002543 sun_set_alt_cyl();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002544 break;
2545 case 'b':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002546 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002547 move_begin(get_partition(0, partitions));
2548 break;
2549 case 'c':
2550 user_cylinders = cylinders =
2551 read_int(1, cylinders, 1048576, 0,
Denis Vlasenkobd852072007-03-19 14:43:38 +00002552 "Number of cylinders");
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002553 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002554 sun_set_ncyl(cylinders);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002555 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002556 warn_cylinders();
2557 break;
2558 case 'd':
2559 print_raw();
2560 break;
2561 case 'e':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002562 if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002563 sgi_set_xcyl();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002564 else if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002565 sun_set_xcyl();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002566 else if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002567 x_list_table(1);
2568 break;
2569 case 'f':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002570 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002571 fix_partition_table_order();
2572 break;
2573 case 'g':
Denis Vlasenko834410a2006-11-29 12:00:28 +00002574#if ENABLE_FEATURE_SGI_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002575 create_sgilabel();
2576#endif
2577 break;
2578 case 'h':
2579 user_heads = heads = read_int(1, heads, 256, 0,
Denis Vlasenkobd852072007-03-19 14:43:38 +00002580 "Number of heads");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002581 update_units();
2582 break;
2583 case 'i':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002584 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002585 sun_set_ilfact();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002586 break;
2587 case 'o':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002588 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002589 sun_set_rspeed();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002590 break;
2591 case 'p':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002592 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002593 list_table(1);
2594 else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002595 x_list_table(0);
2596 break;
2597 case 'q':
2598 close(fd);
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00002599 puts("");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002600 exit(0);
2601 case 'r':
2602 return;
2603 case 's':
2604 user_sectors = sectors = read_int(1, sectors, 63, 0,
Denis Vlasenkobd852072007-03-19 14:43:38 +00002605 "Number of sectors");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002606 if (dos_compatible_flag) {
2607 sector_offset = sectors;
Denis Vlasenkobd852072007-03-19 14:43:38 +00002608 printf("Warning: setting sector offset for DOS "
2609 "compatiblity\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002610 }
2611 update_units();
2612 break;
2613 case 'v':
2614 verify();
2615 break;
2616 case 'w':
2617 write_table(); /* does not return */
2618 break;
2619 case 'y':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002620 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002621 sun_set_pcylcount();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002622 break;
2623 default:
2624 xmenu();
2625 }
2626 }
2627}
2628#endif /* ADVANCED mode */
2629
2630static int
Rob Landleyb73451d2006-02-24 16:29:00 +00002631is_ide_cdrom_or_tape(const char *device)
2632{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002633 FILE *procf;
2634 char buf[100];
2635 struct stat statbuf;
2636 int is_ide = 0;
2637
2638 /* No device was given explicitly, and we are trying some
2639 likely things. But opening /dev/hdc may produce errors like
2640 "hdc: tray open or drive not ready"
2641 if it happens to be a CD-ROM drive. It even happens that
2642 the process hangs on the attempt to read a music CD.
2643 So try to be careful. This only works since 2.1.73. */
2644
2645 if (strncmp("/dev/hd", device, 7))
2646 return 0;
2647
2648 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
2649 procf = fopen(buf, "r");
2650 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2651 is_ide = (!strncmp(buf, "cdrom", 5) ||
2652 !strncmp(buf, "tape", 4));
2653 else
2654 /* Now when this proc file does not exist, skip the
2655 device when it is read-only. */
2656 if (stat(device, &statbuf) == 0)
2657 is_ide = ((statbuf.st_mode & 0222) == 0);
2658
2659 if (procf)
2660 fclose(procf);
2661 return is_ide;
2662}
2663
Rob Landley5527b912006-02-25 03:46:10 +00002664
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002665static void
Denis Vlasenkod5470832007-01-03 02:58:54 +00002666trydev(const char *device, int user_specified)
Rob Landleyb73451d2006-02-24 16:29:00 +00002667{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002668 int gb;
2669
2670 disk_device = device;
2671 if (setjmp(listingbuf))
2672 return;
2673 if (!user_specified)
2674 if (is_ide_cdrom_or_tape(device))
2675 return;
Denis Vlasenko28703012006-12-19 20:32:02 +00002676 fd = open(disk_device, type_open);
2677 if (fd >= 0) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002678 gb = get_boot(try_only);
2679 if (gb > 0) { /* I/O error */
2680 close(fd);
2681 } else if (gb < 0) { /* no DOS signature */
2682 list_disk_geometry();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002683 if (LABEL_IS_AIX) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002684 return;
Rob Landley5527b912006-02-25 03:46:10 +00002685 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002686#if ENABLE_FEATURE_OSF_LABEL
Denis Vlasenkod5470832007-01-03 02:58:54 +00002687 if (bsd_trydev(device) < 0)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002688#endif
Denis Vlasenkobd852072007-03-19 14:43:38 +00002689 printf("Disk %s doesn't contain a valid "
2690 "partition table\n", device);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002691 close(fd);
2692 } else {
2693 close(fd);
2694 list_table(0);
Denis Vlasenko834410a2006-11-29 12:00:28 +00002695#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002696 if (!LABEL_IS_SUN && partitions > 4){
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002697 delete_partition(ext_index);
Rob Landley5527b912006-02-25 03:46:10 +00002698 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002699#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002700 }
2701 } else {
2702 /* Ignore other errors, since we try IDE
2703 and SCSI hard disks which may not be
2704 installed on the system. */
2705 if (errno == EACCES) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002706 printf("Cannot open %s\n", device);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002707 return;
2708 }
2709 }
2710}
2711
2712/* for fdisk -l: try all things in /proc/partitions
2713 that look like a partition name (do not end in a digit) */
2714static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002715tryprocpt(void)
2716{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002717 FILE *procpt;
2718 char line[100], ptname[100], devname[120], *s;
2719 int ma, mi, sz;
2720
Denis Vlasenkoddec5af2006-10-26 23:25:17 +00002721 procpt = fopen_or_warn("/proc/partitions", "r");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002722
2723 while (fgets(line, sizeof(line), procpt)) {
Rob Landleyb73451d2006-02-24 16:29:00 +00002724 if (sscanf(line, " %d %d %d %[^\n ]",
2725 &ma, &mi, &sz, ptname) != 4)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002726 continue;
2727 for (s = ptname; *s; s++);
2728 if (isdigit(s[-1]))
2729 continue;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002730 sprintf(devname, "/dev/%s", ptname);
Denis Vlasenkod5470832007-01-03 02:58:54 +00002731 trydev(devname, 0);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002732 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002733#if ENABLE_FEATURE_CLEAN_UP
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002734 fclose(procpt);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002735#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002736}
2737
Denis Vlasenko834410a2006-11-29 12:00:28 +00002738#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002739static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002740unknown_command(int c)
2741{
Denis Vlasenkobd852072007-03-19 14:43:38 +00002742 printf("%c: unknown command\n", c);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002743}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002744#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002745
Denis Vlasenko06af2162007-02-03 17:28:39 +00002746int fdisk_main(int argc, char **argv);
Rob Landleyb73451d2006-02-24 16:29:00 +00002747int fdisk_main(int argc, char **argv)
2748{
Denis Vlasenko834410a2006-11-29 12:00:28 +00002749 char *str_b, *str_C, *str_H, *str_S;
2750 unsigned opt;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002751 /*
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002752 * fdisk -v
2753 * fdisk -l [-b sectorsize] [-u] device ...
2754 * fdisk -s [partition] ...
2755 * fdisk [-b sectorsize] [-u] device
2756 *
2757 * Options -C, -H, -S set the geometry.
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002758 */
Denis Vlasenko834410a2006-11-29 12:00:28 +00002759 enum {
2760 OPT_b = 1 << 0,
2761 OPT_C = 1 << 1,
2762 OPT_H = 1 << 2,
2763 OPT_l = 1 << 3,
2764 OPT_S = 1 << 4,
2765 OPT_u = 1 << 5,
2766 OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
2767 };
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +00002768
Denis Vlasenkodfce08f2007-03-19 14:45:10 +00002769 PTR_TO_GLOBALS = xzalloc(sizeof(G));
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +00002770
Denis Vlasenko834410a2006-11-29 12:00:28 +00002771 opt = getopt32(argc, argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"),
2772 &str_b, &str_C, &str_H, &str_S);
2773 argc -= optind;
2774 argv += optind;
2775 if (opt & OPT_b) { // -b
2776 /* Ugly: this sector size is really per device,
2777 so cannot be combined with multiple disks,
2778 and the same goes for the C/H/S options.
2779 */
2780 sector_size = xatoi_u(str_b);
2781 if (sector_size != 512 && sector_size != 1024 &&
2782 sector_size != 2048)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002783 bb_show_usage();
Denis Vlasenko834410a2006-11-29 12:00:28 +00002784 sector_offset = 2;
2785 user_set_sector_size = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002786 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002787 if (opt & OPT_C) user_cylinders = xatoi_u(str_C); // -C
2788 if (opt & OPT_H) { // -H
2789 user_heads = xatoi_u(str_H);
2790 if (user_heads <= 0 || user_heads >= 256)
2791 user_heads = 0;
2792 }
2793 //if (opt & OPT_l) // -l
2794 if (opt & OPT_S) { // -S
2795 user_sectors = xatoi_u(str_S);
2796 if (user_sectors <= 0 || user_sectors >= 64)
2797 user_sectors = 0;
2798 }
2799 if (opt & OPT_u) display_in_cyl_units = 0; // -u
2800 //if (opt & OPT_s) // -s
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002801
Denis Vlasenko834410a2006-11-29 12:00:28 +00002802 if (user_set_sector_size && argc != 1)
Denis Vlasenkobd852072007-03-19 14:43:38 +00002803 printf("Warning: the -b (set sector size) option should"
2804 " be used with one specified device\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002805
Denis Vlasenko834410a2006-11-29 12:00:28 +00002806#if ENABLE_FEATURE_FDISK_WRITABLE
2807 if (opt & OPT_l) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002808 nowarn = 1;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002809#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002810 type_open = O_RDONLY;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002811 if (argc > 0) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002812 int k;
Denis Vlasenko28703012006-12-19 20:32:02 +00002813#if defined(__GNUC__)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002814 /* avoid gcc warning:
2815 variable `k' might be clobbered by `longjmp' */
2816 (void)&k;
2817#endif
2818 listing = 1;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002819 for (k = 0; k < argc; k++)
Denis Vlasenkod5470832007-01-03 02:58:54 +00002820 trydev(argv[k], 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002821 } else {
2822 /* we no longer have default device names */
2823 /* but, we can use /proc/partitions instead */
2824 tryprocpt();
2825 }
2826 return 0;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002827#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002828 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002829#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002830
Denis Vlasenko834410a2006-11-29 12:00:28 +00002831#if ENABLE_FEATURE_FDISK_BLKSIZE
2832 if (opt & OPT_s) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002833 long size;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002834 int j;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002835
2836 nowarn = 1;
2837 type_open = O_RDONLY;
2838
Denis Vlasenko834410a2006-11-29 12:00:28 +00002839 if (argc <= 0)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002840 bb_show_usage();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002841
Denis Vlasenko834410a2006-11-29 12:00:28 +00002842 for (j = 0; j < argc; j++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002843 disk_device = argv[j];
Denis Vlasenko834410a2006-11-29 12:00:28 +00002844 fd = open(disk_device, type_open);
2845 if (fd < 0)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002846 fdisk_fatal(unable_to_open);
2847 if (ioctl(fd, BLKGETSIZE, &size))
2848 fdisk_fatal(ioctl_error);
2849 close(fd);
Denis Vlasenko834410a2006-11-29 12:00:28 +00002850 if (argc == 1)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002851 printf("%ld\n", size/2);
2852 else
2853 printf("%s: %ld\n", argv[j], size/2);
2854 }
2855 return 0;
2856 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002857#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002858
Denis Vlasenko834410a2006-11-29 12:00:28 +00002859#if ENABLE_FEATURE_FDISK_WRITABLE
2860 if (argc != 1)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002861 bb_show_usage();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002862
Denis Vlasenko834410a2006-11-29 12:00:28 +00002863 disk_device = argv[0];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002864 get_boot(fdisk);
2865
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002866 if (LABEL_IS_OSF) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002867 /* OSF label, and no DOS label */
Denis Vlasenkobd852072007-03-19 14:43:38 +00002868 printf("Detected an OSF/1 disklabel on %s, entering "
2869 "disklabel mode\n", disk_device);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +00002870 bsd_select();
Rob Landley5527b912006-02-25 03:46:10 +00002871 /*Why do we do this? It seems to be counter-intuitive*/
2872 current_label_type = label_dos;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002873 /* If we return we may want to make an empty DOS label? */
2874 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002875
2876 while (1) {
Denis Vlasenko3bba5452006-12-30 17:57:03 +00002877 int c;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002878 putchar('\n');
Denis Vlasenkobd852072007-03-19 14:43:38 +00002879 c = tolower(read_nonempty("Command (m for help): "));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002880 switch (c) {
2881 case 'a':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002882 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002883 toggle_active(get_partition(1, partitions));
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002884 else if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002885 toggle_sunflags(get_partition(1, partitions),
2886 0x01);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002887 else if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002888 sgi_set_bootpartition(
2889 get_partition(1, partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002890 else
2891 unknown_command(c);
2892 break;
2893 case 'b':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002894 if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002895 printf("\nThe current boot file is: %s\n",
Rob Landleyb73451d2006-02-24 16:29:00 +00002896 sgi_get_bootfile());
Denis Vlasenkobd852072007-03-19 14:43:38 +00002897 if (read_maybe_empty("Please enter the name of the "
2898 "new boot file: ") == '\n')
2899 printf("Boot file unchanged\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002900 else
2901 sgi_set_bootfile(line_ptr);
Denis Vlasenko834410a2006-11-29 12:00:28 +00002902 }
2903#if ENABLE_FEATURE_OSF_LABEL
2904 else
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +00002905 bsd_select();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002906#endif
2907 break;
2908 case 'c':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002909 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002910 toggle_dos_compatibility_flag();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002911 else if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002912 toggle_sunflags(get_partition(1, partitions),
2913 0x10);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002914 else if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002915 sgi_set_swappartition(
2916 get_partition(1, partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002917 else
2918 unknown_command(c);
2919 break;
2920 case 'd':
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002921 {
Eric Andersen040f4402003-07-30 08:40:37 +00002922 int j;
Eric Andersen040f4402003-07-30 08:40:37 +00002923 /* If sgi_label then don't use get_existing_partition,
2924 let the user select a partition, since
2925 get_existing_partition() only works for Linux-like
2926 partition tables */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002927 if (!LABEL_IS_SGI) {
Eric Andersen040f4402003-07-30 08:40:37 +00002928 j = get_existing_partition(1, partitions);
2929 } else {
2930 j = get_partition(1, partitions);
2931 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002932 if (j >= 0)
2933 delete_partition(j);
2934 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002935 break;
2936 case 'i':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002937 if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002938 create_sgiinfo();
2939 else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002940 unknown_command(c);
2941 case 'l':
2942 list_types(get_sys_types());
2943 break;
2944 case 'm':
2945 menu();
2946 break;
2947 case 'n':
2948 new_partition();
2949 break;
2950 case 'o':
2951 create_doslabel();
2952 break;
2953 case 'p':
2954 list_table(0);
2955 break;
2956 case 'q':
2957 close(fd);
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00002958 puts("");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002959 return 0;
2960 case 's':
Denis Vlasenko834410a2006-11-29 12:00:28 +00002961#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002962 create_sunlabel();
2963#endif
2964 break;
2965 case 't':
2966 change_sysid();
2967 break;
2968 case 'u':
2969 change_units();
2970 break;
2971 case 'v':
2972 verify();
2973 break;
2974 case 'w':
2975 write_table(); /* does not return */
2976 break;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002977#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002978 case 'x':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002979 if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002980 printf("\n\tSorry, no experts menu for SGI "
2981 "partition tables available\n\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002982 } else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002983 xselect();
2984 break;
2985#endif
2986 default:
2987 unknown_command(c);
2988 menu();
2989 }
2990 }
2991 return 0;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00002992#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002993}