Magellan Linux

Annotation of /tags/mkinitrd-6_2_0/util-linux/fdisk.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 994 - (hide annotations) (download)
Sun May 30 11:53:18 2010 UTC (14 years ago) by niro
File MIME type: text/plain
File size: 75822 byte(s)
tagged 'mkinitrd-6_2_0'
1 niro 532 /* vi: set sw=4 ts=4: */
2     /* fdisk.c -- Partition table manipulator for Linux.
3     *
4     * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
5     * Copyright (C) 2001,2002 Vladimir Oleynik <dzo@simtreas.ru> (initial bb port)
6     *
7     * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
8     */
9    
10 niro 816 #ifndef _LARGEFILE64_SOURCE
11     /* For lseek64 */
12 niro 984 # define _LARGEFILE64_SOURCE
13 niro 816 #endif
14 niro 532 #include <assert.h> /* assert */
15 niro 984 #include <sys/mount.h>
16     #if !defined(BLKSSZGET)
17     # define BLKSSZGET _IO(0x12, 104)
18     #endif
19     #if !defined(BLKGETSIZE64)
20     # define BLKGETSIZE64 _IOR(0x12,114,size_t)
21     #endif
22 niro 816 #include "libbb.h"
23 niro 532
24     /* Looks like someone forgot to add this to config system */
25     #ifndef ENABLE_FEATURE_FDISK_BLKSIZE
26     # define ENABLE_FEATURE_FDISK_BLKSIZE 0
27 niro 984 # define IF_FEATURE_FDISK_BLKSIZE(a)
28 niro 532 #endif
29    
30 niro 816 #define DEFAULT_SECTOR_SIZE 512
31     #define DEFAULT_SECTOR_SIZE_STR "512"
32     #define MAX_SECTOR_SIZE 2048
33     #define SECTOR_SIZE 512 /* still used in osf/sgi/sun code */
34     #define MAXIMUM_PARTS 60
35 niro 532
36 niro 816 #define ACTIVE_FLAG 0x80
37 niro 532
38 niro 816 #define EXTENDED 0x05
39     #define WIN98_EXTENDED 0x0f
40     #define LINUX_PARTITION 0x81
41     #define LINUX_SWAP 0x82
42     #define LINUX_NATIVE 0x83
43     #define LINUX_EXTENDED 0x85
44     #define LINUX_LVM 0x8e
45     #define LINUX_RAID 0xfd
46 niro 532
47    
48 niro 816 enum {
49     OPT_b = 1 << 0,
50     OPT_C = 1 << 1,
51     OPT_H = 1 << 2,
52     OPT_l = 1 << 3,
53     OPT_S = 1 << 4,
54     OPT_u = 1 << 5,
55     OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
56     };
57 niro 532
58    
59 niro 816 typedef unsigned long long ullong;
60 niro 984 /* Used for sector numbers. Partition formats we know
61     * do not support more than 2^32 sectors
62     */
63     typedef uint32_t sector_t;
64     #if UINT_MAX == 4294967295
65     # define SECT_FMT ""
66     #elif ULONG_MAX == 4294967295
67     # define SECT_FMT "l"
68     #else
69     # error Cant detect sizeof(uint32_t)
70     #endif
71 niro 816
72 niro 532 struct hd_geometry {
73     unsigned char heads;
74     unsigned char sectors;
75     unsigned short cylinders;
76     unsigned long start;
77     };
78    
79     #define HDIO_GETGEO 0x0301 /* get device geometry */
80    
81 niro 816 static const char msg_building_new_label[] ALIGN1 =
82     "Building a new %s. Changes will remain in memory only,\n"
83     "until you decide to write them. After that the previous content\n"
84     "won't be recoverable.\n\n";
85 niro 532
86 niro 816 static const char msg_part_already_defined[] ALIGN1 =
87 niro 984 "Partition %u is already defined, delete it before re-adding\n";
88 niro 532
89    
90     struct partition {
91     unsigned char boot_ind; /* 0x80 - active */
92     unsigned char head; /* starting head */
93     unsigned char sector; /* starting sector */
94     unsigned char cyl; /* starting cylinder */
95 niro 816 unsigned char sys_ind; /* what partition type */
96 niro 532 unsigned char end_head; /* end head */
97     unsigned char end_sector; /* end sector */
98     unsigned char end_cyl; /* end cylinder */
99     unsigned char start4[4]; /* starting sector counting from 0 */
100     unsigned char size4[4]; /* nr of sectors in partition */
101 niro 816 } PACKED;
102 niro 532
103 niro 984 static const char unable_to_open[] ALIGN1 = "can't open '%s'";
104 niro 816 static const char unable_to_read[] ALIGN1 = "can't read from %s";
105     static const char unable_to_seek[] ALIGN1 = "can't seek on %s";
106 niro 532
107     enum label_type {
108 niro 816 LABEL_DOS, LABEL_SUN, LABEL_SGI, LABEL_AIX, LABEL_OSF
109 niro 532 };
110    
111 niro 816 #define LABEL_IS_DOS (LABEL_DOS == current_label_type)
112    
113 niro 532 #if ENABLE_FEATURE_SUN_LABEL
114 niro 816 #define LABEL_IS_SUN (LABEL_SUN == current_label_type)
115 niro 532 #define STATIC_SUN static
116     #else
117     #define LABEL_IS_SUN 0
118     #define STATIC_SUN extern
119     #endif
120    
121     #if ENABLE_FEATURE_SGI_LABEL
122 niro 816 #define LABEL_IS_SGI (LABEL_SGI == current_label_type)
123 niro 532 #define STATIC_SGI static
124     #else
125     #define LABEL_IS_SGI 0
126     #define STATIC_SGI extern
127     #endif
128    
129     #if ENABLE_FEATURE_AIX_LABEL
130 niro 816 #define LABEL_IS_AIX (LABEL_AIX == current_label_type)
131 niro 532 #define STATIC_AIX static
132     #else
133     #define LABEL_IS_AIX 0
134     #define STATIC_AIX extern
135     #endif
136    
137     #if ENABLE_FEATURE_OSF_LABEL
138 niro 816 #define LABEL_IS_OSF (LABEL_OSF == current_label_type)
139 niro 532 #define STATIC_OSF static
140     #else
141     #define LABEL_IS_OSF 0
142     #define STATIC_OSF extern
143     #endif
144    
145 niro 816 enum action { OPEN_MAIN, TRY_ONLY, CREATE_EMPTY_DOS, CREATE_EMPTY_SUN };
146 niro 532
147 niro 816 static void update_units(void);
148 niro 532 #if ENABLE_FEATURE_FDISK_WRITABLE
149     static void change_units(void);
150     static void reread_partition_table(int leave);
151     static void delete_partition(int i);
152 niro 984 static unsigned get_partition(int warn, unsigned max);
153 niro 816 static void list_types(const char *const *sys);
154 niro 984 static sector_t read_int(sector_t low, sector_t dflt, sector_t high, sector_t base, const char *mesg);
155 niro 532 #endif
156     static const char *partition_type(unsigned char type);
157     static void get_geometry(void);
158 niro 816 #if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE
159 niro 532 static int get_boot(enum action what);
160 niro 816 #else
161     static int get_boot(void);
162     #endif
163 niro 532
164     #define PLURAL 0
165     #define SINGULAR 1
166    
167 niro 984 static sector_t get_start_sect(const struct partition *p);
168     static sector_t get_nr_sects(const struct partition *p);
169 niro 532
170     /*
171     * per partition table entry data
172     *
173     * The four primary partitions have the same sectorbuffer (MBRbuffer)
174     * and have NULL ext_pointer.
175     * Each logical partition table entry has two pointers, one for the
176     * partition and one link to the next one.
177     */
178 niro 816 struct pte {
179 niro 532 struct partition *part_table; /* points into sectorbuffer */
180     struct partition *ext_pointer; /* points into sectorbuffer */
181 niro 984 sector_t offset; /* disk sector number */
182     char *sectorbuffer; /* disk sector contents */
183 niro 532 #if ENABLE_FEATURE_FDISK_WRITABLE
184     char changed; /* boolean */
185     #endif
186 niro 816 };
187 niro 532
188 niro 816 /* DOS partition types */
189 niro 532
190 niro 816 static const char *const i386_sys_types[] = {
191     "\x00" "Empty",
192     "\x01" "FAT12",
193     "\x04" "FAT16 <32M",
194     "\x05" "Extended", /* DOS 3.3+ extended partition */
195     "\x06" "FAT16", /* DOS 16-bit >=32M */
196     "\x07" "HPFS/NTFS", /* OS/2 IFS, eg, HPFS or NTFS or QNX */
197     "\x0a" "OS/2 Boot Manager",/* OS/2 Boot Manager */
198     "\x0b" "Win95 FAT32",
199     "\x0c" "Win95 FAT32 (LBA)",/* LBA really is 'Extended Int 13h' */
200     "\x0e" "Win95 FAT16 (LBA)",
201     "\x0f" "Win95 Ext'd (LBA)",
202     "\x11" "Hidden FAT12",
203     "\x12" "Compaq diagnostics",
204     "\x14" "Hidden FAT16 <32M",
205     "\x16" "Hidden FAT16",
206     "\x17" "Hidden HPFS/NTFS",
207     "\x1b" "Hidden Win95 FAT32",
208     "\x1c" "Hidden W95 FAT32 (LBA)",
209     "\x1e" "Hidden W95 FAT16 (LBA)",
210     "\x3c" "Part.Magic recovery",
211     "\x41" "PPC PReP Boot",
212     "\x42" "SFS",
213     "\x63" "GNU HURD or SysV", /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
214     "\x80" "Old Minix", /* Minix 1.4a and earlier */
215     "\x81" "Minix / old Linux",/* Minix 1.4b and later */
216     "\x82" "Linux swap", /* also Solaris */
217     "\x83" "Linux",
218     "\x84" "OS/2 hidden C: drive",
219     "\x85" "Linux extended",
220     "\x86" "NTFS volume set",
221     "\x87" "NTFS volume set",
222     "\x8e" "Linux LVM",
223     "\x9f" "BSD/OS", /* BSDI */
224     "\xa0" "Thinkpad hibernation",
225     "\xa5" "FreeBSD", /* various BSD flavours */
226     "\xa6" "OpenBSD",
227     "\xa8" "Darwin UFS",
228     "\xa9" "NetBSD",
229     "\xab" "Darwin boot",
230     "\xb7" "BSDI fs",
231     "\xb8" "BSDI swap",
232     "\xbe" "Solaris boot",
233     "\xeb" "BeOS fs",
234     "\xee" "EFI GPT", /* Intel EFI GUID Partition Table */
235     "\xef" "EFI (FAT-12/16/32)", /* Intel EFI System Partition */
236     "\xf0" "Linux/PA-RISC boot", /* Linux/PA-RISC boot loader */
237     "\xf2" "DOS secondary", /* DOS 3.3+ secondary */
238     "\xfd" "Linux raid autodetect", /* New (2.2.x) raid partition with
239     autodetect using persistent
240     superblock */
241     #if 0 /* ENABLE_WEIRD_PARTITION_TYPES */
242     "\x02" "XENIX root",
243     "\x03" "XENIX usr",
244     "\x08" "AIX", /* AIX boot (AIX -- PS/2 port) or SplitDrive */
245     "\x09" "AIX bootable", /* AIX data or Coherent */
246     "\x10" "OPUS",
247     "\x18" "AST SmartSleep",
248     "\x24" "NEC DOS",
249     "\x39" "Plan 9",
250     "\x40" "Venix 80286",
251     "\x4d" "QNX4.x",
252     "\x4e" "QNX4.x 2nd part",
253     "\x4f" "QNX4.x 3rd part",
254     "\x50" "OnTrack DM",
255     "\x51" "OnTrack DM6 Aux1", /* (or Novell) */
256     "\x52" "CP/M", /* CP/M or Microport SysV/AT */
257     "\x53" "OnTrack DM6 Aux3",
258     "\x54" "OnTrackDM6",
259     "\x55" "EZ-Drive",
260     "\x56" "Golden Bow",
261     "\x5c" "Priam Edisk",
262     "\x61" "SpeedStor",
263     "\x64" "Novell Netware 286",
264     "\x65" "Novell Netware 386",
265     "\x70" "DiskSecure Multi-Boot",
266     "\x75" "PC/IX",
267     "\x93" "Amoeba",
268     "\x94" "Amoeba BBT", /* (bad block table) */
269     "\xa7" "NeXTSTEP",
270     "\xbb" "Boot Wizard hidden",
271     "\xc1" "DRDOS/sec (FAT-12)",
272     "\xc4" "DRDOS/sec (FAT-16 < 32M)",
273     "\xc6" "DRDOS/sec (FAT-16)",
274     "\xc7" "Syrinx",
275     "\xda" "Non-FS data",
276     "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or
277     Concurrent DOS or CTOS */
278     "\xde" "Dell Utility", /* Dell PowerEdge Server utilities */
279     "\xdf" "BootIt", /* BootIt EMBRM */
280     "\xe1" "DOS access", /* DOS access or SpeedStor 12-bit FAT
281     extended partition */
282     "\xe3" "DOS R/O", /* DOS R/O or SpeedStor */
283     "\xe4" "SpeedStor", /* SpeedStor 16-bit FAT extended
284     partition < 1024 cyl. */
285     "\xf1" "SpeedStor",
286     "\xf4" "SpeedStor", /* SpeedStor large partition */
287     "\xfe" "LANstep", /* SpeedStor >1024 cyl. or LANstep */
288     "\xff" "BBT", /* Xenix Bad Block Table */
289     #endif
290     NULL
291     };
292    
293     enum {
294     dev_fd = 3 /* the disk */
295     };
296    
297     /* Globals */
298     struct globals {
299     char *line_ptr;
300    
301     const char *disk_device;
302     int g_partitions; // = 4; /* maximum partition + 1 */
303     unsigned units_per_sector; // = 1;
304     unsigned sector_size; // = DEFAULT_SECTOR_SIZE;
305     unsigned user_set_sector_size;
306     unsigned sector_offset; // = 1;
307     unsigned g_heads, g_sectors, g_cylinders;
308     smallint /* enum label_type */ current_label_type;
309     smallint display_in_cyl_units; // = 1;
310     #if ENABLE_FEATURE_OSF_LABEL
311     smallint possibly_osf_label;
312     #endif
313    
314     smallint listing; /* no aborts for fdisk -l */
315     smallint dos_compatible_flag; // = 1;
316 niro 532 #if ENABLE_FEATURE_FDISK_WRITABLE
317 niro 816 //int dos_changed;
318     smallint nowarn; /* no warnings for fdisk -l/-s */
319     #endif
320     int ext_index; /* the prime extended partition */
321     unsigned user_cylinders, user_heads, user_sectors;
322     unsigned pt_heads, pt_sectors;
323     unsigned kern_heads, kern_sectors;
324 niro 984 sector_t extended_offset; /* offset of link pointers */
325     sector_t total_number_of_sectors;
326 niro 816
327     jmp_buf listingbuf;
328     char line_buffer[80];
329     char partname_buffer[80];
330     /* Raw disk label. For DOS-type partition tables the MBR,
331     * with descriptions of the primary partitions. */
332     char MBRbuffer[MAX_SECTOR_SIZE];
333     /* Partition tables */
334     struct pte ptes[MAXIMUM_PARTS];
335     };
336     #define G (*ptr_to_globals)
337     #define line_ptr (G.line_ptr )
338     #define disk_device (G.disk_device )
339     #define g_partitions (G.g_partitions )
340     #define units_per_sector (G.units_per_sector )
341     #define sector_size (G.sector_size )
342     #define user_set_sector_size (G.user_set_sector_size)
343     #define sector_offset (G.sector_offset )
344     #define g_heads (G.g_heads )
345     #define g_sectors (G.g_sectors )
346     #define g_cylinders (G.g_cylinders )
347     #define current_label_type (G.current_label_type )
348     #define display_in_cyl_units (G.display_in_cyl_units)
349     #define possibly_osf_label (G.possibly_osf_label )
350     #define listing (G.listing )
351     #define dos_compatible_flag (G.dos_compatible_flag )
352     #define nowarn (G.nowarn )
353     #define ext_index (G.ext_index )
354     #define user_cylinders (G.user_cylinders )
355     #define user_heads (G.user_heads )
356     #define user_sectors (G.user_sectors )
357     #define pt_heads (G.pt_heads )
358     #define pt_sectors (G.pt_sectors )
359     #define kern_heads (G.kern_heads )
360     #define kern_sectors (G.kern_sectors )
361     #define extended_offset (G.extended_offset )
362     #define total_number_of_sectors (G.total_number_of_sectors)
363     #define listingbuf (G.listingbuf )
364     #define line_buffer (G.line_buffer )
365     #define partname_buffer (G.partname_buffer)
366     #define MBRbuffer (G.MBRbuffer )
367     #define ptes (G.ptes )
368     #define INIT_G() do { \
369     SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
370     sector_size = DEFAULT_SECTOR_SIZE; \
371     sector_offset = 1; \
372     g_partitions = 4; \
373     display_in_cyl_units = 1; \
374     units_per_sector = 1; \
375     dos_compatible_flag = 1; \
376     } while (0)
377    
378    
379     /* TODO: move to libbb? */
380 niro 984 /* TODO: return unsigned long long, FEATURE_FDISK_BLKSIZE _can_ handle
381     * disks > 2^32 sectors
382     */
383     static sector_t bb_BLKGETSIZE_sectors(int fd)
384 niro 816 {
385     uint64_t v64;
386     unsigned long longsectors;
387    
388     if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
389     /* Got bytes, convert to 512 byte sectors */
390 niro 984 v64 >>= 9;
391     if (v64 != (sector_t)v64) {
392     ret_trunc:
393     /* Not only DOS, but all other partition tables
394     * we support can't record more than 32 bit
395     * sector counts or offsets
396     */
397     bb_error_msg("device has more than 2^32 sectors, can't use all of them");
398     v64 = (uint32_t)-1L;
399     }
400     return v64;
401 niro 816 }
402     /* Needs temp of type long */
403     if (ioctl(fd, BLKGETSIZE, &longsectors))
404     longsectors = 0;
405 niro 984 if (sizeof(long) > sizeof(sector_t)
406     && longsectors != (sector_t)longsectors
407     ) {
408     goto ret_trunc;
409     }
410 niro 816 return longsectors;
411     }
412    
413    
414     #define IS_EXTENDED(i) \
415     ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
416    
417     #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
418    
419     #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
420    
421     #define pt_offset(b, n) \
422     ((struct partition *)((b) + 0x1be + (n) * sizeof(struct partition)))
423    
424     #define sector(s) ((s) & 0x3f)
425    
426     #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
427    
428     #define hsc2sector(h,s,c) \
429     (sector(s) - 1 + sectors * ((h) + heads * cylinder(s,c)))
430    
431     #define set_hsc(h,s,c,sector) \
432     do { \
433     s = sector % g_sectors + 1; \
434     sector /= g_sectors; \
435     h = sector % g_heads; \
436     sector /= g_heads; \
437     c = sector & 0xff; \
438     s |= (sector >> 2) & 0xc0; \
439     } while (0)
440    
441 niro 532 static void
442 niro 816 close_dev_fd(void)
443     {
444     /* Not really closing, but making sure it is open, and to harmless place */
445     xmove_fd(xopen(bb_dev_null, O_RDONLY), dev_fd);
446     }
447    
448     #if ENABLE_FEATURE_FDISK_WRITABLE
449     /* Read line; return 0 or first printable char */
450     static int
451     read_line(const char *prompt)
452     {
453     int sz;
454    
455     sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
456     if (sz <= 0)
457     exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
458    
459     if (line_buffer[sz-1] == '\n')
460     line_buffer[--sz] = '\0';
461    
462     line_ptr = line_buffer;
463 niro 984 while (*line_ptr != '\0' && (unsigned char)*line_ptr <= ' ')
464 niro 816 line_ptr++;
465     return *line_ptr;
466     }
467     #endif
468    
469     /*
470     * Return partition name - uses static storage
471     */
472     static const char *
473     partname(const char *dev, int pno, int lth)
474     {
475     const char *p;
476     int w, wp;
477     int bufsiz;
478     char *bufp;
479    
480     bufp = partname_buffer;
481     bufsiz = sizeof(partname_buffer);
482    
483     w = strlen(dev);
484     p = "";
485    
486     if (isdigit(dev[w-1]))
487     p = "p";
488    
489     /* devfs kludge - note: fdisk partition names are not supposed
490     to equal kernel names, so there is no reason to do this */
491     if (strcmp(dev + w - 4, "disc") == 0) {
492     w -= 4;
493     p = "part";
494     }
495    
496     wp = strlen(p);
497    
498     if (lth) {
499     snprintf(bufp, bufsiz, "%*.*s%s%-2u",
500     lth-wp-2, w, dev, p, pno);
501     } else {
502     snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
503     }
504     return bufp;
505     }
506    
507     #if ENABLE_FEATURE_FDISK_WRITABLE
508     static void
509 niro 532 set_all_unchanged(void)
510     {
511     int i;
512    
513     for (i = 0; i < MAXIMUM_PARTS; i++)
514     ptes[i].changed = 0;
515     }
516    
517 niro 816 static ALWAYS_INLINE void
518 niro 532 set_changed(int i)
519     {
520     ptes[i].changed = 1;
521     }
522     #endif /* FEATURE_FDISK_WRITABLE */
523    
524 niro 816 static ALWAYS_INLINE struct partition *
525 niro 532 get_part_table(int i)
526     {
527     return ptes[i].part_table;
528     }
529    
530     static const char *
531     str_units(int n)
532     { /* n==1: use singular */
533     if (n == 1)
534 niro 816 return display_in_cyl_units ? "cylinder" : "sector";
535     return display_in_cyl_units ? "cylinders" : "sectors";
536 niro 532 }
537    
538     static int
539     valid_part_table_flag(const char *mbuffer)
540     {
541     return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa);
542     }
543    
544     #if ENABLE_FEATURE_FDISK_WRITABLE
545 niro 816 static ALWAYS_INLINE void
546 niro 532 write_part_table_flag(char *b)
547     {
548     b[510] = 0x55;
549     b[511] = 0xaa;
550     }
551    
552     static char
553     read_nonempty(const char *mesg)
554     {
555 niro 816 while (!read_line(mesg))
556     continue;
557 niro 532 return *line_ptr;
558     }
559    
560     static char
561     read_maybe_empty(const char *mesg)
562     {
563 niro 816 if (!read_line(mesg)) {
564 niro 532 line_ptr = line_buffer;
565 niro 816 line_ptr[0] = '\n';
566     line_ptr[1] = '\0';
567 niro 532 }
568 niro 816 return line_ptr[0];
569 niro 532 }
570    
571     static int
572 niro 816 read_hex(const char *const *sys)
573 niro 532 {
574     unsigned long v;
575     while (1) {
576 niro 816 read_nonempty("Hex code (type L to list codes): ");
577 niro 532 if (*line_ptr == 'l' || *line_ptr == 'L') {
578     list_types(sys);
579     continue;
580     }
581     v = bb_strtoul(line_ptr, NULL, 16);
582     if (v > 0xff)
583     /* Bad input also triggers this */
584     continue;
585     return v;
586     }
587     }
588     #endif /* FEATURE_FDISK_WRITABLE */
589    
590 niro 816 static void fdisk_fatal(const char *why)
591     {
592     if (listing) {
593     close_dev_fd();
594     longjmp(listingbuf, 1);
595     }
596     bb_error_msg_and_die(why, disk_device);
597     }
598    
599     static void
600 niro 984 seek_sector(sector_t secno)
601 niro 816 {
602     #if ENABLE_FDISK_SUPPORT_LARGE_DISKS
603 niro 984 off64_t off = (off64_t)secno * sector_size;
604     if (lseek64(dev_fd, off, SEEK_SET) == (off64_t) -1)
605 niro 816 fdisk_fatal(unable_to_seek);
606     #else
607 niro 984 uint64_t off = (uint64_t)secno * sector_size;
608     if (off > MAXINT(off_t)
609     || lseek(dev_fd, (off_t)off, SEEK_SET) == (off_t) -1
610 niro 816 ) {
611     fdisk_fatal(unable_to_seek);
612     }
613     #endif
614     }
615    
616     #if ENABLE_FEATURE_FDISK_WRITABLE
617     static void
618 niro 984 write_sector(sector_t secno, const void *buf)
619 niro 816 {
620     seek_sector(secno);
621     xwrite(dev_fd, buf, sector_size);
622     }
623     #endif
624    
625    
626 niro 532 #include "fdisk_aix.c"
627    
628     typedef struct {
629     unsigned char info[128]; /* Informative text string */
630     unsigned char spare0[14];
631     struct sun_info {
632     unsigned char spare1;
633     unsigned char id;
634     unsigned char spare2;
635     unsigned char flags;
636     } infos[8];
637     unsigned char spare1[246]; /* Boot information etc. */
638     unsigned short rspeed; /* Disk rotational speed */
639     unsigned short pcylcount; /* Physical cylinder count */
640     unsigned short sparecyl; /* extra sects per cylinder */
641     unsigned char spare2[4]; /* More magic... */
642     unsigned short ilfact; /* Interleave factor */
643     unsigned short ncyl; /* Data cylinder count */
644     unsigned short nacyl; /* Alt. cylinder count */
645     unsigned short ntrks; /* Tracks per cylinder */
646     unsigned short nsect; /* Sectors per track */
647     unsigned char spare3[4]; /* Even more magic... */
648     struct sun_partinfo {
649     uint32_t start_cylinder;
650     uint32_t num_sectors;
651     } partitions[8];
652     unsigned short magic; /* Magic number */
653     unsigned short csum; /* Label xor'd checksum */
654     } sun_partition;
655     #define sunlabel ((sun_partition *)MBRbuffer)
656     STATIC_OSF void bsd_select(void);
657     STATIC_OSF void xbsd_print_disklabel(int);
658     #include "fdisk_osf.c"
659    
660     #if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
661     static uint16_t
662     fdisk_swap16(uint16_t x)
663     {
664     return (x << 8) | (x >> 8);
665     }
666    
667     static uint32_t
668     fdisk_swap32(uint32_t x)
669     {
670     return (x << 24) |
671     ((x & 0xFF00) << 8) |
672     ((x & 0xFF0000) >> 8) |
673     (x >> 24);
674     }
675     #endif
676    
677 niro 816 STATIC_SGI const char *const sgi_sys_types[];
678 niro 532 STATIC_SGI unsigned sgi_get_num_sectors(int i);
679     STATIC_SGI int sgi_get_sysid(int i);
680     STATIC_SGI void sgi_delete_partition(int i);
681     STATIC_SGI void sgi_change_sysid(int i, int sys);
682     STATIC_SGI void sgi_list_table(int xtra);
683     #if ENABLE_FEATURE_FDISK_ADVANCED
684     STATIC_SGI void sgi_set_xcyl(void);
685     #endif
686     STATIC_SGI int verify_sgi(int verbose);
687     STATIC_SGI void sgi_add_partition(int n, int sys);
688     STATIC_SGI void sgi_set_swappartition(int i);
689     STATIC_SGI const char *sgi_get_bootfile(void);
690     STATIC_SGI void sgi_set_bootfile(const char* aFile);
691     STATIC_SGI void create_sgiinfo(void);
692     STATIC_SGI void sgi_write_table(void);
693     STATIC_SGI void sgi_set_bootpartition(int i);
694     #include "fdisk_sgi.c"
695    
696 niro 816 STATIC_SUN const char *const sun_sys_types[];
697 niro 532 STATIC_SUN void sun_delete_partition(int i);
698     STATIC_SUN void sun_change_sysid(int i, int sys);
699     STATIC_SUN void sun_list_table(int xtra);
700     STATIC_SUN void add_sun_partition(int n, int sys);
701     #if ENABLE_FEATURE_FDISK_ADVANCED
702     STATIC_SUN void sun_set_alt_cyl(void);
703     STATIC_SUN void sun_set_ncyl(int cyl);
704     STATIC_SUN void sun_set_xcyl(void);
705     STATIC_SUN void sun_set_ilfact(void);
706     STATIC_SUN void sun_set_rspeed(void);
707     STATIC_SUN void sun_set_pcylcount(void);
708     #endif
709     STATIC_SUN void toggle_sunflags(int i, unsigned char mask);
710     STATIC_SUN void verify_sun(void);
711     STATIC_SUN void sun_write_table(void);
712     #include "fdisk_sun.c"
713    
714    
715     #if ENABLE_FEATURE_FDISK_WRITABLE
716     /* start_sect and nr_sects are stored little endian on all machines */
717     /* moreover, they are not aligned correctly */
718     static void
719     store4_little_endian(unsigned char *cp, unsigned val)
720     {
721     cp[0] = val;
722     cp[1] = val >> 8;
723     cp[2] = val >> 16;
724     cp[3] = val >> 24;
725     }
726     #endif /* FEATURE_FDISK_WRITABLE */
727    
728     static unsigned
729     read4_little_endian(const unsigned char *cp)
730     {
731     return cp[0] + (cp[1] << 8) + (cp[2] << 16) + (cp[3] << 24);
732     }
733    
734     #if ENABLE_FEATURE_FDISK_WRITABLE
735     static void
736     set_start_sect(struct partition *p, unsigned start_sect)
737     {
738     store4_little_endian(p->start4, start_sect);
739     }
740     #endif
741    
742 niro 984 static sector_t
743 niro 532 get_start_sect(const struct partition *p)
744     {
745     return read4_little_endian(p->start4);
746     }
747    
748     #if ENABLE_FEATURE_FDISK_WRITABLE
749     static void
750     set_nr_sects(struct partition *p, unsigned nr_sects)
751     {
752     store4_little_endian(p->size4, nr_sects);
753     }
754     #endif
755    
756 niro 984 static sector_t
757 niro 532 get_nr_sects(const struct partition *p)
758     {
759     return read4_little_endian(p->size4);
760     }
761    
762     /* Allocate a buffer and read a partition table sector */
763     static void
764 niro 984 read_pte(struct pte *pe, sector_t offset)
765 niro 532 {
766     pe->offset = offset;
767 niro 816 pe->sectorbuffer = xzalloc(sector_size);
768 niro 532 seek_sector(offset);
769 niro 816 /* xread would make us abort - bad for fdisk -l */
770     if (full_read(dev_fd, pe->sectorbuffer, sector_size) != sector_size)
771 niro 532 fdisk_fatal(unable_to_read);
772     #if ENABLE_FEATURE_FDISK_WRITABLE
773     pe->changed = 0;
774     #endif
775     pe->part_table = pe->ext_pointer = NULL;
776     }
777    
778 niro 984 static sector_t
779 niro 532 get_partition_start(const struct pte *pe)
780     {
781     return pe->offset + get_start_sect(pe->part_table);
782     }
783    
784     #if ENABLE_FEATURE_FDISK_WRITABLE
785     /*
786     * Avoid warning about DOS partitions when no DOS partition was changed.
787     * Here a heuristic "is probably dos partition".
788     * We might also do the opposite and warn in all cases except
789     * for "is probably nondos partition".
790     */
791 niro 816 #ifdef UNUSED
792 niro 532 static int
793     is_dos_partition(int t)
794     {
795     return (t == 1 || t == 4 || t == 6 ||
796     t == 0x0b || t == 0x0c || t == 0x0e ||
797     t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
798     t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
799     t == 0xc1 || t == 0xc4 || t == 0xc6);
800     }
801 niro 816 #endif
802 niro 532
803     static void
804     menu(void)
805     {
806 niro 816 puts("Command Action");
807 niro 532 if (LABEL_IS_SUN) {
808 niro 816 puts("a\ttoggle a read only flag"); /* sun */
809     puts("b\tedit bsd disklabel");
810     puts("c\ttoggle the mountable flag"); /* sun */
811     puts("d\tdelete a partition");
812     puts("l\tlist known partition types");
813     puts("n\tadd a new partition");
814     puts("o\tcreate a new empty DOS partition table");
815     puts("p\tprint the partition table");
816     puts("q\tquit without saving changes");
817     puts("s\tcreate a new empty Sun disklabel"); /* sun */
818     puts("t\tchange a partition's system id");
819     puts("u\tchange display/entry units");
820     puts("v\tverify the partition table");
821     puts("w\twrite table to disk and exit");
822 niro 532 #if ENABLE_FEATURE_FDISK_ADVANCED
823 niro 816 puts("x\textra functionality (experts only)");
824 niro 532 #endif
825 niro 816 } else if (LABEL_IS_SGI) {
826     puts("a\tselect bootable partition"); /* sgi flavour */
827     puts("b\tedit bootfile entry"); /* sgi */
828     puts("c\tselect sgi swap partition"); /* sgi flavour */
829     puts("d\tdelete a partition");
830     puts("l\tlist known partition types");
831     puts("n\tadd a new partition");
832     puts("o\tcreate a new empty DOS partition table");
833     puts("p\tprint the partition table");
834     puts("q\tquit without saving changes");
835     puts("s\tcreate a new empty Sun disklabel"); /* sun */
836     puts("t\tchange a partition's system id");
837     puts("u\tchange display/entry units");
838     puts("v\tverify the partition table");
839     puts("w\twrite table to disk and exit");
840     } else if (LABEL_IS_AIX) {
841     puts("o\tcreate a new empty DOS partition table");
842     puts("q\tquit without saving changes");
843     puts("s\tcreate a new empty Sun disklabel"); /* sun */
844     } else {
845     puts("a\ttoggle a bootable flag");
846     puts("b\tedit bsd disklabel");
847     puts("c\ttoggle the dos compatibility flag");
848     puts("d\tdelete a partition");
849     puts("l\tlist known partition types");
850     puts("n\tadd a new partition");
851     puts("o\tcreate a new empty DOS partition table");
852     puts("p\tprint the partition table");
853     puts("q\tquit without saving changes");
854     puts("s\tcreate a new empty Sun disklabel"); /* sun */
855     puts("t\tchange a partition's system id");
856     puts("u\tchange display/entry units");
857     puts("v\tverify the partition table");
858     puts("w\twrite table to disk and exit");
859 niro 532 #if ENABLE_FEATURE_FDISK_ADVANCED
860 niro 816 puts("x\textra functionality (experts only)");
861 niro 532 #endif
862     }
863     }
864     #endif /* FEATURE_FDISK_WRITABLE */
865    
866    
867     #if ENABLE_FEATURE_FDISK_ADVANCED
868     static void
869     xmenu(void)
870     {
871 niro 816 puts("Command Action");
872 niro 532 if (LABEL_IS_SUN) {
873 niro 816 puts("a\tchange number of alternate cylinders"); /*sun*/
874     puts("c\tchange number of cylinders");
875     puts("d\tprint the raw data in the partition table");
876     puts("e\tchange number of extra sectors per cylinder");/*sun*/
877     puts("h\tchange number of heads");
878     puts("i\tchange interleave factor"); /*sun*/
879     puts("o\tchange rotation speed (rpm)"); /*sun*/
880     puts("p\tprint the partition table");
881     puts("q\tquit without saving changes");
882     puts("r\treturn to main menu");
883     puts("s\tchange number of sectors/track");
884     puts("v\tverify the partition table");
885     puts("w\twrite table to disk and exit");
886     puts("y\tchange number of physical cylinders"); /*sun*/
887     } else if (LABEL_IS_SGI) {
888     puts("b\tmove beginning of data in a partition"); /* !sun */
889     puts("c\tchange number of cylinders");
890     puts("d\tprint the raw data in the partition table");
891     puts("e\tlist extended partitions"); /* !sun */
892     puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
893     puts("h\tchange number of heads");
894     puts("p\tprint the partition table");
895     puts("q\tquit without saving changes");
896     puts("r\treturn to main menu");
897     puts("s\tchange number of sectors/track");
898     puts("v\tverify the partition table");
899     puts("w\twrite table to disk and exit");
900     } else if (LABEL_IS_AIX) {
901     puts("b\tmove beginning of data in a partition"); /* !sun */
902     puts("c\tchange number of cylinders");
903     puts("d\tprint the raw data in the partition table");
904     puts("e\tlist extended partitions"); /* !sun */
905     puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
906     puts("h\tchange number of heads");
907     puts("p\tprint the partition table");
908     puts("q\tquit without saving changes");
909     puts("r\treturn to main menu");
910     puts("s\tchange number of sectors/track");
911     puts("v\tverify the partition table");
912     puts("w\twrite table to disk and exit");
913     } else {
914     puts("b\tmove beginning of data in a partition"); /* !sun */
915     puts("c\tchange number of cylinders");
916     puts("d\tprint the raw data in the partition table");
917     puts("e\tlist extended partitions"); /* !sun */
918     puts("f\tfix partition order"); /* !sun, !aix, !sgi */
919 niro 532 #if ENABLE_FEATURE_SGI_LABEL
920 niro 816 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
921 niro 532 #endif
922 niro 816 puts("h\tchange number of heads");
923     puts("p\tprint the partition table");
924     puts("q\tquit without saving changes");
925     puts("r\treturn to main menu");
926     puts("s\tchange number of sectors/track");
927     puts("v\tverify the partition table");
928     puts("w\twrite table to disk and exit");
929 niro 532 }
930     }
931     #endif /* ADVANCED mode */
932    
933     #if ENABLE_FEATURE_FDISK_WRITABLE
934 niro 816 static const char *const *
935 niro 532 get_sys_types(void)
936     {
937     return (
938     LABEL_IS_SUN ? sun_sys_types :
939     LABEL_IS_SGI ? sgi_sys_types :
940     i386_sys_types);
941     }
942     #else
943     #define get_sys_types() i386_sys_types
944     #endif /* FEATURE_FDISK_WRITABLE */
945    
946 niro 816 static const char *
947     partition_type(unsigned char type)
948 niro 532 {
949     int i;
950 niro 816 const char *const *types = get_sys_types();
951 niro 532
952 niro 816 for (i = 0; types[i]; i++)
953     if ((unsigned char)types[i][0] == type)
954     return types[i] + 1;
955 niro 532
956 niro 816 return "Unknown";
957 niro 532 }
958    
959    
960     #if ENABLE_FEATURE_FDISK_WRITABLE
961     static int
962     get_sysid(int i)
963     {
964     return LABEL_IS_SUN ? sunlabel->infos[i].id :
965     (LABEL_IS_SGI ? sgi_get_sysid(i) :
966     ptes[i].part_table->sys_ind);
967     }
968    
969 niro 816 static void
970     list_types(const char *const *sys)
971 niro 532 {
972 niro 816 enum { COLS = 3 };
973    
974     unsigned last[COLS];
975     unsigned done, next, size;
976 niro 532 int i;
977    
978 niro 816 for (size = 0; sys[size]; size++)
979     continue;
980 niro 532
981 niro 816 done = 0;
982     for (i = COLS-1; i >= 0; i--) {
983     done += (size + i - done) / (i + 1);
984     last[COLS-1 - i] = done;
985     }
986 niro 532
987 niro 816 i = done = next = 0;
988 niro 532 do {
989 niro 816 printf("%c%2x %-22.22s", i ? ' ' : '\n',
990     (unsigned char)sys[next][0],
991     sys[next] + 1);
992 niro 532 next = last[i++] + done;
993 niro 816 if (i >= COLS || next >= last[i]) {
994 niro 532 i = 0;
995     next = ++done;
996     }
997     } while (done < last[0]);
998 niro 816 bb_putchar('\n');
999 niro 532 }
1000     #endif /* FEATURE_FDISK_WRITABLE */
1001    
1002     static int
1003     is_cleared_partition(const struct partition *p)
1004     {
1005     return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
1006     p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
1007     get_start_sect(p) || get_nr_sects(p));
1008     }
1009    
1010     static void
1011     clear_partition(struct partition *p)
1012     {
1013     if (!p)
1014     return;
1015     memset(p, 0, sizeof(struct partition));
1016     }
1017    
1018     #if ENABLE_FEATURE_FDISK_WRITABLE
1019     static void
1020 niro 984 set_partition(int i, int doext, sector_t start, sector_t stop, int sysid)
1021 niro 532 {
1022     struct partition *p;
1023 niro 984 sector_t offset;
1024 niro 532
1025     if (doext) {
1026     p = ptes[i].ext_pointer;
1027     offset = extended_offset;
1028     } else {
1029     p = ptes[i].part_table;
1030     offset = ptes[i].offset;
1031     }
1032     p->boot_ind = 0;
1033     p->sys_ind = sysid;
1034     set_start_sect(p, start - offset);
1035     set_nr_sects(p, stop - start + 1);
1036 niro 816 if (dos_compatible_flag && (start / (g_sectors * g_heads) > 1023))
1037     start = g_heads * g_sectors * 1024 - 1;
1038 niro 532 set_hsc(p->head, p->sector, p->cyl, start);
1039 niro 816 if (dos_compatible_flag && (stop / (g_sectors * g_heads) > 1023))
1040     stop = g_heads * g_sectors * 1024 - 1;
1041 niro 532 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
1042     ptes[i].changed = 1;
1043     }
1044     #endif
1045    
1046     static int
1047     warn_geometry(void)
1048     {
1049 niro 816 if (g_heads && g_sectors && g_cylinders)
1050 niro 532 return 0;
1051    
1052 niro 816 printf("Unknown value(s) for:");
1053     if (!g_heads)
1054     printf(" heads");
1055     if (!g_sectors)
1056     printf(" sectors");
1057     if (!g_cylinders)
1058     printf(" cylinders");
1059     printf(
1060 niro 532 #if ENABLE_FEATURE_FDISK_WRITABLE
1061 niro 816 " (settable in the extra functions menu)"
1062 niro 532 #endif
1063 niro 816 "\n");
1064 niro 532 return 1;
1065     }
1066    
1067 niro 816 static void
1068     update_units(void)
1069 niro 532 {
1070 niro 816 int cyl_units = g_heads * g_sectors;
1071 niro 532
1072     if (display_in_cyl_units && cyl_units)
1073     units_per_sector = cyl_units;
1074     else
1075     units_per_sector = 1; /* in sectors */
1076     }
1077    
1078     #if ENABLE_FEATURE_FDISK_WRITABLE
1079     static void
1080     warn_cylinders(void)
1081     {
1082 niro 816 if (LABEL_IS_DOS && g_cylinders > 1024 && !nowarn)
1083     printf("\n"
1084 niro 984 "The number of cylinders for this disk is set to %u.\n"
1085 niro 532 "There is nothing wrong with that, but this is larger than 1024,\n"
1086     "and could in certain setups cause problems with:\n"
1087     "1) software that runs at boot time (e.g., old versions of LILO)\n"
1088     "2) booting and partitioning software from other OSs\n"
1089 niro 816 " (e.g., DOS FDISK, OS/2 FDISK)\n",
1090     g_cylinders);
1091 niro 532 }
1092     #endif
1093    
1094     static void
1095     read_extended(int ext)
1096     {
1097     int i;
1098     struct pte *pex;
1099     struct partition *p, *q;
1100    
1101     ext_index = ext;
1102     pex = &ptes[ext];
1103     pex->ext_pointer = pex->part_table;
1104    
1105     p = pex->part_table;
1106     if (!get_start_sect(p)) {
1107 niro 816 printf("Bad offset in primary extended partition\n");
1108 niro 532 return;
1109     }
1110    
1111     while (IS_EXTENDED(p->sys_ind)) {
1112 niro 816 struct pte *pe = &ptes[g_partitions];
1113 niro 532
1114 niro 816 if (g_partitions >= MAXIMUM_PARTS) {
1115 niro 532 /* This is not a Linux restriction, but
1116     this program uses arrays of size MAXIMUM_PARTS.
1117     Do not try to 'improve' this test. */
1118 niro 816 struct pte *pre = &ptes[g_partitions - 1];
1119 niro 532 #if ENABLE_FEATURE_FDISK_WRITABLE
1120 niro 984 printf("Warning: deleting partitions after %u\n",
1121 niro 816 g_partitions);
1122 niro 532 pre->changed = 1;
1123     #endif
1124     clear_partition(pre->ext_pointer);
1125     return;
1126     }
1127    
1128     read_pte(pe, extended_offset + get_start_sect(p));
1129    
1130     if (!extended_offset)
1131     extended_offset = get_start_sect(p);
1132    
1133     q = p = pt_offset(pe->sectorbuffer, 0);
1134     for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
1135     if (IS_EXTENDED(p->sys_ind)) {
1136     if (pe->ext_pointer)
1137 niro 816 printf("Warning: extra link "
1138 niro 532 "pointer in partition table"
1139 niro 984 " %u\n", g_partitions + 1);
1140 niro 532 else
1141     pe->ext_pointer = p;
1142     } else if (p->sys_ind) {
1143     if (pe->part_table)
1144 niro 816 printf("Warning: ignoring extra "
1145 niro 532 "data in partition table"
1146 niro 984 " %u\n", g_partitions + 1);
1147 niro 532 else
1148     pe->part_table = p;
1149     }
1150     }
1151    
1152     /* very strange code here... */
1153     if (!pe->part_table) {
1154     if (q != pe->ext_pointer)
1155     pe->part_table = q;
1156     else
1157     pe->part_table = q + 1;
1158     }
1159     if (!pe->ext_pointer) {
1160     if (q != pe->part_table)
1161     pe->ext_pointer = q;
1162     else
1163     pe->ext_pointer = q + 1;
1164     }
1165    
1166     p = pe->ext_pointer;
1167 niro 816 g_partitions++;
1168 niro 532 }
1169    
1170     #if ENABLE_FEATURE_FDISK_WRITABLE
1171     /* remove empty links */
1172     remove:
1173 niro 816 for (i = 4; i < g_partitions; i++) {
1174 niro 532 struct pte *pe = &ptes[i];
1175    
1176 niro 816 if (!get_nr_sects(pe->part_table)
1177     && (g_partitions > 5 || ptes[4].part_table->sys_ind)
1178     ) {
1179 niro 984 printf("Omitting empty partition (%u)\n", i+1);
1180 niro 532 delete_partition(i);
1181     goto remove; /* numbering changed */
1182     }
1183     }
1184     #endif
1185     }
1186    
1187     #if ENABLE_FEATURE_FDISK_WRITABLE
1188     static void
1189     create_doslabel(void)
1190     {
1191     int i;
1192    
1193 niro 816 printf(msg_building_new_label, "DOS disklabel");
1194 niro 532
1195 niro 816 current_label_type = LABEL_DOS;
1196 niro 532
1197     #if ENABLE_FEATURE_OSF_LABEL
1198     possibly_osf_label = 0;
1199     #endif
1200 niro 816 g_partitions = 4;
1201 niro 532
1202     for (i = 510-64; i < 510; i++)
1203     MBRbuffer[i] = 0;
1204     write_part_table_flag(MBRbuffer);
1205     extended_offset = 0;
1206     set_all_unchanged();
1207     set_changed(0);
1208 niro 816 get_boot(CREATE_EMPTY_DOS);
1209 niro 532 }
1210     #endif /* FEATURE_FDISK_WRITABLE */
1211    
1212     static void
1213     get_sectorsize(void)
1214     {
1215     if (!user_set_sector_size) {
1216     int arg;
1217 niro 816 if (ioctl(dev_fd, BLKSSZGET, &arg) == 0)
1218 niro 532 sector_size = arg;
1219     if (sector_size != DEFAULT_SECTOR_SIZE)
1220 niro 984 printf("Note: sector size is %u "
1221 niro 816 "(not " DEFAULT_SECTOR_SIZE_STR ")\n",
1222     sector_size);
1223 niro 532 }
1224     }
1225    
1226     static void
1227     get_kernel_geometry(void)
1228     {
1229     struct hd_geometry geometry;
1230    
1231 niro 816 if (!ioctl(dev_fd, HDIO_GETGEO, &geometry)) {
1232 niro 532 kern_heads = geometry.heads;
1233     kern_sectors = geometry.sectors;
1234     /* never use geometry.cylinders - it is truncated */
1235     }
1236     }
1237    
1238     static void
1239     get_partition_table_geometry(void)
1240     {
1241     const unsigned char *bufp = (const unsigned char *)MBRbuffer;
1242     struct partition *p;
1243     int i, h, s, hh, ss;
1244     int first = 1;
1245     int bad = 0;
1246    
1247     if (!(valid_part_table_flag((char*)bufp)))
1248     return;
1249    
1250     hh = ss = 0;
1251     for (i = 0; i < 4; i++) {
1252     p = pt_offset(bufp, i);
1253     if (p->sys_ind != 0) {
1254     h = p->end_head + 1;
1255     s = (p->end_sector & 077);
1256     if (first) {
1257     hh = h;
1258     ss = s;
1259     first = 0;
1260     } else if (hh != h || ss != s)
1261     bad = 1;
1262     }
1263     }
1264    
1265     if (!first && !bad) {
1266     pt_heads = hh;
1267     pt_sectors = ss;
1268     }
1269     }
1270    
1271     static void
1272     get_geometry(void)
1273     {
1274     int sec_fac;
1275    
1276     get_sectorsize();
1277     sec_fac = sector_size / 512;
1278     #if ENABLE_FEATURE_SUN_LABEL
1279     guess_device_type();
1280     #endif
1281 niro 816 g_heads = g_cylinders = g_sectors = 0;
1282 niro 532 kern_heads = kern_sectors = 0;
1283     pt_heads = pt_sectors = 0;
1284    
1285     get_kernel_geometry();
1286     get_partition_table_geometry();
1287    
1288 niro 816 g_heads = user_heads ? user_heads :
1289 niro 532 pt_heads ? pt_heads :
1290     kern_heads ? kern_heads : 255;
1291 niro 816 g_sectors = user_sectors ? user_sectors :
1292 niro 532 pt_sectors ? pt_sectors :
1293     kern_sectors ? kern_sectors : 63;
1294 niro 816 total_number_of_sectors = bb_BLKGETSIZE_sectors(dev_fd);
1295 niro 532
1296     sector_offset = 1;
1297     if (dos_compatible_flag)
1298 niro 816 sector_offset = g_sectors;
1299 niro 532
1300 niro 816 g_cylinders = total_number_of_sectors / (g_heads * g_sectors * sec_fac);
1301     if (!g_cylinders)
1302     g_cylinders = user_cylinders;
1303 niro 532 }
1304    
1305     /*
1306 niro 816 * Opens disk_device and optionally reads MBR.
1307     * FIXME: document what each 'what' value will do!
1308     * Returns:
1309 niro 532 * -1: no 0xaa55 flag present (possibly entire disk BSD)
1310     * 0: found or created label
1311     * 1: I/O error
1312     */
1313 niro 816 #if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE
1314     static int get_boot(enum action what)
1315     #else
1316     static int get_boot(void)
1317     #define get_boot(what) get_boot()
1318     #endif
1319 niro 532 {
1320 niro 816 int i, fd;
1321 niro 532
1322 niro 816 g_partitions = 4;
1323 niro 532 for (i = 0; i < 4; i++) {
1324     struct pte *pe = &ptes[i];
1325     pe->part_table = pt_offset(MBRbuffer, i);
1326     pe->ext_pointer = NULL;
1327     pe->offset = 0;
1328     pe->sectorbuffer = MBRbuffer;
1329     #if ENABLE_FEATURE_FDISK_WRITABLE
1330 niro 816 pe->changed = (what == CREATE_EMPTY_DOS);
1331 niro 532 #endif
1332     }
1333    
1334 niro 816 #if ENABLE_FEATURE_FDISK_WRITABLE
1335     // ALERT! highly idiotic design!
1336     // We end up here when we call get_boot() recursively
1337     // via get_boot() [table is bad] -> create_doslabel() -> get_boot(CREATE_EMPTY_DOS).
1338     // or get_boot() [table is bad] -> create_sunlabel() -> get_boot(CREATE_EMPTY_SUN).
1339     // (just factor out re-init of ptes[0,1,2,3] in a separate fn instead?)
1340     // So skip opening device _again_...
1341 niro 984 if (what == CREATE_EMPTY_DOS IF_FEATURE_SUN_LABEL(|| what == CREATE_EMPTY_SUN))
1342 niro 816 goto created_table;
1343 niro 532
1344 niro 816 fd = open(disk_device, (option_mask32 & OPT_l) ? O_RDONLY : O_RDWR);
1345 niro 532
1346 niro 816 if (fd < 0) {
1347     fd = open(disk_device, O_RDONLY);
1348     if (fd < 0) {
1349     if (what == TRY_ONLY)
1350 niro 532 return 1;
1351     fdisk_fatal(unable_to_open);
1352 niro 816 }
1353     printf("'%s' is opened for read only\n", disk_device);
1354 niro 532 }
1355 niro 816 xmove_fd(fd, dev_fd);
1356     if (512 != full_read(dev_fd, MBRbuffer, 512)) {
1357     if (what == TRY_ONLY) {
1358     close_dev_fd();
1359 niro 532 return 1;
1360 niro 816 }
1361 niro 532 fdisk_fatal(unable_to_read);
1362     }
1363     #else
1364 niro 816 fd = open(disk_device, O_RDONLY);
1365     if (fd < 0)
1366 niro 532 return 1;
1367 niro 816 if (512 != full_read(fd, MBRbuffer, 512)) {
1368     close(fd);
1369 niro 532 return 1;
1370 niro 816 }
1371     xmove_fd(fd, dev_fd);
1372 niro 532 #endif
1373    
1374     get_geometry();
1375     update_units();
1376    
1377     #if ENABLE_FEATURE_SUN_LABEL
1378     if (check_sun_label())
1379     return 0;
1380     #endif
1381     #if ENABLE_FEATURE_SGI_LABEL
1382     if (check_sgi_label())
1383     return 0;
1384     #endif
1385     #if ENABLE_FEATURE_AIX_LABEL
1386     if (check_aix_label())
1387     return 0;
1388     #endif
1389     #if ENABLE_FEATURE_OSF_LABEL
1390     if (check_osf_label()) {
1391     possibly_osf_label = 1;
1392     if (!valid_part_table_flag(MBRbuffer)) {
1393 niro 816 current_label_type = LABEL_OSF;
1394 niro 532 return 0;
1395     }
1396 niro 816 printf("This disk has both DOS and BSD magic.\n"
1397     "Give the 'b' command to go to BSD mode.\n");
1398 niro 532 }
1399     #endif
1400    
1401     #if !ENABLE_FEATURE_FDISK_WRITABLE
1402 niro 816 if (!valid_part_table_flag(MBRbuffer))
1403 niro 532 return -1;
1404     #else
1405 niro 816 if (!valid_part_table_flag(MBRbuffer)) {
1406     if (what == OPEN_MAIN) {
1407     printf("Device contains neither a valid DOS "
1408 niro 532 "partition table, nor Sun, SGI or OSF "
1409 niro 816 "disklabel\n");
1410 niro 532 #ifdef __sparc__
1411 niro 984 IF_FEATURE_SUN_LABEL(create_sunlabel();)
1412 niro 532 #else
1413     create_doslabel();
1414     #endif
1415     return 0;
1416     }
1417 niro 816 /* TRY_ONLY: */
1418     return -1;
1419     }
1420     created_table:
1421 niro 532 #endif /* FEATURE_FDISK_WRITABLE */
1422    
1423 niro 816
1424 niro 984 IF_FEATURE_FDISK_WRITABLE(warn_cylinders();)
1425 niro 532 warn_geometry();
1426    
1427     for (i = 0; i < 4; i++) {
1428 niro 816 if (IS_EXTENDED(ptes[i].part_table->sys_ind)) {
1429     if (g_partitions != 4)
1430     printf("Ignoring extra extended "
1431 niro 984 "partition %u\n", i + 1);
1432 niro 532 else
1433     read_extended(i);
1434     }
1435     }
1436    
1437 niro 816 for (i = 3; i < g_partitions; i++) {
1438 niro 532 struct pte *pe = &ptes[i];
1439     if (!valid_part_table_flag(pe->sectorbuffer)) {
1440 niro 816 printf("Warning: invalid flag 0x%02x,0x%02x of partition "
1441 niro 984 "table %u will be corrected by w(rite)\n",
1442 niro 532 pe->sectorbuffer[510],
1443     pe->sectorbuffer[511],
1444     i + 1);
1445 niro 984 IF_FEATURE_FDISK_WRITABLE(pe->changed = 1;)
1446 niro 532 }
1447     }
1448    
1449     return 0;
1450     }
1451    
1452     #if ENABLE_FEATURE_FDISK_WRITABLE
1453     /*
1454     * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
1455     * If the user hits Enter, DFLT is returned.
1456     * Answers like +10 are interpreted as offsets from BASE.
1457     *
1458     * There is no default if DFLT is not between LOW and HIGH.
1459     */
1460 niro 984 static sector_t
1461     read_int(sector_t low, sector_t dflt, sector_t high, sector_t base, const char *mesg)
1462 niro 532 {
1463 niro 984 sector_t value;
1464 niro 532 int default_ok = 1;
1465     const char *fmt = "%s (%u-%u, default %u): ";
1466    
1467     if (dflt < low || dflt > high) {
1468     fmt = "%s (%u-%u): ";
1469     default_ok = 0;
1470     }
1471    
1472     while (1) {
1473     int use_default = default_ok;
1474    
1475     /* ask question and read answer */
1476     do {
1477     printf(fmt, mesg, low, high, dflt);
1478     read_maybe_empty("");
1479     } while (*line_ptr != '\n' && !isdigit(*line_ptr)
1480     && *line_ptr != '-' && *line_ptr != '+');
1481    
1482     if (*line_ptr == '+' || *line_ptr == '-') {
1483     int minus = (*line_ptr == '-');
1484     int absolute = 0;
1485    
1486 niro 984 value = atoi(line_ptr + 1);
1487 niro 532
1488 niro 984 /* (1) if 2nd char is digit, use_default = 0.
1489     * (2) move line_ptr to first non-digit. */
1490 niro 532 while (isdigit(*++line_ptr))
1491     use_default = 0;
1492    
1493     switch (*line_ptr) {
1494     case 'c':
1495     case 'C':
1496     if (!display_in_cyl_units)
1497 niro 984 value *= g_heads * g_sectors;
1498 niro 532 break;
1499     case 'K':
1500     absolute = 1024;
1501     break;
1502     case 'k':
1503     absolute = 1000;
1504     break;
1505     case 'm':
1506     case 'M':
1507     absolute = 1000000;
1508     break;
1509     case 'g':
1510     case 'G':
1511     absolute = 1000000000;
1512     break;
1513     default:
1514     break;
1515     }
1516     if (absolute) {
1517 niro 816 ullong bytes;
1518 niro 532 unsigned long unit;
1519    
1520 niro 984 bytes = (ullong) value * absolute;
1521 niro 532 unit = sector_size * units_per_sector;
1522     bytes += unit/2; /* round */
1523     bytes /= unit;
1524 niro 984 value = bytes;
1525 niro 532 }
1526     if (minus)
1527 niro 984 value = -value;
1528     value += base;
1529 niro 532 } else {
1530 niro 984 value = atoi(line_ptr);
1531 niro 532 while (isdigit(*line_ptr)) {
1532     line_ptr++;
1533     use_default = 0;
1534     }
1535     }
1536 niro 816 if (use_default) {
1537 niro 984 value = dflt;
1538     printf("Using default value %u\n", value);
1539 niro 816 }
1540 niro 984 if (value >= low && value <= high)
1541 niro 532 break;
1542 niro 816 printf("Value is out of range\n");
1543 niro 532 }
1544 niro 984 return value;
1545 niro 532 }
1546    
1547 niro 984 static unsigned
1548     get_partition(int warn, unsigned max)
1549 niro 532 {
1550     struct pte *pe;
1551 niro 984 unsigned i;
1552 niro 532
1553 niro 816 i = read_int(1, 0, max, 0, "Partition number") - 1;
1554 niro 532 pe = &ptes[i];
1555    
1556     if (warn) {
1557     if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind)
1558     || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
1559     || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
1560     ) {
1561 niro 984 printf("Warning: partition %u has empty type\n", i+1);
1562 niro 532 }
1563     }
1564     return i;
1565     }
1566    
1567     static int
1568 niro 984 get_existing_partition(int warn, unsigned max)
1569 niro 532 {
1570     int pno = -1;
1571 niro 984 unsigned i;
1572 niro 532
1573     for (i = 0; i < max; i++) {
1574     struct pte *pe = &ptes[i];
1575     struct partition *p = pe->part_table;
1576    
1577     if (p && !is_cleared_partition(p)) {
1578     if (pno >= 0)
1579     goto not_unique;
1580     pno = i;
1581     }
1582     }
1583     if (pno >= 0) {
1584 niro 984 printf("Selected partition %u\n", pno+1);
1585 niro 532 return pno;
1586     }
1587 niro 816 printf("No partition is defined yet!\n");
1588 niro 532 return -1;
1589    
1590     not_unique:
1591     return get_partition(warn, max);
1592     }
1593    
1594     static int
1595 niro 984 get_nonexisting_partition(int warn, unsigned max)
1596 niro 532 {
1597     int pno = -1;
1598 niro 984 unsigned i;
1599 niro 532
1600     for (i = 0; i < max; i++) {
1601     struct pte *pe = &ptes[i];
1602     struct partition *p = pe->part_table;
1603    
1604     if (p && is_cleared_partition(p)) {
1605     if (pno >= 0)
1606     goto not_unique;
1607     pno = i;
1608     }
1609     }
1610     if (pno >= 0) {
1611 niro 984 printf("Selected partition %u\n", pno+1);
1612 niro 532 return pno;
1613     }
1614 niro 816 printf("All primary partitions have been defined already!\n");
1615 niro 532 return -1;
1616    
1617     not_unique:
1618     return get_partition(warn, max);
1619     }
1620    
1621    
1622     static void
1623     change_units(void)
1624     {
1625     display_in_cyl_units = !display_in_cyl_units;
1626     update_units();
1627 niro 816 printf("Changing display/entry units to %s\n",
1628 niro 532 str_units(PLURAL));
1629     }
1630    
1631     static void
1632     toggle_active(int i)
1633     {
1634     struct pte *pe = &ptes[i];
1635     struct partition *p = pe->part_table;
1636    
1637     if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
1638 niro 984 printf("WARNING: Partition %u is an extended partition\n", i + 1);
1639 niro 532 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1640     pe->changed = 1;
1641     }
1642    
1643     static void
1644     toggle_dos_compatibility_flag(void)
1645     {
1646 niro 816 dos_compatible_flag = 1 - dos_compatible_flag;
1647 niro 532 if (dos_compatible_flag) {
1648 niro 816 sector_offset = g_sectors;
1649     printf("DOS Compatibility flag is set\n");
1650     } else {
1651 niro 532 sector_offset = 1;
1652 niro 816 printf("DOS Compatibility flag is not set\n");
1653 niro 532 }
1654     }
1655    
1656     static void
1657     delete_partition(int i)
1658     {
1659     struct pte *pe = &ptes[i];
1660     struct partition *p = pe->part_table;
1661     struct partition *q = pe->ext_pointer;
1662    
1663     /* Note that for the fifth partition (i == 4) we don't actually
1664     * decrement partitions.
1665     */
1666    
1667     if (warn_geometry())
1668     return; /* C/H/S not set */
1669     pe->changed = 1;
1670    
1671     if (LABEL_IS_SUN) {
1672     sun_delete_partition(i);
1673     return;
1674     }
1675     if (LABEL_IS_SGI) {
1676     sgi_delete_partition(i);
1677     return;
1678     }
1679    
1680     if (i < 4) {
1681     if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
1682 niro 816 g_partitions = 4;
1683 niro 532 ptes[ext_index].ext_pointer = NULL;
1684     extended_offset = 0;
1685     }
1686     clear_partition(p);
1687     return;
1688     }
1689    
1690     if (!q->sys_ind && i > 4) {
1691     /* the last one in the chain - just delete */
1692 niro 816 --g_partitions;
1693 niro 532 --i;
1694     clear_partition(ptes[i].ext_pointer);
1695     ptes[i].changed = 1;
1696     } else {
1697     /* not the last one - further ones will be moved down */
1698     if (i > 4) {
1699     /* delete this link in the chain */
1700     p = ptes[i-1].ext_pointer;
1701     *p = *q;
1702     set_start_sect(p, get_start_sect(q));
1703     set_nr_sects(p, get_nr_sects(q));
1704     ptes[i-1].changed = 1;
1705 niro 816 } else if (g_partitions > 5) { /* 5 will be moved to 4 */
1706 niro 532 /* the first logical in a longer chain */
1707     pe = &ptes[5];
1708    
1709     if (pe->part_table) /* prevent SEGFAULT */
1710     set_start_sect(pe->part_table,
1711 niro 984 get_partition_start(pe) -
1712     extended_offset);
1713 niro 532 pe->offset = extended_offset;
1714     pe->changed = 1;
1715     }
1716    
1717 niro 816 if (g_partitions > 5) {
1718     g_partitions--;
1719     while (i < g_partitions) {
1720 niro 532 ptes[i] = ptes[i+1];
1721     i++;
1722     }
1723     } else
1724     /* the only logical: clear only */
1725     clear_partition(ptes[i].part_table);
1726     }
1727     }
1728    
1729     static void
1730     change_sysid(void)
1731     {
1732     int i, sys, origsys;
1733     struct partition *p;
1734    
1735     /* If sgi_label then don't use get_existing_partition,
1736     let the user select a partition, since get_existing_partition()
1737     only works for Linux like partition tables. */
1738     if (!LABEL_IS_SGI) {
1739 niro 816 i = get_existing_partition(0, g_partitions);
1740 niro 532 } else {
1741 niro 816 i = get_partition(0, g_partitions);
1742 niro 532 }
1743     if (i == -1)
1744     return;
1745     p = ptes[i].part_table;
1746     origsys = sys = get_sysid(i);
1747    
1748     /* if changing types T to 0 is allowed, then
1749     the reverse change must be allowed, too */
1750     if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
1751 niro 984 printf("Partition %u does not exist yet!\n", i + 1);
1752 niro 532 return;
1753     }
1754     while (1) {
1755 niro 816 sys = read_hex(get_sys_types());
1756 niro 532
1757     if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
1758 niro 816 printf("Type 0 means free space to many systems\n"
1759 niro 532 "(but not to Linux). Having partitions of\n"
1760 niro 816 "type 0 is probably unwise.\n");
1761 niro 532 /* break; */
1762     }
1763    
1764     if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
1765     if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
1766 niro 816 printf("You cannot change a partition into"
1767     " an extended one or vice versa\n");
1768 niro 532 break;
1769     }
1770     }
1771    
1772     if (sys < 256) {
1773 niro 816 #if ENABLE_FEATURE_SUN_LABEL
1774 niro 532 if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
1775 niro 816 printf("Consider leaving partition 3 "
1776 niro 532 "as Whole disk (5),\n"
1777     "as SunOS/Solaris expects it and "
1778 niro 816 "even Linux likes it\n\n");
1779     #endif
1780     #if ENABLE_FEATURE_SGI_LABEL
1781 niro 532 if (LABEL_IS_SGI &&
1782     (
1783     (i == 10 && sys != SGI_ENTIRE_DISK) ||
1784     (i == 8 && sys != 0)
1785     )
1786 niro 816 ) {
1787     printf("Consider leaving partition 9 "
1788 niro 532 "as volume header (0),\nand "
1789     "partition 11 as entire volume (6)"
1790 niro 816 "as IRIX expects it\n\n");
1791 niro 532 }
1792 niro 816 #endif
1793 niro 532 if (sys == origsys)
1794     break;
1795     if (LABEL_IS_SUN) {
1796     sun_change_sysid(i, sys);
1797     } else if (LABEL_IS_SGI) {
1798     sgi_change_sysid(i, sys);
1799     } else
1800     p->sys_ind = sys;
1801    
1802 niro 984 printf("Changed system type of partition %u "
1803 niro 816 "to %x (%s)\n", i + 1, sys,
1804 niro 532 partition_type(sys));
1805     ptes[i].changed = 1;
1806 niro 816 //if (is_dos_partition(origsys) || is_dos_partition(sys))
1807     // dos_changed = 1;
1808 niro 532 break;
1809     }
1810     }
1811     }
1812     #endif /* FEATURE_FDISK_WRITABLE */
1813    
1814    
1815     /* check_consistency() and linear2chs() added Sat Mar 6 12:28:16 1993,
1816     * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1817     * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1818     * Lubkin Oct. 1991). */
1819    
1820     static void
1821     linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
1822     {
1823 niro 816 int spc = g_heads * g_sectors;
1824 niro 532
1825     *c = ls / spc;
1826     ls = ls % spc;
1827 niro 816 *h = ls / g_sectors;
1828     *s = ls % g_sectors + 1; /* sectors count from 1 */
1829 niro 532 }
1830    
1831     static void
1832     check_consistency(const struct partition *p, int partition)
1833     {
1834     unsigned pbc, pbh, pbs; /* physical beginning c, h, s */
1835     unsigned pec, peh, pes; /* physical ending c, h, s */
1836     unsigned lbc, lbh, lbs; /* logical beginning c, h, s */
1837     unsigned lec, leh, les; /* logical ending c, h, s */
1838    
1839 niro 816 if (!g_heads || !g_sectors || (partition >= 4))
1840 niro 532 return; /* do not check extended partitions */
1841    
1842     /* physical beginning c, h, s */
1843     pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
1844     pbh = p->head;
1845     pbs = p->sector & 0x3f;
1846    
1847     /* physical ending c, h, s */
1848     pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
1849     peh = p->end_head;
1850     pes = p->end_sector & 0x3f;
1851    
1852     /* compute logical beginning (c, h, s) */
1853     linear2chs(get_start_sect(p), &lbc, &lbh, &lbs);
1854    
1855     /* compute logical ending (c, h, s) */
1856     linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
1857    
1858     /* Same physical / logical beginning? */
1859 niro 816 if (g_cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
1860 niro 984 printf("Partition %u has different physical/logical "
1861 niro 816 "beginnings (non-Linux?):\n", partition + 1);
1862 niro 984 printf(" phys=(%u, %u, %u) ", pbc, pbh, pbs);
1863     printf("logical=(%u, %u, %u)\n", lbc, lbh, lbs);
1864 niro 532 }
1865    
1866     /* Same physical / logical ending? */
1867 niro 816 if (g_cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
1868 niro 984 printf("Partition %u has different physical/logical "
1869 niro 816 "endings:\n", partition + 1);
1870 niro 984 printf(" phys=(%u, %u, %u) ", pec, peh, pes);
1871     printf("logical=(%u, %u, %u)\n", lec, leh, les);
1872 niro 532 }
1873    
1874     /* Ending on cylinder boundary? */
1875 niro 816 if (peh != (g_heads - 1) || pes != g_sectors) {
1876 niro 984 printf("Partition %u does not end on cylinder boundary\n",
1877 niro 532 partition + 1);
1878     }
1879     }
1880    
1881     static void
1882     list_disk_geometry(void)
1883     {
1884 niro 984 ullong bytes = ((ullong)total_number_of_sectors << 9);
1885     long megabytes = bytes / 1000000;
1886 niro 532
1887     if (megabytes < 10000)
1888 niro 984 printf("\nDisk %s: %lu MB, %llu bytes\n",
1889     disk_device, megabytes, bytes);
1890 niro 532 else
1891 niro 984 printf("\nDisk %s: %lu.%lu GB, %llu bytes\n",
1892     disk_device, megabytes/1000, (megabytes/100)%10, bytes);
1893     printf("%u heads, %u sectors/track, %u cylinders",
1894 niro 816 g_heads, g_sectors, g_cylinders);
1895 niro 532 if (units_per_sector == 1)
1896 niro 984 printf(", total %"SECT_FMT"u sectors",
1897     total_number_of_sectors / (sector_size/512));
1898     printf("\nUnits = %s of %u * %u = %u bytes\n\n",
1899     str_units(PLURAL),
1900     units_per_sector, sector_size, units_per_sector * sector_size);
1901 niro 532 }
1902    
1903     /*
1904     * Check whether partition entries are ordered by their starting positions.
1905     * Return 0 if OK. Return i if partition i should have been earlier.
1906     * Two separate checks: primary and logical partitions.
1907     */
1908     static int
1909     wrong_p_order(int *prev)
1910     {
1911     const struct pte *pe;
1912     const struct partition *p;
1913 niro 984 sector_t last_p_start_pos = 0, p_start_pos;
1914     unsigned i, last_i = 0;
1915 niro 532
1916 niro 816 for (i = 0; i < g_partitions; i++) {
1917 niro 532 if (i == 4) {
1918     last_i = 4;
1919     last_p_start_pos = 0;
1920     }
1921     pe = &ptes[i];
1922 niro 816 p = pe->part_table;
1923     if (p->sys_ind) {
1924 niro 532 p_start_pos = get_partition_start(pe);
1925    
1926     if (last_p_start_pos > p_start_pos) {
1927     if (prev)
1928     *prev = last_i;
1929     return i;
1930     }
1931    
1932     last_p_start_pos = p_start_pos;
1933     last_i = i;
1934     }
1935     }
1936     return 0;
1937     }
1938    
1939     #if ENABLE_FEATURE_FDISK_ADVANCED
1940     /*
1941     * Fix the chain of logicals.
1942     * extended_offset is unchanged, the set of sectors used is unchanged
1943     * The chain is sorted so that sectors increase, and so that
1944     * starting sectors increase.
1945     *
1946     * After this it may still be that cfdisk doesnt like the table.
1947     * (This is because cfdisk considers expanded parts, from link to
1948     * end of partition, and these may still overlap.)
1949     * Now
1950     * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
1951     * may help.
1952     */
1953     static void
1954     fix_chain_of_logicals(void)
1955     {
1956     int j, oj, ojj, sj, sjj;
1957     struct partition *pj,*pjj,tmp;
1958    
1959     /* Stage 1: sort sectors but leave sector of part 4 */
1960     /* (Its sector is the global extended_offset.) */
1961     stage1:
1962 niro 816 for (j = 5; j < g_partitions - 1; j++) {
1963 niro 532 oj = ptes[j].offset;
1964     ojj = ptes[j+1].offset;
1965     if (oj > ojj) {
1966     ptes[j].offset = ojj;
1967     ptes[j+1].offset = oj;
1968     pj = ptes[j].part_table;
1969     set_start_sect(pj, get_start_sect(pj)+oj-ojj);
1970     pjj = ptes[j+1].part_table;
1971     set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
1972     set_start_sect(ptes[j-1].ext_pointer,
1973     ojj-extended_offset);
1974     set_start_sect(ptes[j].ext_pointer,
1975     oj-extended_offset);
1976     goto stage1;
1977     }
1978     }
1979    
1980     /* Stage 2: sort starting sectors */
1981     stage2:
1982 niro 816 for (j = 4; j < g_partitions - 1; j++) {
1983 niro 532 pj = ptes[j].part_table;
1984     pjj = ptes[j+1].part_table;
1985     sj = get_start_sect(pj);
1986     sjj = get_start_sect(pjj);
1987     oj = ptes[j].offset;
1988     ojj = ptes[j+1].offset;
1989     if (oj+sj > ojj+sjj) {
1990     tmp = *pj;
1991     *pj = *pjj;
1992     *pjj = tmp;
1993     set_start_sect(pj, ojj+sjj-oj);
1994     set_start_sect(pjj, oj+sj-ojj);
1995     goto stage2;
1996     }
1997     }
1998    
1999     /* Probably something was changed */
2000 niro 816 for (j = 4; j < g_partitions; j++)
2001 niro 532 ptes[j].changed = 1;
2002     }
2003    
2004    
2005     static void
2006     fix_partition_table_order(void)
2007     {
2008     struct pte *pei, *pek;
2009     int i,k;
2010    
2011     if (!wrong_p_order(NULL)) {
2012 niro 816 printf("Ordering is already correct\n\n");
2013 niro 532 return;
2014     }
2015    
2016     while ((i = wrong_p_order(&k)) != 0 && i < 4) {
2017     /* partition i should have come earlier, move it */
2018     /* We have to move data in the MBR */
2019     struct partition *pi, *pk, *pe, pbuf;
2020     pei = &ptes[i];
2021     pek = &ptes[k];
2022    
2023     pe = pei->ext_pointer;
2024     pei->ext_pointer = pek->ext_pointer;
2025     pek->ext_pointer = pe;
2026    
2027     pi = pei->part_table;
2028     pk = pek->part_table;
2029    
2030     memmove(&pbuf, pi, sizeof(struct partition));
2031     memmove(pi, pk, sizeof(struct partition));
2032     memmove(pk, &pbuf, sizeof(struct partition));
2033    
2034     pei->changed = pek->changed = 1;
2035     }
2036    
2037     if (i)
2038     fix_chain_of_logicals();
2039    
2040     printf("Done.\n");
2041    
2042     }
2043     #endif
2044    
2045     static void
2046     list_table(int xtra)
2047     {
2048     const struct partition *p;
2049     int i, w;
2050    
2051     if (LABEL_IS_SUN) {
2052     sun_list_table(xtra);
2053     return;
2054     }
2055     if (LABEL_IS_SUN) {
2056     sgi_list_table(xtra);
2057     return;
2058     }
2059    
2060     list_disk_geometry();
2061    
2062     if (LABEL_IS_OSF) {
2063     xbsd_print_disklabel(xtra);
2064     return;
2065     }
2066    
2067     /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
2068     but if the device name ends in a digit, say /dev/foo1,
2069     then the partition is called /dev/foo1p3. */
2070     w = strlen(disk_device);
2071     if (w && isdigit(disk_device[w-1]))
2072     w++;
2073     if (w < 5)
2074     w = 5;
2075    
2076 niro 816 // 1 12345678901 12345678901 12345678901 12
2077     printf("%*s Boot Start End Blocks Id System\n",
2078     w+1, "Device");
2079 niro 532
2080 niro 816 for (i = 0; i < g_partitions; i++) {
2081 niro 532 const struct pte *pe = &ptes[i];
2082 niro 984 sector_t psects;
2083     sector_t pblocks;
2084 niro 532 unsigned podd;
2085    
2086     p = pe->part_table;
2087     if (!p || is_cleared_partition(p))
2088     continue;
2089    
2090     psects = get_nr_sects(p);
2091     pblocks = psects;
2092     podd = 0;
2093    
2094     if (sector_size < 1024) {
2095     pblocks /= (1024 / sector_size);
2096     podd = psects % (1024 / sector_size);
2097     }
2098     if (sector_size > 1024)
2099     pblocks *= (sector_size / 1024);
2100    
2101 niro 984 printf("%s %c %11"SECT_FMT"u %11"SECT_FMT"u %11"SECT_FMT"u%c %2x %s\n",
2102 niro 532 partname(disk_device, i+1, w+2),
2103     !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
2104     ? '*' : '?',
2105 niro 984 cround(get_partition_start(pe)), /* start */
2106     cround(get_partition_start(pe) + psects /* end */
2107 niro 532 - (psects ? 1 : 0)),
2108 niro 984 pblocks, podd ? '+' : ' ', /* odd flag on end */
2109 niro 532 p->sys_ind, /* type id */
2110     partition_type(p->sys_ind)); /* type name */
2111    
2112     check_consistency(p, i);
2113     }
2114    
2115     /* Is partition table in disk order? It need not be, but... */
2116 niro 984 /* partition table entries are not checked for correct order
2117     * if this is a sgi, sun or aix labeled disk... */
2118 niro 532 if (LABEL_IS_DOS && wrong_p_order(NULL)) {
2119     /* FIXME */
2120 niro 816 printf("\nPartition table entries are not in disk order\n");
2121 niro 532 }
2122     }
2123    
2124     #if ENABLE_FEATURE_FDISK_ADVANCED
2125     static void
2126     x_list_table(int extend)
2127     {
2128     const struct pte *pe;
2129     const struct partition *p;
2130     int i;
2131    
2132 niro 984 printf("\nDisk %s: %u heads, %u sectors, %u cylinders\n\n",
2133 niro 816 disk_device, g_heads, g_sectors, g_cylinders);
2134     printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n");
2135     for (i = 0; i < g_partitions; i++) {
2136 niro 532 pe = &ptes[i];
2137     p = (extend ? pe->ext_pointer : pe->part_table);
2138     if (p != NULL) {
2139 niro 984 printf("%2u %02x%4u%4u%5u%4u%4u%5u%11"SECT_FMT"u%11"SECT_FMT"u %02x\n",
2140 niro 532 i + 1, p->boot_ind, p->head,
2141     sector(p->sector),
2142     cylinder(p->sector, p->cyl), p->end_head,
2143     sector(p->end_sector),
2144     cylinder(p->end_sector, p->end_cyl),
2145 niro 984 get_start_sect(p), get_nr_sects(p),
2146     p->sys_ind);
2147 niro 532 if (p->sys_ind)
2148     check_consistency(p, i);
2149     }
2150     }
2151     }
2152     #endif
2153    
2154     #if ENABLE_FEATURE_FDISK_WRITABLE
2155     static void
2156 niro 984 fill_bounds(sector_t *first, sector_t *last)
2157 niro 532 {
2158 niro 984 unsigned i;
2159 niro 532 const struct pte *pe = &ptes[0];
2160     const struct partition *p;
2161    
2162 niro 816 for (i = 0; i < g_partitions; pe++,i++) {
2163 niro 532 p = pe->part_table;
2164     if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
2165     first[i] = 0xffffffff;
2166     last[i] = 0;
2167     } else {
2168     first[i] = get_partition_start(pe);
2169     last[i] = first[i] + get_nr_sects(p) - 1;
2170     }
2171     }
2172     }
2173    
2174     static void
2175 niro 984 check(int n, unsigned h, unsigned s, unsigned c, sector_t start)
2176 niro 532 {
2177 niro 984 sector_t total, real_s, real_c;
2178 niro 532
2179     real_s = sector(s) - 1;
2180     real_c = cylinder(s, c);
2181 niro 816 total = (real_c * g_sectors + real_s) * g_heads + h;
2182 niro 532 if (!total)
2183 niro 984 printf("Partition %u contains sector 0\n", n);
2184 niro 816 if (h >= g_heads)
2185 niro 984 printf("Partition %u: head %u greater than maximum %u\n",
2186 niro 816 n, h + 1, g_heads);
2187     if (real_s >= g_sectors)
2188 niro 984 printf("Partition %u: sector %u greater than "
2189     "maximum %u\n", n, s, g_sectors);
2190 niro 816 if (real_c >= g_cylinders)
2191 niro 984 printf("Partition %u: cylinder %"SECT_FMT"u greater than "
2192     "maximum %u\n", n, real_c + 1, g_cylinders);
2193 niro 816 if (g_cylinders <= 1024 && start != total)
2194 niro 984 printf("Partition %u: previous sectors %"SECT_FMT"u disagrees with "
2195     "total %"SECT_FMT"u\n", n, start, total);
2196 niro 532 }
2197    
2198     static void
2199     verify(void)
2200     {
2201     int i, j;
2202 niro 984 sector_t total = 1;
2203     sector_t first[g_partitions], last[g_partitions];
2204 niro 532 struct partition *p;
2205    
2206     if (warn_geometry())
2207     return;
2208    
2209     if (LABEL_IS_SUN) {
2210     verify_sun();
2211     return;
2212     }
2213     if (LABEL_IS_SGI) {
2214     verify_sgi(1);
2215     return;
2216     }
2217    
2218     fill_bounds(first, last);
2219 niro 816 for (i = 0; i < g_partitions; i++) {
2220 niro 532 struct pte *pe = &ptes[i];
2221    
2222     p = pe->part_table;
2223     if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
2224     check_consistency(p, i);
2225     if (get_partition_start(pe) < first[i])
2226 niro 816 printf("Warning: bad start-of-data in "
2227 niro 984 "partition %u\n", i + 1);
2228 niro 532 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
2229     last[i]);
2230     total += last[i] + 1 - first[i];
2231 niro 816 for (j = 0; j < i; j++) {
2232     if ((first[i] >= first[j] && first[i] <= last[j])
2233     || ((last[i] <= last[j] && last[i] >= first[j]))) {
2234 niro 984 printf("Warning: partition %u overlaps "
2235     "partition %u\n", j + 1, i + 1);
2236 niro 816 total += first[i] >= first[j] ?
2237     first[i] : first[j];
2238     total -= last[i] <= last[j] ?
2239     last[i] : last[j];
2240     }
2241 niro 532 }
2242     }
2243     }
2244    
2245     if (extended_offset) {
2246     struct pte *pex = &ptes[ext_index];
2247 niro 984 sector_t e_last = get_start_sect(pex->part_table) +
2248 niro 532 get_nr_sects(pex->part_table) - 1;
2249    
2250 niro 816 for (i = 4; i < g_partitions; i++) {
2251 niro 532 total++;
2252     p = ptes[i].part_table;
2253     if (!p->sys_ind) {
2254 niro 816 if (i != 4 || i + 1 < g_partitions)
2255 niro 984 printf("Warning: partition %u "
2256 niro 816 "is empty\n", i + 1);
2257     } else if (first[i] < extended_offset || last[i] > e_last) {
2258 niro 984 printf("Logical partition %u not entirely in "
2259     "partition %u\n", i + 1, ext_index + 1);
2260 niro 532 }
2261     }
2262     }
2263    
2264 niro 816 if (total > g_heads * g_sectors * g_cylinders)
2265 niro 984 printf("Total allocated sectors %u greater than the maximum "
2266     "%u\n", total, g_heads * g_sectors * g_cylinders);
2267 niro 816 else {
2268     total = g_heads * g_sectors * g_cylinders - total;
2269     if (total != 0)
2270 niro 984 printf("%"SECT_FMT"u unallocated sectors\n", total);
2271 niro 816 }
2272 niro 532 }
2273    
2274     static void
2275     add_partition(int n, int sys)
2276     {
2277     char mesg[256]; /* 48 does not suffice in Japanese */
2278     int i, num_read = 0;
2279     struct partition *p = ptes[n].part_table;
2280     struct partition *q = ptes[ext_index].part_table;
2281 niro 984 sector_t limit, temp;
2282     sector_t start, stop = 0;
2283     sector_t first[g_partitions], last[g_partitions];
2284 niro 532
2285     if (p && p->sys_ind) {
2286 niro 816 printf(msg_part_already_defined, n + 1);
2287 niro 532 return;
2288     }
2289     fill_bounds(first, last);
2290     if (n < 4) {
2291     start = sector_offset;
2292     if (display_in_cyl_units || !total_number_of_sectors)
2293 niro 984 limit = (sector_t) g_heads * g_sectors * g_cylinders - 1;
2294 niro 532 else
2295 niro 816 limit = total_number_of_sectors - 1;
2296 niro 532 if (extended_offset) {
2297     first[ext_index] = extended_offset;
2298     last[ext_index] = get_start_sect(q) +
2299     get_nr_sects(q) - 1;
2300     }
2301     } else {
2302     start = extended_offset + sector_offset;
2303     limit = get_start_sect(q) + get_nr_sects(q) - 1;
2304     }
2305     if (display_in_cyl_units)
2306 niro 816 for (i = 0; i < g_partitions; i++)
2307 niro 532 first[i] = (cround(first[i]) - 1) * units_per_sector;
2308    
2309 niro 816 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
2310 niro 532 do {
2311     temp = start;
2312 niro 816 for (i = 0; i < g_partitions; i++) {
2313 niro 532 int lastplusoff;
2314    
2315     if (start == ptes[i].offset)
2316     start += sector_offset;
2317     lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
2318     if (start >= first[i] && start <= lastplusoff)
2319     start = lastplusoff + 1;
2320     }
2321     if (start > limit)
2322     break;
2323     if (start >= temp+units_per_sector && num_read) {
2324 niro 984 printf("Sector %"SECT_FMT"u is already allocated\n", temp);
2325 niro 532 temp = start;
2326     num_read = 0;
2327     }
2328     if (!num_read && start == temp) {
2329 niro 984 sector_t saved_start;
2330 niro 532
2331     saved_start = start;
2332     start = read_int(cround(saved_start), cround(saved_start), cround(limit),
2333     0, mesg);
2334     if (display_in_cyl_units) {
2335     start = (start - 1) * units_per_sector;
2336 niro 984 if (start < saved_start)
2337     start = saved_start;
2338 niro 532 }
2339     num_read = 1;
2340     }
2341     } while (start != temp || !num_read);
2342     if (n > 4) { /* NOT for fifth partition */
2343     struct pte *pe = &ptes[n];
2344    
2345     pe->offset = start - sector_offset;
2346     if (pe->offset == extended_offset) { /* must be corrected */
2347     pe->offset++;
2348     if (sector_offset == 1)
2349     start++;
2350     }
2351     }
2352    
2353 niro 816 for (i = 0; i < g_partitions; i++) {
2354 niro 532 struct pte *pe = &ptes[i];
2355    
2356     if (start < pe->offset && limit >= pe->offset)
2357     limit = pe->offset - 1;
2358     if (start < first[i] && limit >= first[i])
2359     limit = first[i] - 1;
2360     }
2361     if (start > limit) {
2362 niro 816 printf("No free sectors available\n");
2363 niro 532 if (n > 4)
2364 niro 816 g_partitions--;
2365 niro 532 return;
2366     }
2367     if (cround(start) == cround(limit)) {
2368     stop = limit;
2369     } else {
2370     snprintf(mesg, sizeof(mesg),
2371 niro 816 "Last %s or +size or +sizeM or +sizeK",
2372 niro 532 str_units(SINGULAR));
2373     stop = read_int(cround(start), cround(limit), cround(limit),
2374     cround(start), mesg);
2375     if (display_in_cyl_units) {
2376     stop = stop * units_per_sector - 1;
2377     if (stop >limit)
2378     stop = limit;
2379     }
2380     }
2381    
2382     set_partition(n, 0, start, stop, sys);
2383     if (n > 4)
2384     set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
2385    
2386     if (IS_EXTENDED(sys)) {
2387     struct pte *pe4 = &ptes[4];
2388     struct pte *pen = &ptes[n];
2389    
2390     ext_index = n;
2391     pen->ext_pointer = p;
2392     pe4->offset = extended_offset = start;
2393     pe4->sectorbuffer = xzalloc(sector_size);
2394     pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2395     pe4->ext_pointer = pe4->part_table + 1;
2396     pe4->changed = 1;
2397 niro 816 g_partitions = 5;
2398 niro 532 }
2399     }
2400    
2401     static void
2402     add_logical(void)
2403     {
2404 niro 816 if (g_partitions > 5 || ptes[4].part_table->sys_ind) {
2405     struct pte *pe = &ptes[g_partitions];
2406 niro 532
2407     pe->sectorbuffer = xzalloc(sector_size);
2408     pe->part_table = pt_offset(pe->sectorbuffer, 0);
2409     pe->ext_pointer = pe->part_table + 1;
2410     pe->offset = 0;
2411     pe->changed = 1;
2412 niro 816 g_partitions++;
2413 niro 532 }
2414 niro 816 add_partition(g_partitions - 1, LINUX_NATIVE);
2415 niro 532 }
2416    
2417     static void
2418     new_partition(void)
2419     {
2420     int i, free_primary = 0;
2421    
2422     if (warn_geometry())
2423     return;
2424    
2425     if (LABEL_IS_SUN) {
2426 niro 816 add_sun_partition(get_partition(0, g_partitions), LINUX_NATIVE);
2427 niro 532 return;
2428     }
2429     if (LABEL_IS_SGI) {
2430 niro 816 sgi_add_partition(get_partition(0, g_partitions), LINUX_NATIVE);
2431 niro 532 return;
2432     }
2433     if (LABEL_IS_AIX) {
2434 niro 816 printf("Sorry - this fdisk cannot handle AIX disk labels.\n"
2435     "If you want to add DOS-type partitions, create a new empty DOS partition\n"
2436     "table first (use 'o'). This will destroy the present disk contents.\n");
2437 niro 532 return;
2438     }
2439    
2440     for (i = 0; i < 4; i++)
2441     free_primary += !ptes[i].part_table->sys_ind;
2442    
2443 niro 816 if (!free_primary && g_partitions >= MAXIMUM_PARTS) {
2444     printf("The maximum number of partitions has been created\n");
2445 niro 532 return;
2446     }
2447    
2448     if (!free_primary) {
2449     if (extended_offset)
2450     add_logical();
2451     else
2452 niro 816 printf("You must delete some partition and add "
2453     "an extended partition first\n");
2454 niro 532 } else {
2455 niro 816 char c, line[80];
2456     snprintf(line, sizeof(line),
2457     "Command action\n"
2458     " %s\n"
2459     " p primary partition (1-4)\n",
2460     (extended_offset ?
2461     "l logical (5 or over)" : "e extended"));
2462 niro 532 while (1) {
2463     c = read_nonempty(line);
2464     if (c == 'p' || c == 'P') {
2465     i = get_nonexisting_partition(0, 4);
2466     if (i >= 0)
2467     add_partition(i, LINUX_NATIVE);
2468     return;
2469     }
2470 niro 816 if (c == 'l' && extended_offset) {
2471 niro 532 add_logical();
2472     return;
2473     }
2474 niro 816 if (c == 'e' && !extended_offset) {
2475 niro 532 i = get_nonexisting_partition(0, 4);
2476     if (i >= 0)
2477     add_partition(i, EXTENDED);
2478     return;
2479     }
2480 niro 816 printf("Invalid partition number "
2481     "for type '%c'\n", c);
2482 niro 532 }
2483     }
2484     }
2485    
2486     static void
2487     write_table(void)
2488     {
2489     int i;
2490    
2491     if (LABEL_IS_DOS) {
2492     for (i = 0; i < 3; i++)
2493     if (ptes[i].changed)
2494     ptes[3].changed = 1;
2495 niro 816 for (i = 3; i < g_partitions; i++) {
2496 niro 532 struct pte *pe = &ptes[i];
2497    
2498     if (pe->changed) {
2499     write_part_table_flag(pe->sectorbuffer);
2500     write_sector(pe->offset, pe->sectorbuffer);
2501     }
2502     }
2503     }
2504     else if (LABEL_IS_SGI) {
2505     /* no test on change? the printf below might be mistaken */
2506     sgi_write_table();
2507     }
2508     else if (LABEL_IS_SUN) {
2509     int needw = 0;
2510    
2511     for (i = 0; i < 8; i++)
2512     if (ptes[i].changed)
2513     needw = 1;
2514     if (needw)
2515     sun_write_table();
2516     }
2517    
2518 niro 816 printf("The partition table has been altered!\n\n");
2519 niro 532 reread_partition_table(1);
2520     }
2521    
2522     static void
2523     reread_partition_table(int leave)
2524     {
2525     int i;
2526    
2527 niro 816 printf("Calling ioctl() to re-read partition table\n");
2528 niro 532 sync();
2529 niro 816 /* sleep(2); Huh? */
2530     i = ioctl_or_perror(dev_fd, BLKRRPART, NULL,
2531     "WARNING: rereading partition table "
2532 niro 532 "failed, kernel still uses old table");
2533     #if 0
2534     if (dos_changed)
2535     printf(
2536 niro 816 "\nWARNING: If you have created or modified any DOS 6.x\n"
2537 niro 532 "partitions, please see the fdisk manual page for additional\n"
2538 niro 816 "information\n");
2539 niro 532 #endif
2540    
2541     if (leave) {
2542     if (ENABLE_FEATURE_CLEAN_UP)
2543 niro 816 close_dev_fd();
2544 niro 532 exit(i != 0);
2545     }
2546     }
2547     #endif /* FEATURE_FDISK_WRITABLE */
2548    
2549     #if ENABLE_FEATURE_FDISK_ADVANCED
2550     #define MAX_PER_LINE 16
2551     static void
2552     print_buffer(char *pbuffer)
2553     {
2554     int i,l;
2555    
2556     for (i = 0, l = 0; i < sector_size; i++, l++) {
2557     if (l == 0)
2558     printf("0x%03X:", i);
2559     printf(" %02X", (unsigned char) pbuffer[i]);
2560     if (l == MAX_PER_LINE - 1) {
2561 niro 816 bb_putchar('\n');
2562 niro 532 l = -1;
2563     }
2564     }
2565     if (l > 0)
2566 niro 816 bb_putchar('\n');
2567     bb_putchar('\n');
2568 niro 532 }
2569    
2570     static void
2571     print_raw(void)
2572     {
2573     int i;
2574    
2575 niro 816 printf("Device: %s\n", disk_device);
2576 niro 532 if (LABEL_IS_SGI || LABEL_IS_SUN)
2577     print_buffer(MBRbuffer);
2578     else {
2579 niro 816 for (i = 3; i < g_partitions; i++)
2580 niro 532 print_buffer(ptes[i].sectorbuffer);
2581     }
2582     }
2583    
2584     static void
2585 niro 984 move_begin(unsigned i)
2586 niro 532 {
2587     struct pte *pe = &ptes[i];
2588     struct partition *p = pe->part_table;
2589 niro 984 sector_t new, first;
2590 niro 532
2591     if (warn_geometry())
2592     return;
2593     if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
2594 niro 984 printf("Partition %u has no data area\n", i + 1);
2595 niro 532 return;
2596     }
2597     first = get_partition_start(pe);
2598     new = read_int(first, first, first + get_nr_sects(p) - 1, first,
2599 niro 816 "New beginning of data") - pe->offset;
2600 niro 532
2601     if (new != get_nr_sects(p)) {
2602     first = get_nr_sects(p) + get_start_sect(p) - new;
2603     set_nr_sects(p, first);
2604     set_start_sect(p, new);
2605     pe->changed = 1;
2606     }
2607     }
2608    
2609     static void
2610     xselect(void)
2611     {
2612     char c;
2613    
2614     while (1) {
2615 niro 816 bb_putchar('\n');
2616     c = tolower(read_nonempty("Expert command (m for help): "));
2617 niro 532 switch (c) {
2618     case 'a':
2619     if (LABEL_IS_SUN)
2620     sun_set_alt_cyl();
2621     break;
2622     case 'b':
2623     if (LABEL_IS_DOS)
2624 niro 816 move_begin(get_partition(0, g_partitions));
2625 niro 532 break;
2626     case 'c':
2627 niro 816 user_cylinders = g_cylinders =
2628     read_int(1, g_cylinders, 1048576, 0,
2629     "Number of cylinders");
2630 niro 532 if (LABEL_IS_SUN)
2631 niro 816 sun_set_ncyl(g_cylinders);
2632 niro 532 if (LABEL_IS_DOS)
2633     warn_cylinders();
2634     break;
2635     case 'd':
2636     print_raw();
2637     break;
2638     case 'e':
2639     if (LABEL_IS_SGI)
2640     sgi_set_xcyl();
2641     else if (LABEL_IS_SUN)
2642     sun_set_xcyl();
2643     else if (LABEL_IS_DOS)
2644     x_list_table(1);
2645     break;
2646     case 'f':
2647     if (LABEL_IS_DOS)
2648     fix_partition_table_order();
2649     break;
2650     case 'g':
2651     #if ENABLE_FEATURE_SGI_LABEL
2652     create_sgilabel();
2653     #endif
2654     break;
2655     case 'h':
2656 niro 816 user_heads = g_heads = read_int(1, g_heads, 256, 0,
2657     "Number of heads");
2658 niro 532 update_units();
2659     break;
2660     case 'i':
2661     if (LABEL_IS_SUN)
2662     sun_set_ilfact();
2663     break;
2664     case 'o':
2665     if (LABEL_IS_SUN)
2666     sun_set_rspeed();
2667     break;
2668     case 'p':
2669     if (LABEL_IS_SUN)
2670     list_table(1);
2671     else
2672     x_list_table(0);
2673     break;
2674     case 'q':
2675 niro 816 if (ENABLE_FEATURE_CLEAN_UP)
2676     close_dev_fd();
2677     bb_putchar('\n');
2678     exit(EXIT_SUCCESS);
2679 niro 532 case 'r':
2680     return;
2681     case 's':
2682 niro 816 user_sectors = g_sectors = read_int(1, g_sectors, 63, 0,
2683     "Number of sectors");
2684 niro 532 if (dos_compatible_flag) {
2685 niro 816 sector_offset = g_sectors;
2686     printf("Warning: setting sector offset for DOS "
2687     "compatiblity\n");
2688 niro 532 }
2689     update_units();
2690     break;
2691     case 'v':
2692     verify();
2693     break;
2694     case 'w':
2695     write_table(); /* does not return */
2696     break;
2697     case 'y':
2698     if (LABEL_IS_SUN)
2699     sun_set_pcylcount();
2700     break;
2701     default:
2702     xmenu();
2703     }
2704     }
2705     }
2706     #endif /* ADVANCED mode */
2707    
2708     static int
2709     is_ide_cdrom_or_tape(const char *device)
2710     {
2711     FILE *procf;
2712     char buf[100];
2713     struct stat statbuf;
2714     int is_ide = 0;
2715    
2716     /* No device was given explicitly, and we are trying some
2717     likely things. But opening /dev/hdc may produce errors like
2718     "hdc: tray open or drive not ready"
2719     if it happens to be a CD-ROM drive. It even happens that
2720     the process hangs on the attempt to read a music CD.
2721     So try to be careful. This only works since 2.1.73. */
2722    
2723     if (strncmp("/dev/hd", device, 7))
2724     return 0;
2725    
2726     snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
2727 niro 816 procf = fopen_for_read(buf);
2728 niro 532 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2729     is_ide = (!strncmp(buf, "cdrom", 5) ||
2730     !strncmp(buf, "tape", 4));
2731     else
2732     /* Now when this proc file does not exist, skip the
2733     device when it is read-only. */
2734     if (stat(device, &statbuf) == 0)
2735     is_ide = ((statbuf.st_mode & 0222) == 0);
2736    
2737     if (procf)
2738     fclose(procf);
2739     return is_ide;
2740     }
2741    
2742    
2743     static void
2744 niro 816 open_list_and_close(const char *device, int user_specified)
2745 niro 532 {
2746     int gb;
2747    
2748     disk_device = device;
2749     if (setjmp(listingbuf))
2750     return;
2751     if (!user_specified)
2752     if (is_ide_cdrom_or_tape(device))
2753     return;
2754 niro 816
2755     /* Open disk_device, save file descriptor to dev_fd */
2756     errno = 0;
2757     gb = get_boot(TRY_ONLY);
2758     if (gb > 0) { /* I/O error */
2759     /* Ignore other errors, since we try IDE
2760     and SCSI hard disks which may not be
2761     installed on the system. */
2762     if (user_specified || errno == EACCES)
2763     bb_perror_msg("can't open '%s'", device);
2764     return;
2765     }
2766    
2767     if (gb < 0) { /* no DOS signature */
2768     list_disk_geometry();
2769     if (LABEL_IS_AIX)
2770     goto ret;
2771 niro 532 #if ENABLE_FEATURE_OSF_LABEL
2772 niro 816 if (bsd_trydev(device) < 0)
2773 niro 532 #endif
2774 niro 816 printf("Disk %s doesn't contain a valid "
2775     "partition table\n", device);
2776     } else {
2777     list_table(0);
2778 niro 532 #if ENABLE_FEATURE_FDISK_WRITABLE
2779 niro 816 if (!LABEL_IS_SUN && g_partitions > 4) {
2780     delete_partition(ext_index);
2781     }
2782 niro 532 #endif
2783     }
2784 niro 816 ret:
2785     close_dev_fd();
2786 niro 532 }
2787    
2788     /* for fdisk -l: try all things in /proc/partitions
2789     that look like a partition name (do not end in a digit) */
2790     static void
2791 niro 816 list_devs_in_proc_partititons(void)
2792 niro 532 {
2793     FILE *procpt;
2794     char line[100], ptname[100], devname[120], *s;
2795     int ma, mi, sz;
2796    
2797     procpt = fopen_or_warn("/proc/partitions", "r");
2798    
2799     while (fgets(line, sizeof(line), procpt)) {
2800 niro 984 if (sscanf(line, " %u %u %u %[^\n ]",
2801 niro 532 &ma, &mi, &sz, ptname) != 4)
2802     continue;
2803 niro 816 for (s = ptname; *s; s++)
2804     continue;
2805 niro 532 if (isdigit(s[-1]))
2806     continue;
2807     sprintf(devname, "/dev/%s", ptname);
2808 niro 816 open_list_and_close(devname, 0);
2809 niro 532 }
2810     #if ENABLE_FEATURE_CLEAN_UP
2811     fclose(procpt);
2812     #endif
2813     }
2814    
2815     #if ENABLE_FEATURE_FDISK_WRITABLE
2816     static void
2817     unknown_command(int c)
2818     {
2819 niro 816 printf("%c: unknown command\n", c);
2820 niro 532 }
2821     #endif
2822    
2823 niro 816 int fdisk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
2824 niro 984 int fdisk_main(int argc UNUSED_PARAM, char **argv)
2825 niro 532 {
2826     unsigned opt;
2827     /*
2828     * fdisk -v
2829     * fdisk -l [-b sectorsize] [-u] device ...
2830     * fdisk -s [partition] ...
2831     * fdisk [-b sectorsize] [-u] device
2832     *
2833     * Options -C, -H, -S set the geometry.
2834     */
2835 niro 816 INIT_G();
2836    
2837     close_dev_fd(); /* needed: fd 3 must not stay closed */
2838    
2839     opt_complementary = "b+:C+:H+:S+"; /* numeric params */
2840 niro 984 opt = getopt32(argv, "b:C:H:lS:u" IF_FEATURE_FDISK_BLKSIZE("s"),
2841 niro 816 &sector_size, &user_cylinders, &user_heads, &user_sectors);
2842 niro 532 argv += optind;
2843     if (opt & OPT_b) { // -b
2844     /* Ugly: this sector size is really per device,
2845     so cannot be combined with multiple disks,
2846     and the same goes for the C/H/S options.
2847     */
2848 niro 816 if (sector_size != 512 && sector_size != 1024
2849     && sector_size != 2048)
2850 niro 532 bb_show_usage();
2851     sector_offset = 2;
2852     user_set_sector_size = 1;
2853     }
2854 niro 816 if (user_heads <= 0 || user_heads >= 256)
2855     user_heads = 0;
2856     if (user_sectors <= 0 || user_sectors >= 64)
2857     user_sectors = 0;
2858     if (opt & OPT_u)
2859     display_in_cyl_units = 0; // -u
2860 niro 532
2861     #if ENABLE_FEATURE_FDISK_WRITABLE
2862     if (opt & OPT_l) {
2863     nowarn = 1;
2864     #endif
2865 niro 816 if (*argv) {
2866 niro 532 listing = 1;
2867 niro 816 do {
2868     open_list_and_close(*argv, 1);
2869     } while (*++argv);
2870 niro 532 } else {
2871 niro 816 /* we don't have device names, */
2872     /* use /proc/partitions instead */
2873     list_devs_in_proc_partititons();
2874 niro 532 }
2875     return 0;
2876     #if ENABLE_FEATURE_FDISK_WRITABLE
2877     }
2878     #endif
2879    
2880     #if ENABLE_FEATURE_FDISK_BLKSIZE
2881     if (opt & OPT_s) {
2882     int j;
2883    
2884     nowarn = 1;
2885 niro 984 if (!argv[0])
2886 niro 532 bb_show_usage();
2887 niro 984 for (j = 0; argv[j]; j++) {
2888 niro 816 unsigned long long size;
2889     fd = xopen(argv[j], O_RDONLY);
2890     size = bb_BLKGETSIZE_sectors(fd) / 2;
2891 niro 532 close(fd);
2892 niro 984 if (argv[1])
2893     printf("%llu\n", size);
2894 niro 532 else
2895 niro 984 printf("%s: %llu\n", argv[j], size);
2896 niro 532 }
2897     return 0;
2898     }
2899     #endif
2900    
2901     #if ENABLE_FEATURE_FDISK_WRITABLE
2902 niro 984 if (!argv[0] || argv[1])
2903 niro 532 bb_show_usage();
2904    
2905     disk_device = argv[0];
2906 niro 816 get_boot(OPEN_MAIN);
2907 niro 532
2908     if (LABEL_IS_OSF) {
2909     /* OSF label, and no DOS label */
2910 niro 816 printf("Detected an OSF/1 disklabel on %s, entering "
2911     "disklabel mode\n", disk_device);
2912 niro 532 bsd_select();
2913     /*Why do we do this? It seems to be counter-intuitive*/
2914 niro 816 current_label_type = LABEL_DOS;
2915 niro 532 /* If we return we may want to make an empty DOS label? */
2916     }
2917    
2918     while (1) {
2919     int c;
2920 niro 816 bb_putchar('\n');
2921     c = tolower(read_nonempty("Command (m for help): "));
2922 niro 532 switch (c) {
2923     case 'a':
2924     if (LABEL_IS_DOS)
2925 niro 816 toggle_active(get_partition(1, g_partitions));
2926 niro 532 else if (LABEL_IS_SUN)
2927 niro 816 toggle_sunflags(get_partition(1, g_partitions),
2928 niro 532 0x01);
2929     else if (LABEL_IS_SGI)
2930     sgi_set_bootpartition(
2931 niro 816 get_partition(1, g_partitions));
2932 niro 532 else
2933     unknown_command(c);
2934     break;
2935     case 'b':
2936     if (LABEL_IS_SGI) {
2937 niro 816 printf("\nThe current boot file is: %s\n",
2938 niro 532 sgi_get_bootfile());
2939 niro 816 if (read_maybe_empty("Please enter the name of the "
2940     "new boot file: ") == '\n')
2941     printf("Boot file unchanged\n");
2942 niro 532 else
2943     sgi_set_bootfile(line_ptr);
2944     }
2945     #if ENABLE_FEATURE_OSF_LABEL
2946     else
2947     bsd_select();
2948     #endif
2949     break;
2950     case 'c':
2951     if (LABEL_IS_DOS)
2952     toggle_dos_compatibility_flag();
2953     else if (LABEL_IS_SUN)
2954 niro 816 toggle_sunflags(get_partition(1, g_partitions),
2955 niro 532 0x10);
2956     else if (LABEL_IS_SGI)
2957     sgi_set_swappartition(
2958 niro 816 get_partition(1, g_partitions));
2959 niro 532 else
2960     unknown_command(c);
2961     break;
2962     case 'd':
2963     {
2964     int j;
2965     /* If sgi_label then don't use get_existing_partition,
2966     let the user select a partition, since
2967     get_existing_partition() only works for Linux-like
2968     partition tables */
2969     if (!LABEL_IS_SGI) {
2970 niro 816 j = get_existing_partition(1, g_partitions);
2971 niro 532 } else {
2972 niro 816 j = get_partition(1, g_partitions);
2973 niro 532 }
2974     if (j >= 0)
2975     delete_partition(j);
2976     }
2977     break;
2978     case 'i':
2979     if (LABEL_IS_SGI)
2980     create_sgiinfo();
2981     else
2982     unknown_command(c);
2983     case 'l':
2984     list_types(get_sys_types());
2985     break;
2986     case 'm':
2987     menu();
2988     break;
2989     case 'n':
2990     new_partition();
2991     break;
2992     case 'o':
2993     create_doslabel();
2994     break;
2995     case 'p':
2996     list_table(0);
2997     break;
2998     case 'q':
2999 niro 816 if (ENABLE_FEATURE_CLEAN_UP)
3000     close_dev_fd();
3001     bb_putchar('\n');
3002 niro 532 return 0;
3003     case 's':
3004     #if ENABLE_FEATURE_SUN_LABEL
3005     create_sunlabel();
3006     #endif
3007     break;
3008     case 't':
3009     change_sysid();
3010     break;
3011     case 'u':
3012     change_units();
3013     break;
3014     case 'v':
3015     verify();
3016     break;
3017     case 'w':
3018     write_table(); /* does not return */
3019     break;
3020     #if ENABLE_FEATURE_FDISK_ADVANCED
3021     case 'x':
3022     if (LABEL_IS_SGI) {
3023 niro 816 printf("\n\tSorry, no experts menu for SGI "
3024     "partition tables available\n\n");
3025 niro 532 } else
3026     xselect();
3027     break;
3028     #endif
3029     default:
3030     unknown_command(c);
3031     menu();
3032     }
3033     }
3034     return 0;
3035     #endif /* FEATURE_FDISK_WRITABLE */
3036     }