blob: 2933db472ab4d250be92e8d4effcafb22b661c65 [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
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000023#define DEFAULT_SECTOR_SIZE 512
24#define MAX_SECTOR_SIZE 2048
Denis Vlasenko98ae2162006-10-12 19:30:44 +000025#define SECTOR_SIZE 512 /* still used in osf/sgi/sun code */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000026#define MAXIMUM_PARTS 60
27
28#define ACTIVE_FLAG 0x80
29
30#define EXTENDED 0x05
31#define WIN98_EXTENDED 0x0f
32#define LINUX_PARTITION 0x81
33#define LINUX_SWAP 0x82
34#define LINUX_NATIVE 0x83
35#define LINUX_EXTENDED 0x85
36#define LINUX_LVM 0x8e
37#define LINUX_RAID 0xfd
38
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +000039/* Used for sector numbers. Today's disk sizes make it necessary */
40typedef unsigned long long ullong;
41
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000042struct hd_geometry {
Rob Landleyb73451d2006-02-24 16:29:00 +000043 unsigned char heads;
44 unsigned char sectors;
45 unsigned short cylinders;
46 unsigned long start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000047};
48
Denis Vlasenko98ae2162006-10-12 19:30:44 +000049#define HDIO_GETGEO 0x0301 /* get device geometry */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000050
Denis Vlasenko6ca409e2007-08-12 20:58:27 +000051static const char msg_building_new_label[] ALIGN1 =
Denis Vlasenkobd852072007-03-19 14:43:38 +000052"Building a new %s. Changes will remain in memory only,\n"
53"until you decide to write them. After that the previous content\n"
54"won't be recoverable.\n\n";
55
Denis Vlasenko6ca409e2007-08-12 20:58:27 +000056static const char msg_part_already_defined[] ALIGN1 =
Denis Vlasenkobd852072007-03-19 14:43:38 +000057"Partition %d is already defined, delete it before re-adding\n";
58
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000059
Denis Vlasenko834410a2006-11-29 12:00:28 +000060static unsigned sector_size = DEFAULT_SECTOR_SIZE;
61static unsigned user_set_sector_size;
62static unsigned sector_offset = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000063
Denis Vlasenko834410a2006-11-29 12:00:28 +000064#if ENABLE_FEATURE_OSF_LABEL
Rob Landleyb73451d2006-02-24 16:29:00 +000065static int possibly_osf_label;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000066#endif
67
Denis Vlasenko834410a2006-11-29 12:00:28 +000068static unsigned heads, sectors, cylinders;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000069static void update_units(void);
70
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000071
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000072struct partition {
73 unsigned char boot_ind; /* 0x80 - active */
74 unsigned char head; /* starting head */
75 unsigned char sector; /* starting sector */
76 unsigned char cyl; /* starting cylinder */
77 unsigned char sys_ind; /* What partition type */
78 unsigned char end_head; /* end head */
79 unsigned char end_sector; /* end sector */
80 unsigned char end_cyl; /* end cylinder */
81 unsigned char start4[4]; /* starting sector counting from 0 */
82 unsigned char size4[4]; /* nr of sectors in partition */
Bernhard Reutner-Fischer86f5c992006-01-22 22:55:11 +000083} ATTRIBUTE_PACKED;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000084
Denis Vlasenko6ca409e2007-08-12 20:58:27 +000085static const char unable_to_open[] ALIGN1 = "cannot open %s";
86static const char unable_to_read[] ALIGN1 = "cannot read from %s";
87static const char unable_to_seek[] ALIGN1 = "cannot seek on %s";
88static const char unable_to_write[] ALIGN1 = "cannot write to %s";
89static const char ioctl_error[] ALIGN1 = "BLKGETSIZE ioctl failed on %s";
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +000090static void fdisk_fatal(const char *why) ATTRIBUTE_NORETURN;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +000091
Denis Vlasenko98ae2162006-10-12 19:30:44 +000092enum label_type {
Rob Landley5527b912006-02-25 03:46:10 +000093 label_dos, label_sun, label_sgi, label_aix, label_osf
94};
Denis Vlasenkodfce08f2007-03-19 14:45:10 +000095
Denis Vlasenko98ae2162006-10-12 19:30:44 +000096#define LABEL_IS_DOS (label_dos == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +000097
Denis Vlasenko834410a2006-11-29 12:00:28 +000098#if ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +000099#define LABEL_IS_SUN (label_sun == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000100#define STATIC_SUN static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000101#else
102#define LABEL_IS_SUN 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000103#define STATIC_SUN extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000104#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000105
Denis Vlasenko834410a2006-11-29 12:00:28 +0000106#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000107#define LABEL_IS_SGI (label_sgi == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000108#define STATIC_SGI static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000109#else
110#define LABEL_IS_SGI 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000111#define STATIC_SGI extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000112#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000113
Denis Vlasenko834410a2006-11-29 12:00:28 +0000114#if ENABLE_FEATURE_AIX_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000115#define LABEL_IS_AIX (label_aix == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000116#define STATIC_AIX static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000117#else
118#define LABEL_IS_AIX 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000119#define STATIC_AIX extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000120#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000121
Denis Vlasenko834410a2006-11-29 12:00:28 +0000122#if ENABLE_FEATURE_OSF_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000123#define LABEL_IS_OSF (label_osf == current_label_type)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000124#define STATIC_OSF static
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000125#else
126#define LABEL_IS_OSF 0
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000127#define STATIC_OSF extern
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000128#endif
Rob Landley5527b912006-02-25 03:46:10 +0000129
Rob Landleyb73451d2006-02-24 16:29:00 +0000130enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000131
Rob Landley5527b912006-02-25 03:46:10 +0000132static enum label_type current_label_type;
133
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000134static const char *disk_device;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000135static int fd; /* the disk */
136static int partitions = 4; /* maximum partition + 1 */
Denis Vlasenko834410a2006-11-29 12:00:28 +0000137static int display_in_cyl_units = 1;
138static unsigned units_per_sector = 1;
139#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000140static void change_units(void);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000141static void reread_partition_table(int leave);
142static void delete_partition(int i);
Rob Landleyb73451d2006-02-24 16:29:00 +0000143static int get_partition(int warn, int max);
Denis Vlasenkobd852072007-03-19 14:43:38 +0000144static void list_types(const char *const *sys);
Denis Vlasenko06c0a712007-01-29 22:51:44 +0000145static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000146#endif
147static const char *partition_type(unsigned char type);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000148static void get_geometry(void);
149static int get_boot(enum action what);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000150
151#define PLURAL 0
152#define SINGULAR 1
153
Denis Vlasenko28703012006-12-19 20:32:02 +0000154static unsigned get_start_sect(const struct partition *p);
155static unsigned get_nr_sects(const struct partition *p);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000156
157/*
158 * per partition table entry data
159 *
160 * The four primary partitions have the same sectorbuffer (MBRbuffer)
161 * and have NULL ext_pointer.
162 * Each logical partition table entry has two pointers, one for the
163 * partition and one link to the next one.
164 */
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000165struct pte {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000166 struct partition *part_table; /* points into sectorbuffer */
167 struct partition *ext_pointer; /* points into sectorbuffer */
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000168 ullong offset; /* disk sector number */
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000169 char *sectorbuffer; /* disk sector contents */
Denis Vlasenko834410a2006-11-29 12:00:28 +0000170#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000171 char changed; /* boolean */
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000172#endif
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000173};
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000174
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000175/* DOS partition types */
176
177static const char *const i386_sys_types[] = {
178 "\x00" "Empty",
179 "\x01" "FAT12",
180 "\x04" "FAT16 <32M",
181 "\x05" "Extended", /* DOS 3.3+ extended partition */
182 "\x06" "FAT16", /* DOS 16-bit >=32M */
183 "\x07" "HPFS/NTFS", /* OS/2 IFS, eg, HPFS or NTFS or QNX */
184 "\x0a" "OS/2 Boot Manager",/* OS/2 Boot Manager */
185 "\x0b" "Win95 FAT32",
186 "\x0c" "Win95 FAT32 (LBA)",/* LBA really is 'Extended Int 13h' */
187 "\x0e" "Win95 FAT16 (LBA)",
188 "\x0f" "Win95 Ext'd (LBA)",
189 "\x11" "Hidden FAT12",
190 "\x12" "Compaq diagnostics",
191 "\x14" "Hidden FAT16 <32M",
192 "\x16" "Hidden FAT16",
193 "\x17" "Hidden HPFS/NTFS",
194 "\x1b" "Hidden Win95 FAT32",
195 "\x1c" "Hidden W95 FAT32 (LBA)",
196 "\x1e" "Hidden W95 FAT16 (LBA)",
197 "\x3c" "Part.Magic recovery",
198 "\x41" "PPC PReP Boot",
199 "\x42" "SFS",
200 "\x63" "GNU HURD or SysV", /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
201 "\x80" "Old Minix", /* Minix 1.4a and earlier */
202 "\x81" "Minix / old Linux",/* Minix 1.4b and later */
203 "\x82" "Linux swap", /* also Solaris */
204 "\x83" "Linux",
205 "\x84" "OS/2 hidden C: drive",
206 "\x85" "Linux extended",
207 "\x86" "NTFS volume set",
208 "\x87" "NTFS volume set",
209 "\x8e" "Linux LVM",
210 "\x9f" "BSD/OS", /* BSDI */
211 "\xa0" "Thinkpad hibernation",
212 "\xa5" "FreeBSD", /* various BSD flavours */
213 "\xa6" "OpenBSD",
214 "\xa8" "Darwin UFS",
215 "\xa9" "NetBSD",
216 "\xab" "Darwin boot",
217 "\xb7" "BSDI fs",
218 "\xb8" "BSDI swap",
219 "\xbe" "Solaris boot",
220 "\xeb" "BeOS fs",
221 "\xee" "EFI GPT", /* Intel EFI GUID Partition Table */
222 "\xef" "EFI (FAT-12/16/32)", /* Intel EFI System Partition */
223 "\xf0" "Linux/PA-RISC boot", /* Linux/PA-RISC boot loader */
224 "\xf2" "DOS secondary", /* DOS 3.3+ secondary */
225 "\xfd" "Linux raid autodetect", /* New (2.2.x) raid partition with
226 autodetect using persistent
227 superblock */
228#if 0 /* ENABLE_WEIRD_PARTITION_TYPES */
229 "\x02" "XENIX root",
230 "\x03" "XENIX usr",
231 "\x08" "AIX", /* AIX boot (AIX -- PS/2 port) or SplitDrive */
232 "\x09" "AIX bootable", /* AIX data or Coherent */
233 "\x10" "OPUS",
234 "\x18" "AST SmartSleep",
235 "\x24" "NEC DOS",
236 "\x39" "Plan 9",
237 "\x40" "Venix 80286",
238 "\x4d" "QNX4.x",
239 "\x4e" "QNX4.x 2nd part",
240 "\x4f" "QNX4.x 3rd part",
241 "\x50" "OnTrack DM",
242 "\x51" "OnTrack DM6 Aux1", /* (or Novell) */
243 "\x52" "CP/M", /* CP/M or Microport SysV/AT */
244 "\x53" "OnTrack DM6 Aux3",
245 "\x54" "OnTrackDM6",
246 "\x55" "EZ-Drive",
247 "\x56" "Golden Bow",
248 "\x5c" "Priam Edisk",
249 "\x61" "SpeedStor",
250 "\x64" "Novell Netware 286",
251 "\x65" "Novell Netware 386",
252 "\x70" "DiskSecure Multi-Boot",
253 "\x75" "PC/IX",
254 "\x93" "Amoeba",
255 "\x94" "Amoeba BBT", /* (bad block table) */
256 "\xa7" "NeXTSTEP",
257 "\xbb" "Boot Wizard hidden",
258 "\xc1" "DRDOS/sec (FAT-12)",
259 "\xc4" "DRDOS/sec (FAT-16 < 32M)",
260 "\xc6" "DRDOS/sec (FAT-16)",
261 "\xc7" "Syrinx",
262 "\xda" "Non-FS data",
263 "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or
264 Concurrent DOS or CTOS */
265 "\xde" "Dell Utility", /* Dell PowerEdge Server utilities */
266 "\xdf" "BootIt", /* BootIt EMBRM */
267 "\xe1" "DOS access", /* DOS access or SpeedStor 12-bit FAT
268 extended partition */
269 "\xe3" "DOS R/O", /* DOS R/O or SpeedStor */
270 "\xe4" "SpeedStor", /* SpeedStor 16-bit FAT extended
271 partition < 1024 cyl. */
272 "\xf1" "SpeedStor",
273 "\xf4" "SpeedStor", /* SpeedStor large partition */
274 "\xfe" "LANstep", /* SpeedStor >1024 cyl. or LANstep */
275 "\xff" "BBT", /* Xenix Bad Block Table */
276#endif
277 NULL
278};
279
280
281/* Globals */
282
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000283struct globals {
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000284 char *line_ptr;
285 char line_buffer[80];
286 char partname_buffer[80];
287 jmp_buf listingbuf;
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000288 /* Raw disk label. For DOS-type partition tables the MBR,
289 * with descriptions of the primary partitions. */
290 char MBRbuffer[MAX_SECTOR_SIZE];
291 /* Partition tables */
292 struct pte ptes[MAXIMUM_PARTS];
293};
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000294/* bb_common_bufsiz1 is too small for this on 64 bit CPUs */
295#define G (*ptr_to_globals)
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000296
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000297#define line_ptr (G.line_ptr)
298#define listingbuf (G.listingbuf)
299#define line_buffer (G.line_buffer)
300#define partname_buffer (G.partname_buffer)
301#define MBRbuffer (G.MBRbuffer)
302#define ptes (G.ptes)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000303
Denis Vlasenkobd852072007-03-19 14:43:38 +0000304
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000305/* Code */
306
307#define IS_EXTENDED(i) \
308 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
309
310#define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
311
312#define scround(x) (((x)+units_per_sector-1)/units_per_sector)
313
314#define pt_offset(b, n) \
315 ((struct partition *)((b) + 0x1be + (n) * sizeof(struct partition)))
316
317#define sector(s) ((s) & 0x3f)
318
319#define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
320
321#define hsc2sector(h,s,c) \
322 (sector(s) - 1 + sectors * ((h) + heads * cylinder(s,c)))
323
324#define set_hsc(h,s,c,sector) \
325 do { \
326 s = sector % sectors + 1; \
327 sector /= sectors; \
328 h = sector % heads; \
329 sector /= heads; \
330 c = sector & 0xff; \
331 s |= (sector >> 2) & 0xc0; \
332 } while (0)
333
Denis Vlasenko58875ae2007-03-22 22:22:10 +0000334#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000335/* read line; return 0 or first printable char */
336static int
337read_line(const char *prompt)
338{
339 int sz;
340
341 sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
342 if (sz <= 0)
343 exit(0); /* Ctrl-D or Ctrl-C */
344
345 if (line_buffer[sz-1] == '\n')
346 line_buffer[--sz] = '\0';
347
348 line_ptr = line_buffer;
349 while (*line_ptr && !isgraph(*line_ptr))
350 line_ptr++;
351 return *line_ptr;
352}
Denis Vlasenko58875ae2007-03-22 22:22:10 +0000353#endif
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000354
Denis Vlasenkobd852072007-03-19 14:43:38 +0000355/*
356 * return partition name - uses static storage
357 */
358static const char *
359partname(const char *dev, int pno, int lth)
360{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000361 const char *p;
362 int w, wp;
363 int bufsiz;
364 char *bufp;
365
Denis Vlasenkodfce08f2007-03-19 14:45:10 +0000366 bufp = partname_buffer;
367 bufsiz = sizeof(partname_buffer);
Denis Vlasenkobd852072007-03-19 14:43:38 +0000368
369 w = strlen(dev);
370 p = "";
371
372 if (isdigit(dev[w-1]))
373 p = "p";
374
375 /* devfs kludge - note: fdisk partition names are not supposed
376 to equal kernel names, so there is no reason to do this */
377 if (strcmp(dev + w - 4, "disc") == 0) {
378 w -= 4;
379 p = "part";
380 }
381
382 wp = strlen(p);
383
384 if (lth) {
385 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
386 lth-wp-2, w, dev, p, pno);
387 } else {
388 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
389 }
390 return bufp;
391}
392
Denis Vlasenko834410a2006-11-29 12:00:28 +0000393#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000394static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000395set_all_unchanged(void)
396{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000397 int i;
398
399 for (i = 0; i < MAXIMUM_PARTS; i++)
400 ptes[i].changed = 0;
401}
402
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000403static ALWAYS_INLINE void
Rob Landleyb73451d2006-02-24 16:29:00 +0000404set_changed(int i)
405{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000406 ptes[i].changed = 1;
407}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000408#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000409
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000410static ALWAYS_INLINE struct partition *
Rob Landleyb73451d2006-02-24 16:29:00 +0000411get_part_table(int i)
412{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000413 return ptes[i].part_table;
414}
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000415
416static const char *
Rob Landleyb73451d2006-02-24 16:29:00 +0000417str_units(int n)
418{ /* n==1: use singular */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000419 if (n == 1)
Denis Vlasenkobd852072007-03-19 14:43:38 +0000420 return display_in_cyl_units ? "cylinder" : "sector";
421 return display_in_cyl_units ? "cylinders" : "sectors";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000422}
423
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000424static int
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000425valid_part_table_flag(const char *mbuffer)
426{
Denis Vlasenko834410a2006-11-29 12:00:28 +0000427 return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000428}
429
Denis Vlasenko834410a2006-11-29 12:00:28 +0000430#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko3ad5d0c2007-06-12 20:54:54 +0000431static ALWAYS_INLINE void
Denis Vlasenko834410a2006-11-29 12:00:28 +0000432write_part_table_flag(char *b)
433{
434 b[510] = 0x55;
435 b[511] = 0xaa;
436}
437
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000438static char
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000439read_nonempty(const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000440{
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000441 while (!read_line(mesg)) /* repeat */;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000442 return *line_ptr;
443}
444
445static char
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000446read_maybe_empty(const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000447{
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000448 if (!read_line(mesg)) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000449 line_ptr = line_buffer;
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000450 line_ptr[0] = '\n';
451 line_ptr[1] = '\0';
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000452 }
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000453 return line_ptr[0];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000454}
455
456static int
Denis Vlasenkobd852072007-03-19 14:43:38 +0000457read_hex(const char *const *sys)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000458{
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000459 unsigned long v;
Rob Landleyb73451d2006-02-24 16:29:00 +0000460 while (1) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000461 read_nonempty("Hex code (type L to list codes): ");
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000462 if (*line_ptr == 'l' || *line_ptr == 'L') {
Rob Landleyb73451d2006-02-24 16:29:00 +0000463 list_types(sys);
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000464 continue;
Rob Landleyb73451d2006-02-24 16:29:00 +0000465 }
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000466 v = bb_strtoul(line_ptr, NULL, 16);
Denis Vlasenko28703012006-12-19 20:32:02 +0000467 if (v > 0xff)
468 /* Bad input also triggers this */
469 continue;
Denis Vlasenkoc6ce8732006-11-29 18:15:52 +0000470 return v;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000471 }
472}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000473#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000474
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000475#include "fdisk_aix.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000476
477typedef struct {
478 unsigned char info[128]; /* Informative text string */
479 unsigned char spare0[14];
480 struct sun_info {
481 unsigned char spare1;
482 unsigned char id;
483 unsigned char spare2;
484 unsigned char flags;
485 } infos[8];
486 unsigned char spare1[246]; /* Boot information etc. */
487 unsigned short rspeed; /* Disk rotational speed */
488 unsigned short pcylcount; /* Physical cylinder count */
489 unsigned short sparecyl; /* extra sects per cylinder */
490 unsigned char spare2[4]; /* More magic... */
491 unsigned short ilfact; /* Interleave factor */
492 unsigned short ncyl; /* Data cylinder count */
493 unsigned short nacyl; /* Alt. cylinder count */
494 unsigned short ntrks; /* Tracks per cylinder */
495 unsigned short nsect; /* Sectors per track */
496 unsigned char spare3[4]; /* Even more magic... */
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000497 struct sun_partinfo {
Eric Andersenacd244a2002-12-11 03:49:33 +0000498 uint32_t start_cylinder;
499 uint32_t num_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000500 } partitions[8];
501 unsigned short magic; /* Magic number */
502 unsigned short csum; /* Label xor'd checksum */
503} sun_partition;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000504#define sunlabel ((sun_partition *)MBRbuffer)
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000505STATIC_OSF void bsd_select(void);
506STATIC_OSF void xbsd_print_disklabel(int);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000507#include "fdisk_osf.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000508
Denis Vlasenko28703012006-12-19 20:32:02 +0000509#if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000510static uint16_t
Denis Vlasenko28703012006-12-19 20:32:02 +0000511fdisk_swap16(uint16_t x)
Rob Landleyb73451d2006-02-24 16:29:00 +0000512{
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000513 return (x << 8) | (x >> 8);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000514}
515
Rob Landley88621d72006-08-29 19:41:06 +0000516static uint32_t
Denis Vlasenko28703012006-12-19 20:32:02 +0000517fdisk_swap32(uint32_t x)
Rob Landleyb73451d2006-02-24 16:29:00 +0000518{
Denis Vlasenko10d0d4e2006-11-27 16:48:17 +0000519 return (x << 24) |
520 ((x & 0xFF00) << 8) |
521 ((x & 0xFF0000) >> 8) |
522 (x >> 24);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000523}
524#endif
525
Denis Vlasenkobd852072007-03-19 14:43:38 +0000526STATIC_SGI const char *const sgi_sys_types[];
Denis Vlasenko834410a2006-11-29 12:00:28 +0000527STATIC_SGI unsigned sgi_get_num_sectors(int i);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000528STATIC_SGI int sgi_get_sysid(int i);
529STATIC_SGI void sgi_delete_partition(int i);
530STATIC_SGI void sgi_change_sysid(int i, int sys);
531STATIC_SGI void sgi_list_table(int xtra);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000532#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000533STATIC_SGI void sgi_set_xcyl(void);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000534#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000535STATIC_SGI int verify_sgi(int verbose);
536STATIC_SGI void sgi_add_partition(int n, int sys);
537STATIC_SGI void sgi_set_swappartition(int i);
538STATIC_SGI const char *sgi_get_bootfile(void);
539STATIC_SGI void sgi_set_bootfile(const char* aFile);
540STATIC_SGI void create_sgiinfo(void);
541STATIC_SGI void sgi_write_table(void);
542STATIC_SGI void sgi_set_bootpartition(int i);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000543#include "fdisk_sgi.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000544
Denis Vlasenkobd852072007-03-19 14:43:38 +0000545STATIC_SUN const char *const sun_sys_types[];
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000546STATIC_SUN void sun_delete_partition(int i);
547STATIC_SUN void sun_change_sysid(int i, int sys);
548STATIC_SUN void sun_list_table(int xtra);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000549STATIC_SUN void add_sun_partition(int n, int sys);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000550#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000551STATIC_SUN void sun_set_alt_cyl(void);
552STATIC_SUN void sun_set_ncyl(int cyl);
553STATIC_SUN void sun_set_xcyl(void);
554STATIC_SUN void sun_set_ilfact(void);
555STATIC_SUN void sun_set_rspeed(void);
556STATIC_SUN void sun_set_pcylcount(void);
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000557#endif
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +0000558STATIC_SUN void toggle_sunflags(int i, unsigned char mask);
559STATIC_SUN void verify_sun(void);
560STATIC_SUN void sun_write_table(void);
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000561#include "fdisk_sun.c"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000562
Denis Vlasenko834410a2006-11-29 12:00:28 +0000563#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000564/* start_sect and nr_sects are stored little endian on all machines */
565/* moreover, they are not aligned correctly */
566static void
Denis Vlasenko834410a2006-11-29 12:00:28 +0000567store4_little_endian(unsigned char *cp, unsigned val)
Rob Landleyb73451d2006-02-24 16:29:00 +0000568{
Denis Vlasenko834410a2006-11-29 12:00:28 +0000569 cp[0] = val;
570 cp[1] = val >> 8;
571 cp[2] = val >> 16;
572 cp[3] = val >> 24;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000573}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000574#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000575
Denis Vlasenko834410a2006-11-29 12:00:28 +0000576static unsigned
Rob Landleyb73451d2006-02-24 16:29:00 +0000577read4_little_endian(const unsigned char *cp)
578{
Denis Vlasenko834410a2006-11-29 12:00:28 +0000579 return cp[0] + (cp[1] << 8) + (cp[2] << 16) + (cp[3] << 24);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000580}
581
Denis Vlasenko834410a2006-11-29 12:00:28 +0000582#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000583static void
Denis Vlasenko834410a2006-11-29 12:00:28 +0000584set_start_sect(struct partition *p, unsigned start_sect)
Rob Landleyb73451d2006-02-24 16:29:00 +0000585{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000586 store4_little_endian(p->start4, start_sect);
587}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000588#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000589
Denis Vlasenko28703012006-12-19 20:32:02 +0000590static unsigned
Rob Landleyb73451d2006-02-24 16:29:00 +0000591get_start_sect(const struct partition *p)
592{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000593 return read4_little_endian(p->start4);
594}
595
Denis Vlasenko834410a2006-11-29 12:00:28 +0000596#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000597static void
Denis Vlasenko28703012006-12-19 20:32:02 +0000598set_nr_sects(struct partition *p, unsigned nr_sects)
Rob Landleyb73451d2006-02-24 16:29:00 +0000599{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000600 store4_little_endian(p->size4, nr_sects);
601}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000602#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000603
Denis Vlasenko28703012006-12-19 20:32:02 +0000604static unsigned
Rob Landleyb73451d2006-02-24 16:29:00 +0000605get_nr_sects(const struct partition *p)
606{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000607 return read4_little_endian(p->size4);
608}
609
610/* normally O_RDWR, -l option gives O_RDONLY */
611static int type_open = O_RDWR;
612
Rob Landleyb73451d2006-02-24 16:29:00 +0000613static int ext_index; /* the prime extended partition */
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000614static int listing; /* no aborts for fdisk -l */
Rob Landleyb73451d2006-02-24 16:29:00 +0000615static int dos_compatible_flag = ~0;
Denis Vlasenko834410a2006-11-29 12:00:28 +0000616#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000617static int dos_changed;
618static int nowarn; /* no warnings for fdisk -l/-s */
619#endif
620
Denis Vlasenko834410a2006-11-29 12:00:28 +0000621static unsigned user_cylinders, user_heads, user_sectors;
622static unsigned pt_heads, pt_sectors;
623static unsigned kern_heads, kern_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000624
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000625static ullong extended_offset; /* offset of link pointers */
626static ullong total_number_of_sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000627
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000628static void fdisk_fatal(const char *why)
Rob Landleyb73451d2006-02-24 16:29:00 +0000629{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000630 if (listing) {
631 close(fd);
632 longjmp(listingbuf, 1);
633 }
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000634 bb_error_msg_and_die(why, disk_device);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000635}
636
637static void
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000638seek_sector(ullong secno)
Rob Landleyb73451d2006-02-24 16:29:00 +0000639{
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000640 secno *= sector_size;
641 if (lseek64(fd, (off64_t)secno, SEEK_SET) == (off64_t) -1)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000642 fdisk_fatal(unable_to_seek);
643}
644
Denis Vlasenko834410a2006-11-29 12:00:28 +0000645#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000646static void
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000647write_sector(ullong secno, char *buf)
Rob Landleyb73451d2006-02-24 16:29:00 +0000648{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000649 seek_sector(secno);
650 if (write(fd, buf, sector_size) != sector_size)
651 fdisk_fatal(unable_to_write);
652}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000653#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000654
655/* Allocate a buffer and read a partition table sector */
656static void
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000657read_pte(struct pte *pe, ullong offset)
Rob Landleyb73451d2006-02-24 16:29:00 +0000658{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000659 pe->offset = offset;
Denis Vlasenkob95636c2006-12-19 23:36:04 +0000660 pe->sectorbuffer = xmalloc(sector_size);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000661 seek_sector(offset);
662 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
663 fdisk_fatal(unable_to_read);
Denis Vlasenko834410a2006-11-29 12:00:28 +0000664#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000665 pe->changed = 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000666#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000667 pe->part_table = pe->ext_pointer = NULL;
668}
669
Denis Vlasenko834410a2006-11-29 12:00:28 +0000670static unsigned
Rob Landleyb73451d2006-02-24 16:29:00 +0000671get_partition_start(const struct pte *pe)
672{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000673 return pe->offset + get_start_sect(pe->part_table);
674}
675
Denis Vlasenko834410a2006-11-29 12:00:28 +0000676#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000677/*
678 * Avoid warning about DOS partitions when no DOS partition was changed.
679 * Here a heuristic "is probably dos partition".
680 * We might also do the opposite and warn in all cases except
681 * for "is probably nondos partition".
682 */
683static int
Rob Landleyb73451d2006-02-24 16:29:00 +0000684is_dos_partition(int t)
685{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000686 return (t == 1 || t == 4 || t == 6 ||
687 t == 0x0b || t == 0x0c || t == 0x0e ||
688 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
689 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
690 t == 0xc1 || t == 0xc4 || t == 0xc6);
691}
692
693static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000694menu(void)
695{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000696 puts("Command Action");
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000697 if (LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000698 puts("a\ttoggle a read only flag"); /* sun */
699 puts("b\tedit bsd disklabel");
700 puts("c\ttoggle the mountable flag"); /* sun */
701 puts("d\tdelete a partition");
702 puts("l\tlist known partition types");
703 puts("n\tadd a new partition");
704 puts("o\tcreate a new empty DOS partition table");
705 puts("p\tprint the partition table");
706 puts("q\tquit without saving changes");
707 puts("s\tcreate a new empty Sun disklabel"); /* sun */
708 puts("t\tchange a partition's system id");
709 puts("u\tchange display/entry units");
710 puts("v\tverify the partition table");
711 puts("w\twrite table to disk and exit");
Denis Vlasenko834410a2006-11-29 12:00:28 +0000712#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkobd852072007-03-19 14:43:38 +0000713 puts("x\textra functionality (experts only)");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000714#endif
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000715 } else if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000716 puts("a\tselect bootable partition"); /* sgi flavour */
717 puts("b\tedit bootfile entry"); /* sgi */
718 puts("c\tselect sgi swap partition"); /* sgi flavour */
719 puts("d\tdelete a partition");
720 puts("l\tlist known partition types");
721 puts("n\tadd a new partition");
722 puts("o\tcreate a new empty DOS partition table");
723 puts("p\tprint the partition table");
724 puts("q\tquit without saving changes");
725 puts("s\tcreate a new empty Sun disklabel"); /* sun */
726 puts("t\tchange a partition's system id");
727 puts("u\tchange display/entry units");
728 puts("v\tverify the partition table");
729 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000730 } else if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000731 puts("o\tcreate a new empty DOS partition table");
732 puts("q\tquit without saving changes");
733 puts("s\tcreate a new empty Sun disklabel"); /* sun */
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000734 } else {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000735 puts("a\ttoggle a bootable flag");
736 puts("b\tedit bsd disklabel");
737 puts("c\ttoggle the dos compatibility flag");
738 puts("d\tdelete a partition");
739 puts("l\tlist known partition types");
740 puts("n\tadd a new partition");
741 puts("o\tcreate a new empty DOS partition table");
742 puts("p\tprint the partition table");
743 puts("q\tquit without saving changes");
744 puts("s\tcreate a new empty Sun disklabel"); /* sun */
745 puts("t\tchange a partition's system id");
746 puts("u\tchange display/entry units");
747 puts("v\tverify the partition table");
748 puts("w\twrite table to disk and exit");
Denis Vlasenko834410a2006-11-29 12:00:28 +0000749#if ENABLE_FEATURE_FDISK_ADVANCED
Denis Vlasenkobd852072007-03-19 14:43:38 +0000750 puts("x\textra functionality (experts only)");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000751#endif
752 }
753}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000754#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000755
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000756
Denis Vlasenko834410a2006-11-29 12:00:28 +0000757#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000758static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000759xmenu(void)
760{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000761 puts("Command Action");
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000762 if (LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000763 puts("a\tchange number of alternate cylinders"); /*sun*/
764 puts("c\tchange number of cylinders");
765 puts("d\tprint the raw data in the partition table");
766 puts("e\tchange number of extra sectors per cylinder");/*sun*/
767 puts("h\tchange number of heads");
768 puts("i\tchange interleave factor"); /*sun*/
769 puts("o\tchange rotation speed (rpm)"); /*sun*/
770 puts("p\tprint the partition table");
771 puts("q\tquit without saving changes");
772 puts("r\treturn to main menu");
773 puts("s\tchange number of sectors/track");
774 puts("v\tverify the partition table");
775 puts("w\twrite table to disk and exit");
776 puts("y\tchange number of physical cylinders"); /*sun*/
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000777 } else if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000778 puts("b\tmove beginning of data in a partition"); /* !sun */
779 puts("c\tchange number of cylinders");
780 puts("d\tprint the raw data in the partition table");
781 puts("e\tlist extended partitions"); /* !sun */
782 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
783 puts("h\tchange number of heads");
784 puts("p\tprint the partition table");
785 puts("q\tquit without saving changes");
786 puts("r\treturn to main menu");
787 puts("s\tchange number of sectors/track");
788 puts("v\tverify the partition table");
789 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000790 } else if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000791 puts("b\tmove beginning of data in a partition"); /* !sun */
792 puts("c\tchange number of cylinders");
793 puts("d\tprint the raw data in the partition table");
794 puts("e\tlist extended partitions"); /* !sun */
795 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
796 puts("h\tchange number of heads");
797 puts("p\tprint the partition table");
798 puts("q\tquit without saving changes");
799 puts("r\treturn to main menu");
800 puts("s\tchange number of sectors/track");
801 puts("v\tverify the partition table");
802 puts("w\twrite table to disk and exit");
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000803 } else {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000804 puts("b\tmove beginning of data in a partition"); /* !sun */
805 puts("c\tchange number of cylinders");
806 puts("d\tprint the raw data in the partition table");
807 puts("e\tlist extended partitions"); /* !sun */
808 puts("f\tfix partition order"); /* !sun, !aix, !sgi */
Denis Vlasenko834410a2006-11-29 12:00:28 +0000809#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenkobd852072007-03-19 14:43:38 +0000810 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000811#endif
Denis Vlasenkobd852072007-03-19 14:43:38 +0000812 puts("h\tchange number of heads");
813 puts("p\tprint the partition table");
814 puts("q\tquit without saving changes");
815 puts("r\treturn to main menu");
816 puts("s\tchange number of sectors/track");
817 puts("v\tverify the partition table");
818 puts("w\twrite table to disk and exit");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000819 }
820}
821#endif /* ADVANCED mode */
822
Denis Vlasenko834410a2006-11-29 12:00:28 +0000823#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenkobd852072007-03-19 14:43:38 +0000824static const char *const *
Rob Landleyb73451d2006-02-24 16:29:00 +0000825get_sys_types(void)
826{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000827 return (
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000828 LABEL_IS_SUN ? sun_sys_types :
829 LABEL_IS_SGI ? sgi_sys_types :
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000830 i386_sys_types);
831}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000832#else
833#define get_sys_types() i386_sys_types
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000834#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000835
Denis Vlasenkobd852072007-03-19 14:43:38 +0000836static const char *
837partition_type(unsigned char type)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000838{
839 int i;
Denis Vlasenkobd852072007-03-19 14:43:38 +0000840 const char *const *types = get_sys_types();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000841
Denis Vlasenkobd852072007-03-19 14:43:38 +0000842 for (i = 0; types[i]; i++)
843 if ((unsigned char)types[i][0] == type)
844 return types[i] + 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000845
Denis Vlasenkobd852072007-03-19 14:43:38 +0000846 return "Unknown";
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000847}
848
849
Denis Vlasenko834410a2006-11-29 12:00:28 +0000850#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000851static int
Rob Landleyb73451d2006-02-24 16:29:00 +0000852get_sysid(int i)
853{
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000854 return LABEL_IS_SUN ? sunlabel->infos[i].id :
855 (LABEL_IS_SGI ? sgi_get_sysid(i) :
856 ptes[i].part_table->sys_ind);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000857}
858
Denis Vlasenkobd852072007-03-19 14:43:38 +0000859static void
860list_types(const char *const *sys)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000861{
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000862 enum { COLS = 3 };
863
864 unsigned last[COLS];
865 unsigned done, next, size;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000866 int i;
867
Denis Vlasenkobd852072007-03-19 14:43:38 +0000868 for (size = 0; sys[size]; size++) /* */;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000869
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000870 done = 0;
871 for (i = COLS-1; i >= 0; i--) {
872 done += (size + i - done) / (i + 1);
873 last[COLS-1 - i] = done;
874 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000875
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000876 i = done = next = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000877 do {
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000878 printf("%c%2x %-22.22s", i ? ' ' : '\n',
Denis Vlasenkobd852072007-03-19 14:43:38 +0000879 (unsigned char)sys[next][0],
880 sys[next] + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000881 next = last[i++] + done;
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000882 if (i >= COLS || next >= last[i]) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000883 i = 0;
884 next = ++done;
885 }
886 } while (done < last[0]);
887 putchar('\n');
888}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +0000889#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000890
891static int
Rob Landleyb73451d2006-02-24 16:29:00 +0000892is_cleared_partition(const struct partition *p)
893{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000894 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
895 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
896 get_start_sect(p) || get_nr_sects(p));
897}
898
899static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000900clear_partition(struct partition *p)
901{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000902 if (!p)
903 return;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000904 memset(p, 0, sizeof(struct partition));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000905}
906
Denis Vlasenko834410a2006-11-29 12:00:28 +0000907#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000908static void
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000909set_partition(int i, int doext, ullong start, ullong stop, int sysid)
Rob Landleyb73451d2006-02-24 16:29:00 +0000910{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000911 struct partition *p;
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +0000912 ullong offset;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000913
914 if (doext) {
915 p = ptes[i].ext_pointer;
916 offset = extended_offset;
917 } else {
918 p = ptes[i].part_table;
919 offset = ptes[i].offset;
920 }
921 p->boot_ind = 0;
922 p->sys_ind = sysid;
923 set_start_sect(p, start - offset);
924 set_nr_sects(p, stop - start + 1);
925 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
926 start = heads*sectors*1024 - 1;
927 set_hsc(p->head, p->sector, p->cyl, start);
928 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
929 stop = heads*sectors*1024 - 1;
930 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
931 ptes[i].changed = 1;
932}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000933#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000934
935static int
Rob Landleyb73451d2006-02-24 16:29:00 +0000936warn_geometry(void)
937{
Denis Vlasenkobd852072007-03-19 14:43:38 +0000938 if (heads && sectors && cylinders)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000939 return 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000940
Denis Vlasenkobd852072007-03-19 14:43:38 +0000941 printf("Unknown value(s) for:");
942 if (!heads)
943 printf(" heads");
944 if (!sectors)
945 printf(" sectors");
946 if (!cylinders)
947 printf(" cylinders");
948 printf(
Denis Vlasenko834410a2006-11-29 12:00:28 +0000949#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenkobd852072007-03-19 14:43:38 +0000950 " (settable in the extra functions menu)"
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000951#endif
Denis Vlasenkobd852072007-03-19 14:43:38 +0000952 "\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000953 return 1;
954}
955
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +0000956static void
957update_units(void)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000958{
959 int cyl_units = heads * sectors;
960
961 if (display_in_cyl_units && cyl_units)
962 units_per_sector = cyl_units;
963 else
964 units_per_sector = 1; /* in sectors */
965}
966
Denis Vlasenko834410a2006-11-29 12:00:28 +0000967#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000968static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000969warn_cylinders(void)
970{
Denis Vlasenko98ae2162006-10-12 19:30:44 +0000971 if (LABEL_IS_DOS && cylinders > 1024 && !nowarn)
Denis Vlasenkobd852072007-03-19 14:43:38 +0000972 printf("\n"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000973"The number of cylinders for this disk is set to %d.\n"
974"There is nothing wrong with that, but this is larger than 1024,\n"
975"and could in certain setups cause problems with:\n"
976"1) software that runs at boot time (e.g., old versions of LILO)\n"
977"2) booting and partitioning software from other OSs\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +0000978" (e.g., DOS FDISK, OS/2 FDISK)\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000979 cylinders);
980}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +0000981#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000982
983static void
Rob Landleyb73451d2006-02-24 16:29:00 +0000984read_extended(int ext)
985{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000986 int i;
987 struct pte *pex;
988 struct partition *p, *q;
989
990 ext_index = ext;
991 pex = &ptes[ext];
992 pex->ext_pointer = pex->part_table;
993
994 p = pex->part_table;
995 if (!get_start_sect(p)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +0000996 printf("Bad offset in primary extended partition\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +0000997 return;
998 }
999
Rob Landleyb73451d2006-02-24 16:29:00 +00001000 while (IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001001 struct pte *pe = &ptes[partitions];
1002
1003 if (partitions >= MAXIMUM_PARTS) {
1004 /* This is not a Linux restriction, but
1005 this program uses arrays of size MAXIMUM_PARTS.
Denis Vlasenko89f0b342006-11-18 22:04:09 +00001006 Do not try to 'improve' this test. */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001007 struct pte *pre = &ptes[partitions-1];
Denis Vlasenko834410a2006-11-29 12:00:28 +00001008#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenkobd852072007-03-19 14:43:38 +00001009 printf("Warning: deleting partitions after %d\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001010 partitions);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001011 pre->changed = 1;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001012#endif
1013 clear_partition(pre->ext_pointer);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001014 return;
1015 }
1016
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001017 read_pte(pe, extended_offset + get_start_sect(p));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001018
1019 if (!extended_offset)
1020 extended_offset = get_start_sect(p);
1021
1022 q = p = pt_offset(pe->sectorbuffer, 0);
1023 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001024 if (IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001025 if (pe->ext_pointer)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001026 printf("Warning: extra link "
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001027 "pointer in partition table"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001028 " %d\n", partitions + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001029 else
1030 pe->ext_pointer = p;
1031 } else if (p->sys_ind) {
1032 if (pe->part_table)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001033 printf("Warning: ignoring extra "
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001034 "data in partition table"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001035 " %d\n", partitions + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001036 else
1037 pe->part_table = p;
1038 }
1039 }
1040
1041 /* very strange code here... */
1042 if (!pe->part_table) {
1043 if (q != pe->ext_pointer)
1044 pe->part_table = q;
1045 else
1046 pe->part_table = q + 1;
1047 }
1048 if (!pe->ext_pointer) {
1049 if (q != pe->part_table)
1050 pe->ext_pointer = q;
1051 else
1052 pe->ext_pointer = q + 1;
1053 }
1054
1055 p = pe->ext_pointer;
1056 partitions++;
1057 }
1058
Denis Vlasenko834410a2006-11-29 12:00:28 +00001059#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001060 /* remove empty links */
1061 remove:
1062 for (i = 4; i < partitions; i++) {
1063 struct pte *pe = &ptes[i];
1064
Denis Vlasenkobd852072007-03-19 14:43:38 +00001065 if (!get_nr_sects(pe->part_table)
1066 && (partitions > 5 || ptes[4].part_table->sys_ind)
1067 ) {
1068 printf("Omitting empty partition (%d)\n", i+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001069 delete_partition(i);
1070 goto remove; /* numbering changed */
1071 }
1072 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001073#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001074}
1075
Denis Vlasenko834410a2006-11-29 12:00:28 +00001076#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001077static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001078create_doslabel(void)
1079{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001080 int i;
1081
Denis Vlasenkobd852072007-03-19 14:43:38 +00001082 printf(msg_building_new_label, "DOS disklabel");
Rob Landley5527b912006-02-25 03:46:10 +00001083
1084 current_label_type = label_dos;
1085
Denis Vlasenko834410a2006-11-29 12:00:28 +00001086#if ENABLE_FEATURE_OSF_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001087 possibly_osf_label = 0;
1088#endif
1089 partitions = 4;
1090
1091 for (i = 510-64; i < 510; i++)
1092 MBRbuffer[i] = 0;
1093 write_part_table_flag(MBRbuffer);
1094 extended_offset = 0;
1095 set_all_unchanged();
1096 set_changed(0);
1097 get_boot(create_empty_dos);
1098}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001099#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001100
1101static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001102get_sectorsize(void)
1103{
Rob Landley736e5252006-02-25 03:36:00 +00001104 if (!user_set_sector_size) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001105 int arg;
1106 if (ioctl(fd, BLKSSZGET, &arg) == 0)
1107 sector_size = arg;
1108 if (sector_size != DEFAULT_SECTOR_SIZE)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001109 printf("Note: sector size is %d (not %d)\n",
Rob Landleyb73451d2006-02-24 16:29:00 +00001110 sector_size, DEFAULT_SECTOR_SIZE);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001111 }
1112}
1113
Rob Landley88621d72006-08-29 19:41:06 +00001114static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001115get_kernel_geometry(void)
1116{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001117 struct hd_geometry geometry;
1118
1119 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
1120 kern_heads = geometry.heads;
1121 kern_sectors = geometry.sectors;
1122 /* never use geometry.cylinders - it is truncated */
1123 }
1124}
1125
1126static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001127get_partition_table_geometry(void)
1128{
"Vladimir N. Oleynik"a972c872005-12-02 10:06:04 +00001129 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001130 struct partition *p;
1131 int i, h, s, hh, ss;
1132 int first = 1;
1133 int bad = 0;
1134
Eric Andersen3496fdc2006-01-30 23:09:20 +00001135 if (!(valid_part_table_flag((char*)bufp)))
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001136 return;
1137
1138 hh = ss = 0;
Rob Landleyb73451d2006-02-24 16:29:00 +00001139 for (i = 0; i < 4; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001140 p = pt_offset(bufp, i);
1141 if (p->sys_ind != 0) {
1142 h = p->end_head + 1;
1143 s = (p->end_sector & 077);
1144 if (first) {
1145 hh = h;
1146 ss = s;
1147 first = 0;
1148 } else if (hh != h || ss != s)
1149 bad = 1;
1150 }
1151 }
1152
1153 if (!first && !bad) {
1154 pt_heads = hh;
1155 pt_sectors = ss;
1156 }
1157}
1158
Rob Landleyb73451d2006-02-24 16:29:00 +00001159static void
1160get_geometry(void)
1161{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001162 int sec_fac;
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001163 uint64_t v64;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001164
1165 get_sectorsize();
1166 sec_fac = sector_size / 512;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001167#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001168 guess_device_type();
1169#endif
1170 heads = cylinders = sectors = 0;
1171 kern_heads = kern_sectors = 0;
1172 pt_heads = pt_sectors = 0;
1173
1174 get_kernel_geometry();
1175 get_partition_table_geometry();
1176
1177 heads = user_heads ? user_heads :
1178 pt_heads ? pt_heads :
1179 kern_heads ? kern_heads : 255;
1180 sectors = user_sectors ? user_sectors :
1181 pt_sectors ? pt_sectors :
1182 kern_sectors ? kern_sectors : 63;
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001183 if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
1184 /* got bytes, convert to 512 byte sectors */
1185 total_number_of_sectors = (v64 >> 9);
Eric Andersen040f4402003-07-30 08:40:37 +00001186 } else {
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001187 unsigned long longsectors; /* need temp of type long */
1188 if (ioctl(fd, BLKGETSIZE, &longsectors))
1189 longsectors = 0;
1190 total_number_of_sectors = longsectors;
Eric Andersen040f4402003-07-30 08:40:37 +00001191 }
1192
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001193 sector_offset = 1;
1194 if (dos_compatible_flag)
1195 sector_offset = sectors;
1196
Eric Andersen040f4402003-07-30 08:40:37 +00001197 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001198 if (!cylinders)
1199 cylinders = user_cylinders;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001200}
1201
1202/*
1203 * Read MBR. Returns:
1204 * -1: no 0xaa55 flag present (possibly entire disk BSD)
1205 * 0: found or created label
1206 * 1: I/O error
1207 */
Rob Landleyb73451d2006-02-24 16:29:00 +00001208static int
1209get_boot(enum action what)
1210{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001211 int i;
1212
1213 partitions = 4;
1214
1215 for (i = 0; i < 4; i++) {
1216 struct pte *pe = &ptes[i];
1217
1218 pe->part_table = pt_offset(MBRbuffer, i);
1219 pe->ext_pointer = NULL;
1220 pe->offset = 0;
1221 pe->sectorbuffer = MBRbuffer;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001222#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001223 pe->changed = (what == create_empty_dos);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001224#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001225 }
1226
Denis Vlasenko834410a2006-11-29 12:00:28 +00001227#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001228 if (what == create_empty_sun && check_sun_label())
1229 return 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001230#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001231
1232 memset(MBRbuffer, 0, 512);
1233
Denis Vlasenko834410a2006-11-29 12:00:28 +00001234#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001235 if (what == create_empty_dos)
1236 goto got_dos_table; /* skip reading disk */
1237
Denis Vlasenkobd852072007-03-19 14:43:38 +00001238 fd = open(disk_device, type_open);
1239 if (fd < 0) {
1240 fd = open(disk_device, O_RDONLY);
1241 if (fd < 0) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001242 if (what == try_only)
1243 return 1;
1244 fdisk_fatal(unable_to_open);
1245 } else
Denis Vlasenkobd852072007-03-19 14:43:38 +00001246 printf("You will not be able to write "
1247 "the partition table\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001248 }
1249
1250 if (512 != read(fd, MBRbuffer, 512)) {
1251 if (what == try_only)
1252 return 1;
1253 fdisk_fatal(unable_to_read);
1254 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001255#else
Denis Vlasenkobd852072007-03-19 14:43:38 +00001256 fd = open(disk_device, O_RDONLY);
1257 if (fd < 0)
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001258 return 1;
1259 if (512 != read(fd, MBRbuffer, 512))
1260 return 1;
1261#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001262
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001263 get_geometry();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001264
1265 update_units();
1266
Denis Vlasenko834410a2006-11-29 12:00:28 +00001267#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001268 if (check_sun_label())
1269 return 0;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001270#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001271
Denis Vlasenko834410a2006-11-29 12:00:28 +00001272#if ENABLE_FEATURE_SGI_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001273 if (check_sgi_label())
1274 return 0;
1275#endif
1276
Denis Vlasenko834410a2006-11-29 12:00:28 +00001277#if ENABLE_FEATURE_AIX_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001278 if (check_aix_label())
1279 return 0;
1280#endif
1281
Denis Vlasenko834410a2006-11-29 12:00:28 +00001282#if ENABLE_FEATURE_OSF_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001283 if (check_osf_label()) {
1284 possibly_osf_label = 1;
1285 if (!valid_part_table_flag(MBRbuffer)) {
Rob Landley5527b912006-02-25 03:46:10 +00001286 current_label_type = label_osf;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001287 return 0;
1288 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001289 printf("This disk has both DOS and BSD magic.\n"
1290 "Give the 'b' command to go to BSD mode.\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001291 }
1292#endif
1293
Denis Vlasenko834410a2006-11-29 12:00:28 +00001294#if ENABLE_FEATURE_FDISK_WRITABLE
Rob Landleyb73451d2006-02-24 16:29:00 +00001295 got_dos_table:
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001296#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001297
1298 if (!valid_part_table_flag(MBRbuffer)) {
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001299#if !ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001300 return -1;
1301#else
Rob Landleyb73451d2006-02-24 16:29:00 +00001302 switch (what) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001303 case fdisk:
Denis Vlasenkobd852072007-03-19 14:43:38 +00001304 printf("Device contains neither a valid DOS "
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001305 "partition table, nor Sun, SGI or OSF "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001306 "disklabel\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001307#ifdef __sparc__
Denis Vlasenko834410a2006-11-29 12:00:28 +00001308#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001309 create_sunlabel();
1310#endif
1311#else
1312 create_doslabel();
1313#endif
1314 return 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001315 case try_only:
1316 return -1;
1317 case create_empty_dos:
Denis Vlasenko834410a2006-11-29 12:00:28 +00001318#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001319 case create_empty_sun:
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001320#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001321 break;
1322 default:
Denis Vlasenkobd852072007-03-19 14:43:38 +00001323 bb_error_msg_and_die("internal error");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001324 }
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001325#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001326 }
1327
Denis Vlasenko834410a2006-11-29 12:00:28 +00001328#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001329 warn_cylinders();
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001330#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001331 warn_geometry();
1332
1333 for (i = 0; i < 4; i++) {
1334 struct pte *pe = &ptes[i];
1335
Rob Landleyb73451d2006-02-24 16:29:00 +00001336 if (IS_EXTENDED(pe->part_table->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001337 if (partitions != 4)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001338 printf("Ignoring extra extended "
1339 "partition %d\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001340 else
1341 read_extended(i);
1342 }
1343 }
1344
1345 for (i = 3; i < partitions; i++) {
1346 struct pte *pe = &ptes[i];
1347
1348 if (!valid_part_table_flag(pe->sectorbuffer)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001349 printf("Warning: invalid flag 0x%02x,0x%02x of partition "
1350 "table %d will be corrected by w(rite)\n",
Denis Vlasenko834410a2006-11-29 12:00:28 +00001351 pe->sectorbuffer[510],
1352 pe->sectorbuffer[511],
1353 i + 1);
1354#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001355 pe->changed = 1;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001356#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001357 }
1358 }
1359
1360 return 0;
1361}
1362
Denis Vlasenko834410a2006-11-29 12:00:28 +00001363#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001364/*
1365 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
1366 * If the user hits Enter, DFLT is returned.
1367 * Answers like +10 are interpreted as offsets from BASE.
1368 *
1369 * There is no default if DFLT is not between LOW and HIGH.
1370 */
Denis Vlasenko834410a2006-11-29 12:00:28 +00001371static unsigned
Denis Vlasenko06c0a712007-01-29 22:51:44 +00001372read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001373{
Denis Vlasenko834410a2006-11-29 12:00:28 +00001374 unsigned i;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001375 int default_ok = 1;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001376 const char *fmt = "%s (%u-%u, default %u): ";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001377
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001378 if (dflt < low || dflt > high) {
1379 fmt = "%s (%u-%u): ";
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001380 default_ok = 0;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001381 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001382
1383 while (1) {
1384 int use_default = default_ok;
1385
1386 /* ask question and read answer */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001387 do {
1388 printf(fmt, mesg, low, high, dflt);
1389 read_maybe_empty("");
1390 } while (*line_ptr != '\n' && !isdigit(*line_ptr)
1391 && *line_ptr != '-' && *line_ptr != '+');
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001392
Eric Andersen84bdea82004-05-19 10:49:17 +00001393 if (*line_ptr == '+' || *line_ptr == '-') {
Rob Landleyb73451d2006-02-24 16:29:00 +00001394 int minus = (*line_ptr == '-');
1395 int absolute = 0;
Eric Andersenc48d49a2003-07-03 10:02:32 +00001396
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001397 i = atoi(line_ptr + 1);
Eric Andersenc48d49a2003-07-03 10:02:32 +00001398
Rob Landleyb73451d2006-02-24 16:29:00 +00001399 while (isdigit(*++line_ptr))
1400 use_default = 0;
Eric Andersen84bdea82004-05-19 10:49:17 +00001401
Rob Landleyb73451d2006-02-24 16:29:00 +00001402 switch (*line_ptr) {
1403 case 'c':
1404 case 'C':
1405 if (!display_in_cyl_units)
1406 i *= heads * sectors;
1407 break;
1408 case 'K':
1409 absolute = 1024;
1410 break;
1411 case 'k':
1412 absolute = 1000;
1413 break;
1414 case 'm':
1415 case 'M':
1416 absolute = 1000000;
1417 break;
1418 case 'g':
1419 case 'G':
1420 absolute = 1000000000;
1421 break;
1422 default:
1423 break;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001424 }
Rob Landleyb73451d2006-02-24 16:29:00 +00001425 if (absolute) {
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001426 ullong bytes;
Rob Landleyb73451d2006-02-24 16:29:00 +00001427 unsigned long unit;
1428
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001429 bytes = (ullong) i * absolute;
Rob Landleyb73451d2006-02-24 16:29:00 +00001430 unit = sector_size * units_per_sector;
1431 bytes += unit/2; /* round */
1432 bytes /= unit;
1433 i = bytes;
1434 }
1435 if (minus)
1436 i = -i;
1437 i += base;
Eric Andersen84bdea82004-05-19 10:49:17 +00001438 } else {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001439 i = atoi(line_ptr);
1440 while (isdigit(*line_ptr)) {
1441 line_ptr++;
1442 use_default = 0;
1443 }
1444 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001445 if (use_default) {
1446 i = dflt;
1447 printf("Using default value %u\n", i);
1448 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001449 if (i >= low && i <= high)
1450 break;
Denis Vlasenkobd852072007-03-19 14:43:38 +00001451 printf("Value is out of range\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001452 }
1453 return i;
1454}
1455
Rob Landleyb73451d2006-02-24 16:29:00 +00001456static int
1457get_partition(int warn, int max)
1458{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001459 struct pte *pe;
1460 int i;
1461
Denis Vlasenkobd852072007-03-19 14:43:38 +00001462 i = read_int(1, 0, max, 0, "Partition number") - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001463 pe = &ptes[i];
1464
1465 if (warn) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001466 if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind)
1467 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
1468 || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
1469 ) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001470 printf("Warning: partition %d has empty type\n", i+1);
Rob Landley5527b912006-02-25 03:46:10 +00001471 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001472 }
1473 return i;
1474}
1475
1476static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001477get_existing_partition(int warn, int max)
1478{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001479 int pno = -1;
1480 int i;
1481
1482 for (i = 0; i < max; i++) {
1483 struct pte *pe = &ptes[i];
1484 struct partition *p = pe->part_table;
1485
1486 if (p && !is_cleared_partition(p)) {
1487 if (pno >= 0)
1488 goto not_unique;
1489 pno = i;
1490 }
1491 }
1492 if (pno >= 0) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001493 printf("Selected partition %d\n", pno+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001494 return pno;
1495 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001496 printf("No partition is defined yet!\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001497 return -1;
1498
1499 not_unique:
1500 return get_partition(warn, max);
1501}
1502
1503static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001504get_nonexisting_partition(int warn, int max)
1505{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001506 int pno = -1;
1507 int i;
1508
1509 for (i = 0; i < max; i++) {
1510 struct pte *pe = &ptes[i];
1511 struct partition *p = pe->part_table;
1512
1513 if (p && is_cleared_partition(p)) {
1514 if (pno >= 0)
1515 goto not_unique;
1516 pno = i;
1517 }
1518 }
1519 if (pno >= 0) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001520 printf("Selected partition %d\n", pno+1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001521 return pno;
1522 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001523 printf("All primary partitions have been defined already!\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001524 return -1;
1525
1526 not_unique:
1527 return get_partition(warn, max);
1528}
1529
1530
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001531static void
1532change_units(void)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001533{
1534 display_in_cyl_units = !display_in_cyl_units;
1535 update_units();
Denis Vlasenkobd852072007-03-19 14:43:38 +00001536 printf("Changing display/entry units to %s\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001537 str_units(PLURAL));
1538}
1539
1540static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001541toggle_active(int i)
1542{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001543 struct pte *pe = &ptes[i];
1544 struct partition *p = pe->part_table;
1545
Rob Landleyb73451d2006-02-24 16:29:00 +00001546 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001547 printf("WARNING: Partition %d is an extended partition\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001548 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1549 pe->changed = 1;
1550}
1551
1552static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001553toggle_dos_compatibility_flag(void)
1554{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001555 dos_compatible_flag = ~dos_compatible_flag;
1556 if (dos_compatible_flag) {
1557 sector_offset = sectors;
Denis Vlasenkobd852072007-03-19 14:43:38 +00001558 printf("DOS Compatibility flag is set\n");
1559 } else {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001560 sector_offset = 1;
Denis Vlasenkobd852072007-03-19 14:43:38 +00001561 printf("DOS Compatibility flag is not set\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001562 }
1563}
1564
1565static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001566delete_partition(int i)
1567{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001568 struct pte *pe = &ptes[i];
1569 struct partition *p = pe->part_table;
1570 struct partition *q = pe->ext_pointer;
1571
1572/* Note that for the fifth partition (i == 4) we don't actually
1573 * decrement partitions.
1574 */
1575
1576 if (warn_geometry())
1577 return; /* C/H/S not set */
1578 pe->changed = 1;
1579
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001580 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001581 sun_delete_partition(i);
1582 return;
1583 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001584 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001585 sgi_delete_partition(i);
1586 return;
1587 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001588
1589 if (i < 4) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001590 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001591 partitions = 4;
1592 ptes[ext_index].ext_pointer = NULL;
1593 extended_offset = 0;
1594 }
1595 clear_partition(p);
1596 return;
1597 }
1598
1599 if (!q->sys_ind && i > 4) {
1600 /* the last one in the chain - just delete */
1601 --partitions;
1602 --i;
1603 clear_partition(ptes[i].ext_pointer);
1604 ptes[i].changed = 1;
1605 } else {
1606 /* not the last one - further ones will be moved down */
1607 if (i > 4) {
1608 /* delete this link in the chain */
1609 p = ptes[i-1].ext_pointer;
1610 *p = *q;
1611 set_start_sect(p, get_start_sect(q));
1612 set_nr_sects(p, get_nr_sects(q));
1613 ptes[i-1].changed = 1;
1614 } else if (partitions > 5) { /* 5 will be moved to 4 */
1615 /* the first logical in a longer chain */
1616 pe = &ptes[5];
1617
1618 if (pe->part_table) /* prevent SEGFAULT */
1619 set_start_sect(pe->part_table,
Rob Landleyb73451d2006-02-24 16:29:00 +00001620 get_partition_start(pe) -
1621 extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001622 pe->offset = extended_offset;
1623 pe->changed = 1;
1624 }
1625
1626 if (partitions > 5) {
1627 partitions--;
1628 while (i < partitions) {
1629 ptes[i] = ptes[i+1];
1630 i++;
1631 }
1632 } else
1633 /* the only logical: clear only */
1634 clear_partition(ptes[i].part_table);
1635 }
1636}
1637
1638static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001639change_sysid(void)
1640{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001641 int i, sys, origsys;
1642 struct partition *p;
1643
Eric Andersen040f4402003-07-30 08:40:37 +00001644 /* If sgi_label then don't use get_existing_partition,
1645 let the user select a partition, since get_existing_partition()
1646 only works for Linux like partition tables. */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001647 if (!LABEL_IS_SGI) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001648 i = get_existing_partition(0, partitions);
Eric Andersen040f4402003-07-30 08:40:37 +00001649 } else {
1650 i = get_partition(0, partitions);
1651 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001652 if (i == -1)
1653 return;
1654 p = ptes[i].part_table;
1655 origsys = sys = get_sysid(i);
1656
1657 /* if changing types T to 0 is allowed, then
1658 the reverse change must be allowed, too */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001659 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001660 printf("Partition %d does not exist yet!\n", i + 1);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001661 return;
1662 }
1663 while (1) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001664 sys = read_hex(get_sys_types());
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001665
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001666 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001667 printf("Type 0 means free space to many systems\n"
Rob Landleyb73451d2006-02-24 16:29:00 +00001668 "(but not to Linux). Having partitions of\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001669 "type 0 is probably unwise.\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001670 /* break; */
1671 }
1672
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001673 if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
Rob Landleyb73451d2006-02-24 16:29:00 +00001674 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001675 printf("You cannot change a partition into"
1676 " an extended one or vice versa\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001677 break;
1678 }
1679 }
1680
1681 if (sys < 256) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001682#if ENABLE_FEATURE_SUN_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001683 if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001684 printf("Consider leaving partition 3 "
Rob Landleyb73451d2006-02-24 16:29:00 +00001685 "as Whole disk (5),\n"
1686 "as SunOS/Solaris expects it and "
Denis Vlasenkobd852072007-03-19 14:43:38 +00001687 "even Linux likes it\n\n");
1688#endif
1689#if ENABLE_FEATURE_SGI_LABEL
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001690 if (LABEL_IS_SGI &&
Rob Landley5527b912006-02-25 03:46:10 +00001691 (
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001692 (i == 10 && sys != SGI_ENTIRE_DISK) ||
Rob Landley5527b912006-02-25 03:46:10 +00001693 (i == 8 && sys != 0)
1694 )
Denis Vlasenkobd852072007-03-19 14:43:38 +00001695 ) {
1696 printf("Consider leaving partition 9 "
Rob Landleyb73451d2006-02-24 16:29:00 +00001697 "as volume header (0),\nand "
1698 "partition 11 as entire volume (6)"
Denis Vlasenkobd852072007-03-19 14:43:38 +00001699 "as IRIX expects it\n\n");
Rob Landley5527b912006-02-25 03:46:10 +00001700 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00001701#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001702 if (sys == origsys)
1703 break;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001704 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001705 sun_change_sysid(i, sys);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001706 } else if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001707 sgi_change_sysid(i, sys);
1708 } else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001709 p->sys_ind = sys;
Rob Landley5527b912006-02-25 03:46:10 +00001710
Denis Vlasenkobd852072007-03-19 14:43:38 +00001711 printf("Changed system type of partition %d "
1712 "to %x (%s)\n", i + 1, sys,
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001713 partition_type(sys));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001714 ptes[i].changed = 1;
1715 if (is_dos_partition(origsys) ||
Rob Landleyb73451d2006-02-24 16:29:00 +00001716 is_dos_partition(sys))
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001717 dos_changed = 1;
1718 break;
1719 }
1720 }
1721}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00001722#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00001723
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001724
Denis Vlasenko28703012006-12-19 20:32:02 +00001725/* check_consistency() and linear2chs() added Sat Mar 6 12:28:16 1993,
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001726 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1727 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1728 * Lubkin Oct. 1991). */
1729
Rob Landleyb73451d2006-02-24 16:29:00 +00001730static void
Denis Vlasenko28703012006-12-19 20:32:02 +00001731linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
Rob Landleyb73451d2006-02-24 16:29:00 +00001732{
1733 int spc = heads * sectors;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001734
1735 *c = ls / spc;
1736 ls = ls % spc;
1737 *h = ls / sectors;
1738 *s = ls % sectors + 1; /* sectors count from 1 */
1739}
1740
Rob Landleyb73451d2006-02-24 16:29:00 +00001741static void
1742check_consistency(const struct partition *p, int partition)
1743{
Denis Vlasenko834410a2006-11-29 12:00:28 +00001744 unsigned pbc, pbh, pbs; /* physical beginning c, h, s */
1745 unsigned pec, peh, pes; /* physical ending c, h, s */
1746 unsigned lbc, lbh, lbs; /* logical beginning c, h, s */
1747 unsigned lec, leh, les; /* logical ending c, h, s */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001748
1749 if (!heads || !sectors || (partition >= 4))
1750 return; /* do not check extended partitions */
1751
1752/* physical beginning c, h, s */
1753 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
1754 pbh = p->head;
1755 pbs = p->sector & 0x3f;
1756
1757/* physical ending c, h, s */
1758 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
1759 peh = p->end_head;
1760 pes = p->end_sector & 0x3f;
1761
1762/* compute logical beginning (c, h, s) */
Denis Vlasenko28703012006-12-19 20:32:02 +00001763 linear2chs(get_start_sect(p), &lbc, &lbh, &lbs);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001764
1765/* compute logical ending (c, h, s) */
Denis Vlasenko28703012006-12-19 20:32:02 +00001766 linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001767
1768/* Same physical / logical beginning? */
1769 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001770 printf("Partition %d has different physical/logical "
1771 "beginnings (non-Linux?):\n", partition + 1);
1772 printf(" phys=(%d, %d, %d) ", pbc, pbh, pbs);
1773 printf("logical=(%d, %d, %d)\n",lbc, lbh, lbs);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001774 }
1775
1776/* Same physical / logical ending? */
1777 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001778 printf("Partition %d has different physical/logical "
1779 "endings:\n", partition + 1);
1780 printf(" phys=(%d, %d, %d) ", pec, peh, pes);
1781 printf("logical=(%d, %d, %d)\n", lec, leh, les);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001782 }
1783
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001784/* Ending on cylinder boundary? */
1785 if (peh != (heads - 1) || pes != sectors) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001786 printf("Partition %i does not end on cylinder boundary\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001787 partition + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001788 }
1789}
1790
1791static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001792list_disk_geometry(void)
1793{
Eric Andersen040f4402003-07-30 08:40:37 +00001794 long long bytes = (total_number_of_sectors << 9);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001795 long megabytes = bytes/1000000;
1796
1797 if (megabytes < 10000)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001798 printf("\nDisk %s: %ld MB, %lld bytes\n",
Rob Landleyb73451d2006-02-24 16:29:00 +00001799 disk_device, megabytes, bytes);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001800 else
Denis Vlasenkobd852072007-03-19 14:43:38 +00001801 printf("\nDisk %s: %ld.%ld GB, %lld bytes\n",
Rob Landleyb73451d2006-02-24 16:29:00 +00001802 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
Denis Vlasenkobd852072007-03-19 14:43:38 +00001803 printf("%d heads, %d sectors/track, %d cylinders",
Rob Landleyb73451d2006-02-24 16:29:00 +00001804 heads, sectors, cylinders);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001805 if (units_per_sector == 1)
Denis Vlasenkobd852072007-03-19 14:43:38 +00001806 printf(", total %llu sectors",
Rob Landleyb73451d2006-02-24 16:29:00 +00001807 total_number_of_sectors / (sector_size/512));
Denis Vlasenkobd852072007-03-19 14:43:38 +00001808 printf("\nUnits = %s of %d * %d = %d bytes\n\n",
Rob Landleyb73451d2006-02-24 16:29:00 +00001809 str_units(PLURAL),
1810 units_per_sector, sector_size, units_per_sector * sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001811}
1812
1813/*
1814 * Check whether partition entries are ordered by their starting positions.
1815 * Return 0 if OK. Return i if partition i should have been earlier.
1816 * Two separate checks: primary and logical partitions.
1817 */
1818static int
Rob Landleyb73451d2006-02-24 16:29:00 +00001819wrong_p_order(int *prev)
1820{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001821 const struct pte *pe;
1822 const struct partition *p;
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001823 ullong last_p_start_pos = 0, p_start_pos;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001824 int i, last_i = 0;
1825
Denis Vlasenkob71c6682007-07-21 15:08:09 +00001826 for (i = 0; i < partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001827 if (i == 4) {
1828 last_i = 4;
1829 last_p_start_pos = 0;
1830 }
1831 pe = &ptes[i];
1832 if ((p = pe->part_table)->sys_ind) {
1833 p_start_pos = get_partition_start(pe);
1834
1835 if (last_p_start_pos > p_start_pos) {
1836 if (prev)
1837 *prev = last_i;
1838 return i;
1839 }
1840
1841 last_p_start_pos = p_start_pos;
1842 last_i = i;
1843 }
1844 }
1845 return 0;
1846}
1847
Denis Vlasenko834410a2006-11-29 12:00:28 +00001848#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001849/*
1850 * Fix the chain of logicals.
1851 * extended_offset is unchanged, the set of sectors used is unchanged
1852 * The chain is sorted so that sectors increase, and so that
1853 * starting sectors increase.
1854 *
1855 * After this it may still be that cfdisk doesnt like the table.
1856 * (This is because cfdisk considers expanded parts, from link to
1857 * end of partition, and these may still overlap.)
1858 * Now
1859 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
1860 * may help.
1861 */
1862static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001863fix_chain_of_logicals(void)
1864{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001865 int j, oj, ojj, sj, sjj;
1866 struct partition *pj,*pjj,tmp;
1867
1868 /* Stage 1: sort sectors but leave sector of part 4 */
1869 /* (Its sector is the global extended_offset.) */
1870 stage1:
1871 for (j = 5; j < partitions-1; j++) {
1872 oj = ptes[j].offset;
1873 ojj = ptes[j+1].offset;
1874 if (oj > ojj) {
1875 ptes[j].offset = ojj;
1876 ptes[j+1].offset = oj;
1877 pj = ptes[j].part_table;
1878 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
1879 pjj = ptes[j+1].part_table;
1880 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
1881 set_start_sect(ptes[j-1].ext_pointer,
Rob Landleyb73451d2006-02-24 16:29:00 +00001882 ojj-extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001883 set_start_sect(ptes[j].ext_pointer,
Rob Landleyb73451d2006-02-24 16:29:00 +00001884 oj-extended_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001885 goto stage1;
1886 }
1887 }
1888
1889 /* Stage 2: sort starting sectors */
1890 stage2:
1891 for (j = 4; j < partitions-1; j++) {
1892 pj = ptes[j].part_table;
1893 pjj = ptes[j+1].part_table;
1894 sj = get_start_sect(pj);
1895 sjj = get_start_sect(pjj);
1896 oj = ptes[j].offset;
1897 ojj = ptes[j+1].offset;
1898 if (oj+sj > ojj+sjj) {
1899 tmp = *pj;
1900 *pj = *pjj;
1901 *pjj = tmp;
1902 set_start_sect(pj, ojj+sjj-oj);
1903 set_start_sect(pjj, oj+sj-ojj);
1904 goto stage2;
1905 }
1906 }
1907
1908 /* Probably something was changed */
1909 for (j = 4; j < partitions; j++)
1910 ptes[j].changed = 1;
1911}
1912
1913
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001914static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001915fix_partition_table_order(void)
1916{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001917 struct pte *pei, *pek;
1918 int i,k;
1919
1920 if (!wrong_p_order(NULL)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00001921 printf("Ordering is already correct\n\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001922 return;
1923 }
1924
1925 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
1926 /* partition i should have come earlier, move it */
1927 /* We have to move data in the MBR */
1928 struct partition *pi, *pk, *pe, pbuf;
1929 pei = &ptes[i];
1930 pek = &ptes[k];
1931
1932 pe = pei->ext_pointer;
1933 pei->ext_pointer = pek->ext_pointer;
1934 pek->ext_pointer = pe;
1935
1936 pi = pei->part_table;
1937 pk = pek->part_table;
1938
1939 memmove(&pbuf, pi, sizeof(struct partition));
1940 memmove(pi, pk, sizeof(struct partition));
1941 memmove(pk, &pbuf, sizeof(struct partition));
1942
1943 pei->changed = pek->changed = 1;
1944 }
1945
1946 if (i)
1947 fix_chain_of_logicals();
1948
1949 printf("Done.\n");
1950
1951}
1952#endif
1953
1954static void
Rob Landleyb73451d2006-02-24 16:29:00 +00001955list_table(int xtra)
1956{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001957 const struct partition *p;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001958 int i, w;
1959
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001960 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001961 sun_list_table(xtra);
1962 return;
1963 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001964 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001965 sgi_list_table(xtra);
1966 return;
1967 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001968
1969 list_disk_geometry();
1970
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001971 if (LABEL_IS_OSF) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001972 xbsd_print_disklabel(xtra);
1973 return;
1974 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001975
1976 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
1977 but if the device name ends in a digit, say /dev/foo1,
1978 then the partition is called /dev/foo1p3. */
1979 w = strlen(disk_device);
1980 if (w && isdigit(disk_device[w-1]))
1981 w++;
1982 if (w < 5)
1983 w = 5;
1984
Denis Vlasenkobd852072007-03-19 14:43:38 +00001985 // 1 12345678901 12345678901 12345678901 12
1986 printf("%*s Boot Start End Blocks Id System\n",
1987 w+1, "Device");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001988
1989 for (i = 0; i < partitions; i++) {
1990 const struct pte *pe = &ptes[i];
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00001991 ullong psects;
1992 ullong pblocks;
Denis Vlasenko834410a2006-11-29 12:00:28 +00001993 unsigned podd;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001994
1995 p = pe->part_table;
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001996 if (!p || is_cleared_partition(p))
1997 continue;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00001998
Denis Vlasenko98ae2162006-10-12 19:30:44 +00001999 psects = get_nr_sects(p);
2000 pblocks = psects;
2001 podd = 0;
2002
2003 if (sector_size < 1024) {
2004 pblocks /= (1024 / sector_size);
2005 podd = psects % (1024 / sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002006 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002007 if (sector_size > 1024)
2008 pblocks *= (sector_size / 1024);
2009
2010 printf("%s %c %11llu %11llu %11llu%c %2x %s\n",
2011 partname(disk_device, i+1, w+2),
2012 !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
2013 ? '*' : '?',
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002014 (ullong) cround(get_partition_start(pe)), /* start */
2015 (ullong) cround(get_partition_start(pe) + psects /* end */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002016 - (psects ? 1 : 0)),
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002017 (ullong) pblocks, podd ? '+' : ' ', /* odd flag on end */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002018 p->sys_ind, /* type id */
2019 partition_type(p->sys_ind)); /* type name */
2020
2021 check_consistency(p, i);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002022 }
2023
2024 /* Is partition table in disk order? It need not be, but... */
2025 /* partition table entries are not checked for correct order if this
2026 is a sgi, sun or aix labeled disk... */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002027 if (LABEL_IS_DOS && wrong_p_order(NULL)) {
Rob Landley5527b912006-02-25 03:46:10 +00002028 /* FIXME */
Denis Vlasenkobd852072007-03-19 14:43:38 +00002029 printf("\nPartition table entries are not in disk order\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002030 }
2031}
2032
Denis Vlasenko834410a2006-11-29 12:00:28 +00002033#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002034static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002035x_list_table(int extend)
2036{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002037 const struct pte *pe;
2038 const struct partition *p;
2039 int i;
2040
Denis Vlasenkobd852072007-03-19 14:43:38 +00002041 printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002042 disk_device, heads, sectors, cylinders);
Denis Vlasenkobd852072007-03-19 14:43:38 +00002043 printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n");
Denis Vlasenkob71c6682007-07-21 15:08:09 +00002044 for (i = 0; i < partitions; i++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002045 pe = &ptes[i];
2046 p = (extend ? pe->ext_pointer : pe->part_table);
2047 if (p != NULL) {
Eric Andersen040f4402003-07-30 08:40:37 +00002048 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002049 i + 1, p->boot_ind, p->head,
2050 sector(p->sector),
2051 cylinder(p->sector, p->cyl), p->end_head,
2052 sector(p->end_sector),
2053 cylinder(p->end_sector, p->end_cyl),
2054 get_start_sect(p), get_nr_sects(p), p->sys_ind);
2055 if (p->sys_ind)
2056 check_consistency(p, i);
2057 }
2058 }
2059}
2060#endif
2061
Denis Vlasenko834410a2006-11-29 12:00:28 +00002062#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002063static void
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002064fill_bounds(ullong *first, ullong *last)
Rob Landleyb73451d2006-02-24 16:29:00 +00002065{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002066 int i;
2067 const struct pte *pe = &ptes[0];
2068 const struct partition *p;
2069
2070 for (i = 0; i < partitions; pe++,i++) {
2071 p = pe->part_table;
Rob Landleyb73451d2006-02-24 16:29:00 +00002072 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002073 first[i] = 0xffffffff;
2074 last[i] = 0;
2075 } else {
2076 first[i] = get_partition_start(pe);
2077 last[i] = first[i] + get_nr_sects(p) - 1;
2078 }
2079 }
2080}
2081
2082static void
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002083check(int n, unsigned h, unsigned s, unsigned c, ullong start)
Rob Landleyb73451d2006-02-24 16:29:00 +00002084{
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002085 ullong total, real_s, real_c;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002086
2087 real_s = sector(s) - 1;
2088 real_c = cylinder(s, c);
2089 total = (real_c * sectors + real_s) * heads + h;
2090 if (!total)
Denis Vlasenkobd852072007-03-19 14:43:38 +00002091 printf("Partition %d contains sector 0\n", n);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002092 if (h >= heads)
Denis Vlasenkobd852072007-03-19 14:43:38 +00002093 printf("Partition %d: head %d greater than maximum %d\n",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002094 n, h + 1, heads);
2095 if (real_s >= sectors)
Denis Vlasenkobd852072007-03-19 14:43:38 +00002096 printf("Partition %d: sector %d greater than "
2097 "maximum %d\n", n, s, sectors);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002098 if (real_c >= cylinders)
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002099 printf("Partition %d: cylinder %llu greater than "
Denis Vlasenkobd852072007-03-19 14:43:38 +00002100 "maximum %d\n", n, real_c + 1, cylinders);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002101 if (cylinders <= 1024 && start != total)
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002102 printf("Partition %d: previous sectors %llu disagrees with "
2103 "total %llu\n", n, start, total);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002104}
2105
2106static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002107verify(void)
2108{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002109 int i, j;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002110 unsigned total = 1;
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002111 ullong first[partitions], last[partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002112 struct partition *p;
2113
2114 if (warn_geometry())
2115 return;
2116
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002117 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002118 verify_sun();
2119 return;
2120 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002121 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002122 verify_sgi(1);
2123 return;
2124 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002125
2126 fill_bounds(first, last);
2127 for (i = 0; i < partitions; i++) {
2128 struct pte *pe = &ptes[i];
2129
2130 p = pe->part_table;
Rob Landleyb73451d2006-02-24 16:29:00 +00002131 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002132 check_consistency(p, i);
2133 if (get_partition_start(pe) < first[i])
Denis Vlasenkobd852072007-03-19 14:43:38 +00002134 printf("Warning: bad start-of-data in "
2135 "partition %d\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002136 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
2137 last[i]);
2138 total += last[i] + 1 - first[i];
Denis Vlasenkobd852072007-03-19 14:43:38 +00002139 for (j = 0; j < i; j++) {
2140 if ((first[i] >= first[j] && first[i] <= last[j])
2141 || ((last[i] <= last[j] && last[i] >= first[j]))) {
2142 printf("Warning: partition %d overlaps "
2143 "partition %d\n", j + 1, i + 1);
2144 total += first[i] >= first[j] ?
2145 first[i] : first[j];
2146 total -= last[i] <= last[j] ?
2147 last[i] : last[j];
2148 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002149 }
2150 }
2151 }
2152
2153 if (extended_offset) {
2154 struct pte *pex = &ptes[ext_index];
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002155 ullong e_last = get_start_sect(pex->part_table) +
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002156 get_nr_sects(pex->part_table) - 1;
2157
2158 for (i = 4; i < partitions; i++) {
2159 total++;
2160 p = ptes[i].part_table;
2161 if (!p->sys_ind) {
2162 if (i != 4 || i + 1 < partitions)
Denis Vlasenkobd852072007-03-19 14:43:38 +00002163 printf("Warning: partition %d "
2164 "is empty\n", i + 1);
2165 } else if (first[i] < extended_offset || last[i] > e_last) {
2166 printf("Logical partition %d not entirely in "
2167 "partition %d\n", i + 1, ext_index + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002168 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002169 }
2170 }
2171
2172 if (total > heads * sectors * cylinders)
Denis Vlasenkobd852072007-03-19 14:43:38 +00002173 printf("Total allocated sectors %d greater than the maximum "
2174 "%d\n", total, heads * sectors * cylinders);
2175 else {
2176 total = heads * sectors * cylinders - total;
2177 if (total != 0)
2178 printf("%d unallocated sectors\n", total);
2179 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002180}
2181
2182static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002183add_partition(int n, int sys)
2184{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002185 char mesg[256]; /* 48 does not suffice in Japanese */
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002186 int i, num_read = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002187 struct partition *p = ptes[n].part_table;
2188 struct partition *q = ptes[ext_index].part_table;
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002189 ullong limit, temp;
2190 ullong start, stop = 0;
2191 ullong first[partitions], last[partitions];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002192
2193 if (p && p->sys_ind) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002194 printf(msg_part_already_defined, n + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002195 return;
2196 }
2197 fill_bounds(first, last);
2198 if (n < 4) {
2199 start = sector_offset;
Eric Andersen040f4402003-07-30 08:40:37 +00002200 if (display_in_cyl_units || !total_number_of_sectors)
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002201 limit = (ullong) heads * sectors * cylinders - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002202 else
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002203 limit = total_number_of_sectors - 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002204 if (extended_offset) {
2205 first[ext_index] = extended_offset;
2206 last[ext_index] = get_start_sect(q) +
2207 get_nr_sects(q) - 1;
2208 }
2209 } else {
2210 start = extended_offset + sector_offset;
2211 limit = get_start_sect(q) + get_nr_sects(q) - 1;
2212 }
2213 if (display_in_cyl_units)
2214 for (i = 0; i < partitions; i++)
2215 first[i] = (cround(first[i]) - 1) * units_per_sector;
2216
Denis Vlasenkobd852072007-03-19 14:43:38 +00002217 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002218 do {
2219 temp = start;
2220 for (i = 0; i < partitions; i++) {
2221 int lastplusoff;
2222
2223 if (start == ptes[i].offset)
2224 start += sector_offset;
Rob Landleyb73451d2006-02-24 16:29:00 +00002225 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002226 if (start >= first[i] && start <= lastplusoff)
2227 start = lastplusoff + 1;
2228 }
2229 if (start > limit)
2230 break;
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002231 if (start >= temp+units_per_sector && num_read) {
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002232 printf("Sector %lld is already allocated\n", temp);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002233 temp = start;
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002234 num_read = 0;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002235 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002236 if (!num_read && start == temp) {
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002237 ullong saved_start;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002238
2239 saved_start = start;
2240 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
2241 0, mesg);
2242 if (display_in_cyl_units) {
2243 start = (start - 1) * units_per_sector;
2244 if (start < saved_start) start = saved_start;
2245 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002246 num_read = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002247 }
Mike Frysingerfa6c4842006-05-26 01:48:17 +00002248 } while (start != temp || !num_read);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002249 if (n > 4) { /* NOT for fifth partition */
2250 struct pte *pe = &ptes[n];
2251
2252 pe->offset = start - sector_offset;
2253 if (pe->offset == extended_offset) { /* must be corrected */
2254 pe->offset++;
2255 if (sector_offset == 1)
2256 start++;
2257 }
2258 }
2259
2260 for (i = 0; i < partitions; i++) {
2261 struct pte *pe = &ptes[i];
2262
2263 if (start < pe->offset && limit >= pe->offset)
2264 limit = pe->offset - 1;
2265 if (start < first[i] && limit >= first[i])
2266 limit = first[i] - 1;
2267 }
2268 if (start > limit) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002269 printf("No free sectors available\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002270 if (n > 4)
2271 partitions--;
2272 return;
2273 }
2274 if (cround(start) == cround(limit)) {
2275 stop = limit;
2276 } else {
2277 snprintf(mesg, sizeof(mesg),
Denis Vlasenkobd852072007-03-19 14:43:38 +00002278 "Last %s or +size or +sizeM or +sizeK",
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002279 str_units(SINGULAR));
2280 stop = read_int(cround(start), cround(limit), cround(limit),
2281 cround(start), mesg);
2282 if (display_in_cyl_units) {
2283 stop = stop * units_per_sector - 1;
2284 if (stop >limit)
2285 stop = limit;
2286 }
2287 }
2288
2289 set_partition(n, 0, start, stop, sys);
2290 if (n > 4)
2291 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
2292
Rob Landleyb73451d2006-02-24 16:29:00 +00002293 if (IS_EXTENDED(sys)) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002294 struct pte *pe4 = &ptes[4];
2295 struct pte *pen = &ptes[n];
2296
2297 ext_index = n;
2298 pen->ext_pointer = p;
2299 pe4->offset = extended_offset = start;
Rob Landley081e3842006-08-03 20:07:35 +00002300 pe4->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002301 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2302 pe4->ext_pointer = pe4->part_table + 1;
2303 pe4->changed = 1;
2304 partitions = 5;
2305 }
2306}
2307
2308static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002309add_logical(void)
2310{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002311 if (partitions > 5 || ptes[4].part_table->sys_ind) {
2312 struct pte *pe = &ptes[partitions];
2313
Rob Landley081e3842006-08-03 20:07:35 +00002314 pe->sectorbuffer = xzalloc(sector_size);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002315 pe->part_table = pt_offset(pe->sectorbuffer, 0);
2316 pe->ext_pointer = pe->part_table + 1;
2317 pe->offset = 0;
2318 pe->changed = 1;
2319 partitions++;
2320 }
2321 add_partition(partitions - 1, LINUX_NATIVE);
2322}
2323
2324static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002325new_partition(void)
2326{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002327 int i, free_primary = 0;
2328
2329 if (warn_geometry())
2330 return;
2331
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002332 if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002333 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
2334 return;
2335 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002336 if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002337 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
2338 return;
2339 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002340 if (LABEL_IS_AIX) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002341 printf("Sorry - this fdisk cannot handle AIX disk labels.\n"
2342"If you want to add DOS-type partitions, create a new empty DOS partition\n"
2343"table first (use 'o'). This will destroy the present disk contents.\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002344 return;
2345 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002346
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002347 for (i = 0; i < 4; i++)
2348 free_primary += !ptes[i].part_table->sys_ind;
Eric Andersenc48d49a2003-07-03 10:02:32 +00002349
Rob Landleyb73451d2006-02-24 16:29:00 +00002350 if (!free_primary && partitions >= MAXIMUM_PARTS) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002351 printf("The maximum number of partitions has been created\n");
Eric Andersen84bdea82004-05-19 10:49:17 +00002352 return;
Rob Landleyb73451d2006-02-24 16:29:00 +00002353 }
Eric Andersenc48d49a2003-07-03 10:02:32 +00002354
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002355 if (!free_primary) {
2356 if (extended_offset)
2357 add_logical();
2358 else
Denis Vlasenkobd852072007-03-19 14:43:38 +00002359 printf("You must delete some partition and add "
2360 "an extended partition first\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002361 } else {
Denis Vlasenkodfce08f2007-03-19 14:45:10 +00002362 char c, line[80];
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00002363 snprintf(line, sizeof(line),
2364 "Command action\n"
2365 " %s\n"
2366 " p primary partition (1-4)\n",
2367 (extended_offset ?
2368 "l logical (5 or over)" : "e extended"));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002369 while (1) {
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002370 c = read_nonempty(line);
2371 if (c == 'p' || c == 'P') {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002372 i = get_nonexisting_partition(0, 4);
2373 if (i >= 0)
2374 add_partition(i, LINUX_NATIVE);
2375 return;
2376 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002377 if (c == 'l' && extended_offset) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002378 add_logical();
2379 return;
2380 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002381 if (c == 'e' && !extended_offset) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002382 i = get_nonexisting_partition(0, 4);
2383 if (i >= 0)
2384 add_partition(i, EXTENDED);
2385 return;
2386 }
Denis Vlasenkobd852072007-03-19 14:43:38 +00002387 printf("Invalid partition number "
2388 "for type '%c'\n", c);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002389 }
2390 }
2391}
2392
2393static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002394write_table(void)
2395{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002396 int i;
2397
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002398 if (LABEL_IS_DOS) {
Rob Landleyb73451d2006-02-24 16:29:00 +00002399 for (i = 0; i < 3; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002400 if (ptes[i].changed)
2401 ptes[3].changed = 1;
2402 for (i = 3; i < partitions; i++) {
2403 struct pte *pe = &ptes[i];
2404
2405 if (pe->changed) {
2406 write_part_table_flag(pe->sectorbuffer);
2407 write_sector(pe->offset, pe->sectorbuffer);
2408 }
2409 }
2410 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002411 else if (LABEL_IS_SGI) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002412 /* no test on change? the printf below might be mistaken */
2413 sgi_write_table();
2414 }
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002415 else if (LABEL_IS_SUN) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002416 int needw = 0;
2417
Rob Landleyb73451d2006-02-24 16:29:00 +00002418 for (i = 0; i < 8; i++)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002419 if (ptes[i].changed)
2420 needw = 1;
2421 if (needw)
2422 sun_write_table();
2423 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002424
Denis Vlasenkobd852072007-03-19 14:43:38 +00002425 printf("The partition table has been altered!\n\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002426 reread_partition_table(1);
2427}
2428
Rob Landleyb73451d2006-02-24 16:29:00 +00002429static void
2430reread_partition_table(int leave)
2431{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002432 int i;
2433
Denis Vlasenkobd852072007-03-19 14:43:38 +00002434 printf("Calling ioctl() to re-read partition table\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002435 sync();
Denis Vlasenkobd852072007-03-19 14:43:38 +00002436 /* sleep(2); Huh? */
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00002437 i = ioctl_or_perror(fd, BLKRRPART, NULL,
2438 "WARNING: rereading partition table "
Denis Vlasenko28703012006-12-19 20:32:02 +00002439 "failed, kernel still uses old table");
Denis Vlasenko28703012006-12-19 20:32:02 +00002440#if 0
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002441 if (dos_changed)
Rob Landleyb73451d2006-02-24 16:29:00 +00002442 printf(
Denis Vlasenkobd852072007-03-19 14:43:38 +00002443 "\nWARNING: If you have created or modified any DOS 6.x\n"
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002444 "partitions, please see the fdisk manual page for additional\n"
Denis Vlasenkobd852072007-03-19 14:43:38 +00002445 "information\n");
Denis Vlasenko28703012006-12-19 20:32:02 +00002446#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002447
2448 if (leave) {
Denis Vlasenko28703012006-12-19 20:32:02 +00002449 if (ENABLE_FEATURE_CLEAN_UP)
2450 close(fd);
2451 exit(i != 0);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002452 }
2453}
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00002454#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002455
Denis Vlasenko834410a2006-11-29 12:00:28 +00002456#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002457#define MAX_PER_LINE 16
2458static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002459print_buffer(char *pbuffer)
2460{
2461 int i,l;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002462
2463 for (i = 0, l = 0; i < sector_size; i++, l++) {
2464 if (l == 0)
2465 printf("0x%03X:", i);
2466 printf(" %02X", (unsigned char) pbuffer[i]);
2467 if (l == MAX_PER_LINE - 1) {
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00002468 puts("");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002469 l = -1;
2470 }
2471 }
2472 if (l > 0)
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00002473 puts("");
2474 puts("");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002475}
2476
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002477static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002478print_raw(void)
2479{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002480 int i;
2481
Denis Vlasenkobd852072007-03-19 14:43:38 +00002482 printf("Device: %s\n", disk_device);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002483 if (LABEL_IS_SGI || LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002484 print_buffer(MBRbuffer);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002485 else {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002486 for (i = 3; i < partitions; i++)
2487 print_buffer(ptes[i].sectorbuffer);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002488 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002489}
2490
2491static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002492move_begin(int i)
2493{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002494 struct pte *pe = &ptes[i];
2495 struct partition *p = pe->part_table;
Denis Vlasenko3f22b7f2007-06-02 12:46:55 +00002496 ullong new, first;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002497
2498 if (warn_geometry())
2499 return;
Rob Landleyb73451d2006-02-24 16:29:00 +00002500 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002501 printf("Partition %d has no data area\n", i + 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002502 return;
2503 }
2504 first = get_partition_start(pe);
2505 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
Denis Vlasenkobd852072007-03-19 14:43:38 +00002506 "New beginning of data") - pe->offset;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002507
2508 if (new != get_nr_sects(p)) {
2509 first = get_nr_sects(p) + get_start_sect(p) - new;
2510 set_nr_sects(p, first);
2511 set_start_sect(p, new);
2512 pe->changed = 1;
2513 }
2514}
2515
2516static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002517xselect(void)
2518{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002519 char c;
2520
Rob Landleyb73451d2006-02-24 16:29:00 +00002521 while (1) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002522 putchar('\n');
Denis Vlasenkobd852072007-03-19 14:43:38 +00002523 c = tolower(read_nonempty("Expert command (m for help): "));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002524 switch (c) {
2525 case 'a':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002526 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002527 sun_set_alt_cyl();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002528 break;
2529 case 'b':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002530 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002531 move_begin(get_partition(0, partitions));
2532 break;
2533 case 'c':
2534 user_cylinders = cylinders =
2535 read_int(1, cylinders, 1048576, 0,
Denis Vlasenkobd852072007-03-19 14:43:38 +00002536 "Number of cylinders");
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002537 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002538 sun_set_ncyl(cylinders);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002539 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002540 warn_cylinders();
2541 break;
2542 case 'd':
2543 print_raw();
2544 break;
2545 case 'e':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002546 if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002547 sgi_set_xcyl();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002548 else if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002549 sun_set_xcyl();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002550 else if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002551 x_list_table(1);
2552 break;
2553 case 'f':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002554 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002555 fix_partition_table_order();
2556 break;
2557 case 'g':
Denis Vlasenko834410a2006-11-29 12:00:28 +00002558#if ENABLE_FEATURE_SGI_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002559 create_sgilabel();
2560#endif
2561 break;
2562 case 'h':
2563 user_heads = heads = read_int(1, heads, 256, 0,
Denis Vlasenkobd852072007-03-19 14:43:38 +00002564 "Number of heads");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002565 update_units();
2566 break;
2567 case 'i':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002568 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002569 sun_set_ilfact();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002570 break;
2571 case 'o':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002572 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002573 sun_set_rspeed();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002574 break;
2575 case 'p':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002576 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002577 list_table(1);
2578 else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002579 x_list_table(0);
2580 break;
2581 case 'q':
2582 close(fd);
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00002583 puts("");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002584 exit(0);
2585 case 'r':
2586 return;
2587 case 's':
2588 user_sectors = sectors = read_int(1, sectors, 63, 0,
Denis Vlasenkobd852072007-03-19 14:43:38 +00002589 "Number of sectors");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002590 if (dos_compatible_flag) {
2591 sector_offset = sectors;
Denis Vlasenkobd852072007-03-19 14:43:38 +00002592 printf("Warning: setting sector offset for DOS "
2593 "compatiblity\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002594 }
2595 update_units();
2596 break;
2597 case 'v':
2598 verify();
2599 break;
2600 case 'w':
2601 write_table(); /* does not return */
2602 break;
2603 case 'y':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002604 if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002605 sun_set_pcylcount();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002606 break;
2607 default:
2608 xmenu();
2609 }
2610 }
2611}
2612#endif /* ADVANCED mode */
2613
2614static int
Rob Landleyb73451d2006-02-24 16:29:00 +00002615is_ide_cdrom_or_tape(const char *device)
2616{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002617 FILE *procf;
2618 char buf[100];
2619 struct stat statbuf;
2620 int is_ide = 0;
2621
2622 /* No device was given explicitly, and we are trying some
2623 likely things. But opening /dev/hdc may produce errors like
2624 "hdc: tray open or drive not ready"
2625 if it happens to be a CD-ROM drive. It even happens that
2626 the process hangs on the attempt to read a music CD.
2627 So try to be careful. This only works since 2.1.73. */
2628
2629 if (strncmp("/dev/hd", device, 7))
2630 return 0;
2631
2632 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
2633 procf = fopen(buf, "r");
2634 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2635 is_ide = (!strncmp(buf, "cdrom", 5) ||
2636 !strncmp(buf, "tape", 4));
2637 else
2638 /* Now when this proc file does not exist, skip the
2639 device when it is read-only. */
2640 if (stat(device, &statbuf) == 0)
2641 is_ide = ((statbuf.st_mode & 0222) == 0);
2642
2643 if (procf)
2644 fclose(procf);
2645 return is_ide;
2646}
2647
Rob Landley5527b912006-02-25 03:46:10 +00002648
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002649static void
Denis Vlasenkod5470832007-01-03 02:58:54 +00002650trydev(const char *device, int user_specified)
Rob Landleyb73451d2006-02-24 16:29:00 +00002651{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002652 int gb;
2653
2654 disk_device = device;
2655 if (setjmp(listingbuf))
2656 return;
2657 if (!user_specified)
2658 if (is_ide_cdrom_or_tape(device))
2659 return;
Denis Vlasenko28703012006-12-19 20:32:02 +00002660 fd = open(disk_device, type_open);
2661 if (fd >= 0) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002662 gb = get_boot(try_only);
2663 if (gb > 0) { /* I/O error */
2664 close(fd);
2665 } else if (gb < 0) { /* no DOS signature */
2666 list_disk_geometry();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002667 if (LABEL_IS_AIX) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002668 return;
Rob Landley5527b912006-02-25 03:46:10 +00002669 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002670#if ENABLE_FEATURE_OSF_LABEL
Denis Vlasenkod5470832007-01-03 02:58:54 +00002671 if (bsd_trydev(device) < 0)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002672#endif
Denis Vlasenkobd852072007-03-19 14:43:38 +00002673 printf("Disk %s doesn't contain a valid "
2674 "partition table\n", device);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002675 close(fd);
2676 } else {
2677 close(fd);
2678 list_table(0);
Denis Vlasenko834410a2006-11-29 12:00:28 +00002679#if ENABLE_FEATURE_FDISK_WRITABLE
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002680 if (!LABEL_IS_SUN && partitions > 4){
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002681 delete_partition(ext_index);
Rob Landley5527b912006-02-25 03:46:10 +00002682 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002683#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002684 }
2685 } else {
2686 /* Ignore other errors, since we try IDE
2687 and SCSI hard disks which may not be
2688 installed on the system. */
2689 if (errno == EACCES) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002690 printf("Cannot open %s\n", device);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002691 return;
2692 }
2693 }
2694}
2695
2696/* for fdisk -l: try all things in /proc/partitions
2697 that look like a partition name (do not end in a digit) */
2698static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002699tryprocpt(void)
2700{
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002701 FILE *procpt;
2702 char line[100], ptname[100], devname[120], *s;
2703 int ma, mi, sz;
2704
Denis Vlasenkoddec5af2006-10-26 23:25:17 +00002705 procpt = fopen_or_warn("/proc/partitions", "r");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002706
2707 while (fgets(line, sizeof(line), procpt)) {
Rob Landleyb73451d2006-02-24 16:29:00 +00002708 if (sscanf(line, " %d %d %d %[^\n ]",
2709 &ma, &mi, &sz, ptname) != 4)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002710 continue;
2711 for (s = ptname; *s; s++);
2712 if (isdigit(s[-1]))
2713 continue;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002714 sprintf(devname, "/dev/%s", ptname);
Denis Vlasenkod5470832007-01-03 02:58:54 +00002715 trydev(devname, 0);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002716 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002717#if ENABLE_FEATURE_CLEAN_UP
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002718 fclose(procpt);
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002719#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002720}
2721
Denis Vlasenko834410a2006-11-29 12:00:28 +00002722#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002723static void
Rob Landleyb73451d2006-02-24 16:29:00 +00002724unknown_command(int c)
2725{
Denis Vlasenkobd852072007-03-19 14:43:38 +00002726 printf("%c: unknown command\n", c);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002727}
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002728#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002729
Denis Vlasenko06af2162007-02-03 17:28:39 +00002730int fdisk_main(int argc, char **argv);
Rob Landleyb73451d2006-02-24 16:29:00 +00002731int fdisk_main(int argc, char **argv)
2732{
Denis Vlasenko834410a2006-11-29 12:00:28 +00002733 char *str_b, *str_C, *str_H, *str_S;
2734 unsigned opt;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002735 /*
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002736 * fdisk -v
2737 * fdisk -l [-b sectorsize] [-u] device ...
2738 * fdisk -s [partition] ...
2739 * fdisk [-b sectorsize] [-u] device
2740 *
2741 * Options -C, -H, -S set the geometry.
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002742 */
Denis Vlasenko834410a2006-11-29 12:00:28 +00002743 enum {
2744 OPT_b = 1 << 0,
2745 OPT_C = 1 << 1,
2746 OPT_H = 1 << 2,
2747 OPT_l = 1 << 3,
2748 OPT_S = 1 << 4,
2749 OPT_u = 1 << 5,
2750 OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
2751 };
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +00002752
Denis Vlasenkodfce08f2007-03-19 14:45:10 +00002753 PTR_TO_GLOBALS = xzalloc(sizeof(G));
Denis Vlasenko8e1a0cc2007-03-18 14:42:45 +00002754
Denis Vlasenko834410a2006-11-29 12:00:28 +00002755 opt = getopt32(argc, argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"),
2756 &str_b, &str_C, &str_H, &str_S);
2757 argc -= optind;
2758 argv += optind;
2759 if (opt & OPT_b) { // -b
2760 /* Ugly: this sector size is really per device,
2761 so cannot be combined with multiple disks,
2762 and the same goes for the C/H/S options.
2763 */
2764 sector_size = xatoi_u(str_b);
2765 if (sector_size != 512 && sector_size != 1024 &&
2766 sector_size != 2048)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002767 bb_show_usage();
Denis Vlasenko834410a2006-11-29 12:00:28 +00002768 sector_offset = 2;
2769 user_set_sector_size = 1;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002770 }
Denis Vlasenko834410a2006-11-29 12:00:28 +00002771 if (opt & OPT_C) user_cylinders = xatoi_u(str_C); // -C
2772 if (opt & OPT_H) { // -H
2773 user_heads = xatoi_u(str_H);
2774 if (user_heads <= 0 || user_heads >= 256)
2775 user_heads = 0;
2776 }
2777 //if (opt & OPT_l) // -l
2778 if (opt & OPT_S) { // -S
2779 user_sectors = xatoi_u(str_S);
2780 if (user_sectors <= 0 || user_sectors >= 64)
2781 user_sectors = 0;
2782 }
2783 if (opt & OPT_u) display_in_cyl_units = 0; // -u
2784 //if (opt & OPT_s) // -s
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002785
Denis Vlasenko834410a2006-11-29 12:00:28 +00002786 if (user_set_sector_size && argc != 1)
Denis Vlasenkobd852072007-03-19 14:43:38 +00002787 printf("Warning: the -b (set sector size) option should"
2788 " be used with one specified device\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002789
Denis Vlasenko834410a2006-11-29 12:00:28 +00002790#if ENABLE_FEATURE_FDISK_WRITABLE
2791 if (opt & OPT_l) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002792 nowarn = 1;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002793#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002794 type_open = O_RDONLY;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002795 if (argc > 0) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002796 int k;
Denis Vlasenko28703012006-12-19 20:32:02 +00002797#if defined(__GNUC__)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002798 /* avoid gcc warning:
2799 variable `k' might be clobbered by `longjmp' */
2800 (void)&k;
2801#endif
2802 listing = 1;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002803 for (k = 0; k < argc; k++)
Denis Vlasenkod5470832007-01-03 02:58:54 +00002804 trydev(argv[k], 1);
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002805 } else {
2806 /* we no longer have default device names */
2807 /* but, we can use /proc/partitions instead */
2808 tryprocpt();
2809 }
2810 return 0;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002811#if ENABLE_FEATURE_FDISK_WRITABLE
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002812 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002813#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002814
Denis Vlasenko834410a2006-11-29 12:00:28 +00002815#if ENABLE_FEATURE_FDISK_BLKSIZE
2816 if (opt & OPT_s) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002817 long size;
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002818 int j;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002819
2820 nowarn = 1;
2821 type_open = O_RDONLY;
2822
Denis Vlasenko834410a2006-11-29 12:00:28 +00002823 if (argc <= 0)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002824 bb_show_usage();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002825
Denis Vlasenko834410a2006-11-29 12:00:28 +00002826 for (j = 0; j < argc; j++) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002827 disk_device = argv[j];
Denis Vlasenko834410a2006-11-29 12:00:28 +00002828 fd = open(disk_device, type_open);
2829 if (fd < 0)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002830 fdisk_fatal(unable_to_open);
2831 if (ioctl(fd, BLKGETSIZE, &size))
2832 fdisk_fatal(ioctl_error);
2833 close(fd);
Denis Vlasenko834410a2006-11-29 12:00:28 +00002834 if (argc == 1)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002835 printf("%ld\n", size/2);
2836 else
2837 printf("%s: %ld\n", argv[j], size/2);
2838 }
2839 return 0;
2840 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002841#endif
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002842
Denis Vlasenko834410a2006-11-29 12:00:28 +00002843#if ENABLE_FEATURE_FDISK_WRITABLE
2844 if (argc != 1)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002845 bb_show_usage();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002846
Denis Vlasenko834410a2006-11-29 12:00:28 +00002847 disk_device = argv[0];
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002848 get_boot(fdisk);
2849
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002850 if (LABEL_IS_OSF) {
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002851 /* OSF label, and no DOS label */
Denis Vlasenkobd852072007-03-19 14:43:38 +00002852 printf("Detected an OSF/1 disklabel on %s, entering "
2853 "disklabel mode\n", disk_device);
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +00002854 bsd_select();
Rob Landley5527b912006-02-25 03:46:10 +00002855 /*Why do we do this? It seems to be counter-intuitive*/
2856 current_label_type = label_dos;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002857 /* If we return we may want to make an empty DOS label? */
2858 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002859
2860 while (1) {
Denis Vlasenko3bba5452006-12-30 17:57:03 +00002861 int c;
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002862 putchar('\n');
Denis Vlasenkobd852072007-03-19 14:43:38 +00002863 c = tolower(read_nonempty("Command (m for help): "));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002864 switch (c) {
2865 case 'a':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002866 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002867 toggle_active(get_partition(1, partitions));
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002868 else if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002869 toggle_sunflags(get_partition(1, partitions),
2870 0x01);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002871 else if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002872 sgi_set_bootpartition(
2873 get_partition(1, partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002874 else
2875 unknown_command(c);
2876 break;
2877 case 'b':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002878 if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002879 printf("\nThe current boot file is: %s\n",
Rob Landleyb73451d2006-02-24 16:29:00 +00002880 sgi_get_bootfile());
Denis Vlasenkobd852072007-03-19 14:43:38 +00002881 if (read_maybe_empty("Please enter the name of the "
2882 "new boot file: ") == '\n')
2883 printf("Boot file unchanged\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002884 else
2885 sgi_set_bootfile(line_ptr);
Denis Vlasenko834410a2006-11-29 12:00:28 +00002886 }
2887#if ENABLE_FEATURE_OSF_LABEL
2888 else
Denis Vlasenkoefeed5e2006-10-14 16:16:03 +00002889 bsd_select();
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002890#endif
2891 break;
2892 case 'c':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002893 if (LABEL_IS_DOS)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002894 toggle_dos_compatibility_flag();
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002895 else if (LABEL_IS_SUN)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002896 toggle_sunflags(get_partition(1, partitions),
2897 0x10);
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002898 else if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002899 sgi_set_swappartition(
2900 get_partition(1, partitions));
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002901 else
2902 unknown_command(c);
2903 break;
2904 case 'd':
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002905 {
Eric Andersen040f4402003-07-30 08:40:37 +00002906 int j;
Eric Andersen040f4402003-07-30 08:40:37 +00002907 /* If sgi_label then don't use get_existing_partition,
2908 let the user select a partition, since
2909 get_existing_partition() only works for Linux-like
2910 partition tables */
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002911 if (!LABEL_IS_SGI) {
Eric Andersen040f4402003-07-30 08:40:37 +00002912 j = get_existing_partition(1, partitions);
2913 } else {
2914 j = get_partition(1, partitions);
2915 }
Glenn L McGrath4dcc2dd2003-01-04 11:56:06 +00002916 if (j >= 0)
2917 delete_partition(j);
2918 }
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002919 break;
2920 case 'i':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002921 if (LABEL_IS_SGI)
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002922 create_sgiinfo();
2923 else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002924 unknown_command(c);
2925 case 'l':
2926 list_types(get_sys_types());
2927 break;
2928 case 'm':
2929 menu();
2930 break;
2931 case 'n':
2932 new_partition();
2933 break;
2934 case 'o':
2935 create_doslabel();
2936 break;
2937 case 'p':
2938 list_table(0);
2939 break;
2940 case 'q':
2941 close(fd);
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00002942 puts("");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002943 return 0;
2944 case 's':
Denis Vlasenko834410a2006-11-29 12:00:28 +00002945#if ENABLE_FEATURE_SUN_LABEL
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002946 create_sunlabel();
2947#endif
2948 break;
2949 case 't':
2950 change_sysid();
2951 break;
2952 case 'u':
2953 change_units();
2954 break;
2955 case 'v':
2956 verify();
2957 break;
2958 case 'w':
2959 write_table(); /* does not return */
2960 break;
Denis Vlasenko834410a2006-11-29 12:00:28 +00002961#if ENABLE_FEATURE_FDISK_ADVANCED
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002962 case 'x':
Denis Vlasenko98ae2162006-10-12 19:30:44 +00002963 if (LABEL_IS_SGI) {
Denis Vlasenkobd852072007-03-19 14:43:38 +00002964 printf("\n\tSorry, no experts menu for SGI "
2965 "partition tables available\n\n");
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002966 } else
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002967 xselect();
2968 break;
2969#endif
2970 default:
2971 unknown_command(c);
2972 menu();
2973 }
2974 }
2975 return 0;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00002976#endif /* FEATURE_FDISK_WRITABLE */
Glenn L McGrath441e7ef2002-11-26 22:00:21 +00002977}