Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/util-linux/fdisk.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 815 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 7  Line 7 
7   * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.   * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
8   */   */
9    
10    #ifndef _LARGEFILE64_SOURCE
11    /* For lseek64 */
12    #define _LARGEFILE64_SOURCE
13    #endif
14  #include <assert.h>             /* assert */  #include <assert.h>             /* assert */
15  #include "busybox.h"  #include "libbb.h"
 #define _(x) x  
16    
17  /* Looks like someone forgot to add this to config system */  /* Looks like someone forgot to add this to config system */
18  #ifndef ENABLE_FEATURE_FDISK_BLKSIZE  #ifndef ENABLE_FEATURE_FDISK_BLKSIZE
# Line 17  Line 20 
20  # define USE_FEATURE_FDISK_BLKSIZE(a)  # define USE_FEATURE_FDISK_BLKSIZE(a)
21  #endif  #endif
22    
23  #define DEFAULT_SECTOR_SIZE     512  #define DEFAULT_SECTOR_SIZE      512
24  #define MAX_SECTOR_SIZE 2048  #define DEFAULT_SECTOR_SIZE_STR "512"
25  #define SECTOR_SIZE     512     /* still used in osf/sgi/sun code */  #define MAX_SECTOR_SIZE         2048
26  #define MAXIMUM_PARTS   60  #define SECTOR_SIZE              512 /* still used in osf/sgi/sun code */
27    #define MAXIMUM_PARTS             60
28  #define ACTIVE_FLAG     0x80  
29    #define ACTIVE_FLAG             0x80
30  #define EXTENDED        0x05  
31  #define WIN98_EXTENDED  0x0f  #define EXTENDED                0x05
32  #define LINUX_PARTITION 0x81  #define WIN98_EXTENDED          0x0f
33  #define LINUX_SWAP      0x82  #define LINUX_PARTITION         0x81
34  #define LINUX_NATIVE    0x83  #define LINUX_SWAP              0x82
35  #define LINUX_EXTENDED  0x85  #define LINUX_NATIVE            0x83
36  #define LINUX_LVM       0x8e  #define LINUX_EXTENDED          0x85
37  #define LINUX_RAID      0xfd  #define LINUX_LVM               0x8e
38    #define LINUX_RAID              0xfd
39  #define IS_EXTENDED(i) \  
40   ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)  
41    enum {
42     OPT_b = 1 << 0,
43     OPT_C = 1 << 1,
44     OPT_H = 1 << 2,
45     OPT_l = 1 << 3,
46     OPT_S = 1 << 4,
47     OPT_u = 1 << 5,
48     OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
49    };
50    
 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))  
51    
52  #define cround(n)       (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))  /* Used for sector numbers. Today's disk sizes make it necessary */
53  #define scround(x)      (((x)+units_per_sector-1)/units_per_sector)  typedef unsigned long long ullong;
54    
55  struct hd_geometry {  struct hd_geometry {
56   unsigned char heads;   unsigned char heads;
# Line 50  struct hd_geometry { Line 61  struct hd_geometry {
61    
62  #define HDIO_GETGEO     0x0301  /* get device geometry */  #define HDIO_GETGEO     0x0301  /* get device geometry */
63    
64  struct systypes {  static const char msg_building_new_label[] ALIGN1 =
65   const char *name;  "Building a new %s. Changes will remain in memory only,\n"
66  };  "until you decide to write them. After that the previous content\n"
67    "won't be recoverable.\n\n";
 static unsigned sector_size = DEFAULT_SECTOR_SIZE;  
 static unsigned user_set_sector_size;  
 static unsigned sector_offset = 1;  
   
 /*  
  * Raw disk label. For DOS-type partition tables the MBR,  
  * with descriptions of the primary partitions.  
  */  
 #if (MAX_SECTOR_SIZE) > (BUFSIZ+1)  
 static char MBRbuffer[MAX_SECTOR_SIZE];  
 #else  
 # define MBRbuffer bb_common_bufsiz1  
 #endif  
   
 #if ENABLE_FEATURE_OSF_LABEL  
 static int possibly_osf_label;  
 #endif  
   
 static unsigned heads, sectors, cylinders;  
 static void update_units(void);  
   
   
 /*  
  * return partition name - uses static storage unless buf is supplied  
  */  
 static const char *  
 partname(const char *dev, int pno, int lth)  
 {  
  static char buffer[80];  
  const char *p;  
  int w, wp;  
  int bufsiz;  
  char *bufp;  
   
  bufp = buffer;  
  bufsiz = sizeof(buffer);  
68    
69   w = strlen(dev);  static const char msg_part_already_defined[] ALIGN1 =
70   p = "";  "Partition %d is already defined, delete it before re-adding\n";
71    
  if (isdigit(dev[w-1]))  
  p = "p";  
   
  /* devfs kludge - note: fdisk partition names are not supposed  
    to equal kernel names, so there is no reason to do this */  
  if (strcmp(dev + w - 4, "disc") == 0) {  
  w -= 4;  
  p = "part";  
  }  
   
  wp = strlen(p);  
   
  if (lth) {  
  snprintf(bufp, bufsiz, "%*.*s%s%-2u",  
  lth-wp-2, w, dev, p, pno);  
  } else {  
  snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);  
  }  
  return bufp;  
 }  
72    
73  struct partition {  struct partition {
74   unsigned char boot_ind;         /* 0x80 - active */   unsigned char boot_ind;         /* 0x80 - active */
75   unsigned char head;             /* starting head */   unsigned char head;             /* starting head */
76   unsigned char sector;           /* starting sector */   unsigned char sector;           /* starting sector */
77   unsigned char cyl;              /* starting cylinder */   unsigned char cyl;              /* starting cylinder */
78   unsigned char sys_ind;          /* What partition type */   unsigned char sys_ind;          /* what partition type */
79   unsigned char end_head;         /* end head */   unsigned char end_head;         /* end head */
80   unsigned char end_sector;       /* end sector */   unsigned char end_sector;       /* end sector */
81   unsigned char end_cyl;          /* end cylinder */   unsigned char end_cyl;          /* end cylinder */
82   unsigned char start4[4];        /* starting sector counting from 0 */   unsigned char start4[4];        /* starting sector counting from 0 */
83   unsigned char size4[4];         /* nr of sectors in partition */   unsigned char size4[4];         /* nr of sectors in partition */
84  } ATTRIBUTE_PACKED;  } PACKED;
85    
86  enum failure {  static const char unable_to_open[] ALIGN1 = "can't open %s";
87   ioctl_error, unable_to_open, unable_to_read, unable_to_seek,  static const char unable_to_read[] ALIGN1 = "can't read from %s";
88   unable_to_write  static const char unable_to_seek[] ALIGN1 = "can't seek on %s";
 };  
89    
90  enum label_type {  enum label_type {
91   label_dos, label_sun, label_sgi, label_aix, label_osf   LABEL_DOS, LABEL_SUN, LABEL_SGI, LABEL_AIX, LABEL_OSF
92  };  };
93  #define LABEL_IS_DOS (label_dos == current_label_type)  
94    #define LABEL_IS_DOS (LABEL_DOS == current_label_type)
95    
96  #if ENABLE_FEATURE_SUN_LABEL  #if ENABLE_FEATURE_SUN_LABEL
97  #define LABEL_IS_SUN (label_sun == current_label_type)  #define LABEL_IS_SUN (LABEL_SUN == current_label_type)
98  #define STATIC_SUN static  #define STATIC_SUN static
99  #else  #else
100  #define LABEL_IS_SUN 0  #define LABEL_IS_SUN 0
# Line 147  enum label_type { Line 102  enum label_type {
102  #endif  #endif
103    
104  #if ENABLE_FEATURE_SGI_LABEL  #if ENABLE_FEATURE_SGI_LABEL
105  #define LABEL_IS_SGI (label_sgi == current_label_type)  #define LABEL_IS_SGI (LABEL_SGI == current_label_type)
106  #define STATIC_SGI static  #define STATIC_SGI static
107  #else  #else
108  #define LABEL_IS_SGI 0  #define LABEL_IS_SGI 0
# Line 155  enum label_type { Line 110  enum label_type {
110  #endif  #endif
111    
112  #if ENABLE_FEATURE_AIX_LABEL  #if ENABLE_FEATURE_AIX_LABEL
113  #define LABEL_IS_AIX (label_aix == current_label_type)  #define LABEL_IS_AIX (LABEL_AIX == current_label_type)
114  #define STATIC_AIX static  #define STATIC_AIX static
115  #else  #else
116  #define LABEL_IS_AIX 0  #define LABEL_IS_AIX 0
# Line 163  enum label_type { Line 118  enum label_type {
118  #endif  #endif
119    
120  #if ENABLE_FEATURE_OSF_LABEL  #if ENABLE_FEATURE_OSF_LABEL
121  #define LABEL_IS_OSF (label_osf == current_label_type)  #define LABEL_IS_OSF (LABEL_OSF == current_label_type)
122  #define STATIC_OSF static  #define STATIC_OSF static
123  #else  #else
124  #define LABEL_IS_OSF 0  #define LABEL_IS_OSF 0
125  #define STATIC_OSF extern  #define STATIC_OSF extern
126  #endif  #endif
127    
128  enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };  enum action { OPEN_MAIN, TRY_ONLY, CREATE_EMPTY_DOS, CREATE_EMPTY_SUN };
129    
130  static enum label_type current_label_type;  static void update_units(void);
   
 static const char *disk_device;  
 static int fd;                  /* the disk */  
 static int partitions = 4;      /* maximum partition + 1 */  
 static int display_in_cyl_units = 1;  
 static unsigned units_per_sector = 1;  
131  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
132  static void change_units(void);  static void change_units(void);
133  static void reread_partition_table(int leave);  static void reread_partition_table(int leave);
134  static void delete_partition(int i);  static void delete_partition(int i);
135  static int get_partition(int warn, int max);  static int get_partition(int warn, int max);
136  static void list_types(const struct systypes *sys);  static void list_types(const char *const *sys);
137  static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, char *mesg);  static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg);
138  #endif  #endif
139  static const char *partition_type(unsigned char type);  static const char *partition_type(unsigned char type);
 static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN;  
140  static void get_geometry(void);  static void get_geometry(void);
141    #if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE
142  static int get_boot(enum action what);  static int get_boot(enum action what);
143    #else
144    static int get_boot(void);
145    #endif
146    
147  #define PLURAL   0  #define PLURAL   0
148  #define SINGULAR 1  #define SINGULAR 1
149    
 #define hex_val(c)      ({ \  
  char _c = (c); \  
  isdigit(_c) ? _c - '0' : \  
  tolower(_c) + 10 - 'a'; \  
  })  
   
   
 #define LINE_LENGTH     800  
 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \  
  (n) * sizeof(struct partition)))  
 #define sector(s)       ((s) & 0x3f)  
 #define cylinder(s, c)  ((c) | (((s) & 0xc0) << 2))  
   
 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \  
  ((h) + heads * cylinder(s,c)))  
 #define set_hsc(h,s,c,sector) { \  
  s = sector % sectors + 1;       \  
  sector /= sectors;      \  
  h = sector % heads;     \  
  sector /= heads;        \  
  c = sector & 0xff;      \  
  s |= (sector >> 2) & 0xc0;      \  
  }  
   
   
150  static unsigned get_start_sect(const struct partition *p);  static unsigned get_start_sect(const struct partition *p);
151  static unsigned get_nr_sects(const struct partition *p);  static unsigned get_nr_sects(const struct partition *p);
152    
# Line 231  static unsigned get_nr_sects(const struc Line 158  static unsigned get_nr_sects(const struc
158   * Each logical partition table entry has two pointers, one for the   * Each logical partition table entry has two pointers, one for the
159   * partition and one link to the next one.   * partition and one link to the next one.
160   */   */
161  static struct pte {  struct pte {
162   struct partition *part_table;   /* points into sectorbuffer */   struct partition *part_table;   /* points into sectorbuffer */
163   struct partition *ext_pointer;  /* points into sectorbuffer */   struct partition *ext_pointer;  /* points into sectorbuffer */
164     ullong offset;          /* disk sector number */
165     char *sectorbuffer;     /* disk sector contents */
166  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
167   char changed;           /* boolean */   char changed;           /* boolean */
168  #endif  #endif
169   off_t offset;            /* disk sector number */  };
170   char *sectorbuffer;     /* disk sector contents */  
171  } ptes[MAXIMUM_PARTS];  /* DOS partition types */
172    
173    static const char *const i386_sys_types[] = {
174     "\x00" "Empty",
175     "\x01" "FAT12",
176     "\x04" "FAT16 <32M",
177     "\x05" "Extended",         /* DOS 3.3+ extended partition */
178     "\x06" "FAT16",            /* DOS 16-bit >=32M */
179     "\x07" "HPFS/NTFS",        /* OS/2 IFS, eg, HPFS or NTFS or QNX */
180     "\x0a" "OS/2 Boot Manager",/* OS/2 Boot Manager */
181     "\x0b" "Win95 FAT32",
182     "\x0c" "Win95 FAT32 (LBA)",/* LBA really is 'Extended Int 13h' */
183     "\x0e" "Win95 FAT16 (LBA)",
184     "\x0f" "Win95 Ext'd (LBA)",
185     "\x11" "Hidden FAT12",
186     "\x12" "Compaq diagnostics",
187     "\x14" "Hidden FAT16 <32M",
188     "\x16" "Hidden FAT16",
189     "\x17" "Hidden HPFS/NTFS",
190     "\x1b" "Hidden Win95 FAT32",
191     "\x1c" "Hidden W95 FAT32 (LBA)",
192     "\x1e" "Hidden W95 FAT16 (LBA)",
193     "\x3c" "Part.Magic recovery",
194     "\x41" "PPC PReP Boot",
195     "\x42" "SFS",
196     "\x63" "GNU HURD or SysV", /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
197     "\x80" "Old Minix",        /* Minix 1.4a and earlier */
198     "\x81" "Minix / old Linux",/* Minix 1.4b and later */
199     "\x82" "Linux swap",       /* also Solaris */
200     "\x83" "Linux",
201     "\x84" "OS/2 hidden C: drive",
202     "\x85" "Linux extended",
203     "\x86" "NTFS volume set",
204     "\x87" "NTFS volume set",
205     "\x8e" "Linux LVM",
206     "\x9f" "BSD/OS",           /* BSDI */
207     "\xa0" "Thinkpad hibernation",
208     "\xa5" "FreeBSD",          /* various BSD flavours */
209     "\xa6" "OpenBSD",
210     "\xa8" "Darwin UFS",
211     "\xa9" "NetBSD",
212     "\xab" "Darwin boot",
213     "\xb7" "BSDI fs",
214     "\xb8" "BSDI swap",
215     "\xbe" "Solaris boot",
216     "\xeb" "BeOS fs",
217     "\xee" "EFI GPT",                    /* Intel EFI GUID Partition Table */
218     "\xef" "EFI (FAT-12/16/32)",         /* Intel EFI System Partition */
219     "\xf0" "Linux/PA-RISC boot",         /* Linux/PA-RISC boot loader */
220     "\xf2" "DOS secondary",              /* DOS 3.3+ secondary */
221     "\xfd" "Linux raid autodetect",      /* New (2.2.x) raid partition with
222     autodetect using persistent
223     superblock */
224    #if 0 /* ENABLE_WEIRD_PARTITION_TYPES */
225     "\x02" "XENIX root",
226     "\x03" "XENIX usr",
227     "\x08" "AIX",              /* AIX boot (AIX -- PS/2 port) or SplitDrive */
228     "\x09" "AIX bootable",     /* AIX data or Coherent */
229     "\x10" "OPUS",
230     "\x18" "AST SmartSleep",
231     "\x24" "NEC DOS",
232     "\x39" "Plan 9",
233     "\x40" "Venix 80286",
234     "\x4d" "QNX4.x",
235     "\x4e" "QNX4.x 2nd part",
236     "\x4f" "QNX4.x 3rd part",
237     "\x50" "OnTrack DM",
238     "\x51" "OnTrack DM6 Aux1", /* (or Novell) */
239     "\x52" "CP/M",             /* CP/M or Microport SysV/AT */
240     "\x53" "OnTrack DM6 Aux3",
241     "\x54" "OnTrackDM6",
242     "\x55" "EZ-Drive",
243     "\x56" "Golden Bow",
244     "\x5c" "Priam Edisk",
245     "\x61" "SpeedStor",
246     "\x64" "Novell Netware 286",
247     "\x65" "Novell Netware 386",
248     "\x70" "DiskSecure Multi-Boot",
249     "\x75" "PC/IX",
250     "\x93" "Amoeba",
251     "\x94" "Amoeba BBT",       /* (bad block table) */
252     "\xa7" "NeXTSTEP",
253     "\xbb" "Boot Wizard hidden",
254     "\xc1" "DRDOS/sec (FAT-12)",
255     "\xc4" "DRDOS/sec (FAT-16 < 32M)",
256     "\xc6" "DRDOS/sec (FAT-16)",
257     "\xc7" "Syrinx",
258     "\xda" "Non-FS data",
259     "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or
260                                  Concurrent DOS or CTOS */
261     "\xde" "Dell Utility",     /* Dell PowerEdge Server utilities */
262     "\xdf" "BootIt",           /* BootIt EMBRM */
263     "\xe1" "DOS access",       /* DOS access or SpeedStor 12-bit FAT
264                                  extended partition */
265     "\xe3" "DOS R/O",          /* DOS R/O or SpeedStor */
266     "\xe4" "SpeedStor",        /* SpeedStor 16-bit FAT extended
267                                  partition < 1024 cyl. */
268     "\xf1" "SpeedStor",
269     "\xf4" "SpeedStor",        /* SpeedStor large partition */
270     "\xfe" "LANstep",          /* SpeedStor >1024 cyl. or LANstep */
271     "\xff" "BBT",              /* Xenix Bad Block Table */
272    #endif
273     NULL
274    };
275    
276    enum {
277     dev_fd = 3                  /* the disk */
278    };
279    
280    /* Globals */
281    struct globals {
282     char *line_ptr;
283    
284     const char *disk_device;
285     int g_partitions; // = 4;       /* maximum partition + 1 */
286     unsigned units_per_sector; // = 1;
287     unsigned sector_size; // = DEFAULT_SECTOR_SIZE;
288     unsigned user_set_sector_size;
289     unsigned sector_offset; // = 1;
290     unsigned g_heads, g_sectors, g_cylinders;
291     smallint /* enum label_type */ current_label_type;
292     smallint display_in_cyl_units; // = 1;
293    #if ENABLE_FEATURE_OSF_LABEL
294     smallint possibly_osf_label;
295    #endif
296    
297     smallint listing;               /* no aborts for fdisk -l */
298     smallint dos_compatible_flag; // = 1;
299    #if ENABLE_FEATURE_FDISK_WRITABLE
300     //int dos_changed;
301     smallint nowarn;                /* no warnings for fdisk -l/-s */
302    #endif
303     int ext_index;                  /* the prime extended partition */
304     unsigned user_cylinders, user_heads, user_sectors;
305     unsigned pt_heads, pt_sectors;
306     unsigned kern_heads, kern_sectors;
307     ullong extended_offset;         /* offset of link pointers */
308     ullong total_number_of_sectors;
309    
310     jmp_buf listingbuf;
311     char line_buffer[80];
312     char partname_buffer[80];
313     /* Raw disk label. For DOS-type partition tables the MBR,
314     * with descriptions of the primary partitions. */
315     char MBRbuffer[MAX_SECTOR_SIZE];
316     /* Partition tables */
317     struct pte ptes[MAXIMUM_PARTS];
318    };
319    #define G (*ptr_to_globals)
320    #define line_ptr             (G.line_ptr            )
321    #define disk_device          (G.disk_device         )
322    #define g_partitions         (G.g_partitions        )
323    #define units_per_sector     (G.units_per_sector    )
324    #define sector_size          (G.sector_size         )
325    #define user_set_sector_size (G.user_set_sector_size)
326    #define sector_offset        (G.sector_offset       )
327    #define g_heads              (G.g_heads             )
328    #define g_sectors            (G.g_sectors           )
329    #define g_cylinders          (G.g_cylinders         )
330    #define current_label_type   (G.current_label_type  )
331    #define display_in_cyl_units (G.display_in_cyl_units)
332    #define possibly_osf_label   (G.possibly_osf_label  )
333    #define listing                 (G.listing                )
334    #define dos_compatible_flag     (G.dos_compatible_flag    )
335    #define nowarn                  (G.nowarn                 )
336    #define ext_index               (G.ext_index              )
337    #define user_cylinders          (G.user_cylinders         )
338    #define user_heads              (G.user_heads             )
339    #define user_sectors            (G.user_sectors           )
340    #define pt_heads                (G.pt_heads               )
341    #define pt_sectors              (G.pt_sectors             )
342    #define kern_heads              (G.kern_heads             )
343    #define kern_sectors            (G.kern_sectors           )
344    #define extended_offset         (G.extended_offset        )
345    #define total_number_of_sectors (G.total_number_of_sectors)
346    #define listingbuf      (G.listingbuf     )
347    #define line_buffer     (G.line_buffer    )
348    #define partname_buffer (G.partname_buffer)
349    #define MBRbuffer       (G.MBRbuffer      )
350    #define ptes            (G.ptes           )
351    #define INIT_G() do { \
352     SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
353     sector_size = DEFAULT_SECTOR_SIZE; \
354     sector_offset = 1; \
355     g_partitions = 4; \
356     display_in_cyl_units = 1; \
357     units_per_sector = 1; \
358     dos_compatible_flag = 1; \
359    } while (0)
360    
361    
362    /* TODO: move to libbb? */
363    static ullong bb_BLKGETSIZE_sectors(int fd)
364    {
365     uint64_t v64;
366     unsigned long longsectors;
367    
368     if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
369     /* Got bytes, convert to 512 byte sectors */
370     return (v64 >> 9);
371     }
372     /* Needs temp of type long */
373     if (ioctl(fd, BLKGETSIZE, &longsectors))
374     longsectors = 0;
375     return longsectors;
376    }
377    
378    
379    #define IS_EXTENDED(i) \
380     ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
381    
382    #define cround(n)       (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
383    
384    #define scround(x)      (((x)+units_per_sector-1)/units_per_sector)
385    
386    #define pt_offset(b, n) \
387     ((struct partition *)((b) + 0x1be + (n) * sizeof(struct partition)))
388    
389    #define sector(s)       ((s) & 0x3f)
390    
391    #define cylinder(s, c)  ((c) | (((s) & 0xc0) << 2))
392    
393    #define hsc2sector(h,s,c) \
394     (sector(s) - 1 + sectors * ((h) + heads * cylinder(s,c)))
395    
396    #define set_hsc(h,s,c,sector) \
397     do { \
398     s = sector % g_sectors + 1;  \
399     sector /= g_sectors;         \
400     h = sector % g_heads;        \
401     sector /= g_heads;           \
402     c = sector & 0xff;           \
403     s |= (sector >> 2) & 0xc0;   \
404     } while (0)
405    
406    static void
407    close_dev_fd(void)
408    {
409     /* Not really closing, but making sure it is open, and to harmless place */
410     xmove_fd(xopen(bb_dev_null, O_RDONLY), dev_fd);
411    }
412    
413    #if ENABLE_FEATURE_FDISK_WRITABLE
414    /* Read line; return 0 or first printable char */
415    static int
416    read_line(const char *prompt)
417    {
418     int sz;
419    
420     sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
421     if (sz <= 0)
422     exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
423    
424     if (line_buffer[sz-1] == '\n')
425     line_buffer[--sz] = '\0';
426    
427     line_ptr = line_buffer;
428     while (*line_ptr && !isgraph(*line_ptr))
429     line_ptr++;
430     return *line_ptr;
431    }
432    #endif
433    
434    /*
435     * Return partition name - uses static storage
436     */
437    static const char *
438    partname(const char *dev, int pno, int lth)
439    {
440     const char *p;
441     int w, wp;
442     int bufsiz;
443     char *bufp;
444    
445     bufp = partname_buffer;
446     bufsiz = sizeof(partname_buffer);
447    
448     w = strlen(dev);
449     p = "";
450    
451     if (isdigit(dev[w-1]))
452     p = "p";
453    
454     /* devfs kludge - note: fdisk partition names are not supposed
455       to equal kernel names, so there is no reason to do this */
456     if (strcmp(dev + w - 4, "disc") == 0) {
457     w -= 4;
458     p = "part";
459     }
460    
461     wp = strlen(p);
462    
463     if (lth) {
464     snprintf(bufp, bufsiz, "%*.*s%s%-2u",
465     lth-wp-2, w, dev, p, pno);
466     } else {
467     snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
468     }
469     return bufp;
470    }
471    
472  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
473  static void  static void
# Line 252  set_all_unchanged(void) Line 479  set_all_unchanged(void)
479   ptes[i].changed = 0;   ptes[i].changed = 0;
480  }  }
481    
482  static ATTRIBUTE_ALWAYS_INLINE void  static ALWAYS_INLINE void
483  set_changed(int i)  set_changed(int i)
484  {  {
485   ptes[i].changed = 1;   ptes[i].changed = 1;
486  }  }
487  #endif /* FEATURE_FDISK_WRITABLE */  #endif /* FEATURE_FDISK_WRITABLE */
488    
489  static ATTRIBUTE_ALWAYS_INLINE struct partition *  static ALWAYS_INLINE struct partition *
490  get_part_table(int i)  get_part_table(int i)
491  {  {
492   return ptes[i].part_table;   return ptes[i].part_table;
# Line 269  static const char * Line 496  static const char *
496  str_units(int n)  str_units(int n)
497  {      /* n==1: use singular */  {      /* n==1: use singular */
498   if (n == 1)   if (n == 1)
499   return display_in_cyl_units ? _("cylinder") : _("sector");   return display_in_cyl_units ? "cylinder" : "sector";
500   else   return display_in_cyl_units ? "cylinders" : "sectors";
  return display_in_cyl_units ? _("cylinders") : _("sectors");  
501  }  }
502    
503  static int  static int
# Line 281  valid_part_table_flag(const char *mbuffe Line 507  valid_part_table_flag(const char *mbuffe
507  }  }
508    
509  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
510  static ATTRIBUTE_ALWAYS_INLINE void  static ALWAYS_INLINE void
511  write_part_table_flag(char *b)  write_part_table_flag(char *b)
512  {  {
513   b[510] = 0x55;   b[510] = 0x55;
514   b[511] = 0xaa;   b[511] = 0xaa;
515  }  }
516    
 static char line_buffer[LINE_LENGTH];  
 static char *line_ptr;  
   
 /* read line; return 0 or first char */  
 static int  
 read_line(void)  
 {  
  fflush(stdout);         /* requested by niles@scyld.com */  
  line_ptr = line_buffer;  
  if (!fgets(line_buffer, LINE_LENGTH, stdin)) {  
  /* error or eof */  
  bb_error_msg_and_die("\ngot EOF, exiting");  
  }  
  while (*line_ptr && !isgraph(*line_ptr))  
  line_ptr++;  
  return *line_ptr;  
 }  
   
517  static char  static char
518  read_nonempty(const char *mesg)  read_nonempty(const char *mesg)
519  {  {
520   do {   while (!read_line(mesg))
521   fputs(mesg, stdout);   continue;
  } while (!read_line());  
522   return *line_ptr;   return *line_ptr;
523  }  }
524    
525  static char  static char
526  read_maybe_empty(const char *mesg)  read_maybe_empty(const char *mesg)
527  {  {
528   fputs(mesg, stdout);   if (!read_line(mesg)) {
  if (!read_line()) {  
529   line_ptr = line_buffer;   line_ptr = line_buffer;
530   *line_ptr = '\n';   line_ptr[0] = '\n';
531   line_ptr[1] = 0;   line_ptr[1] = '\0';
532   }   }
533   return *line_ptr;   return line_ptr[0];
534  }  }
535    
536  static int  static int
537  read_hex(const struct systypes *sys)  read_hex(const char *const *sys)
538  {  {
539   unsigned long v;   unsigned long v;
540   while (1) {   while (1) {
541   read_nonempty(_("Hex code (type L to list codes): "));   read_nonempty("Hex code (type L to list codes): ");
542   if (*line_ptr == 'l' || *line_ptr == 'L') {   if (*line_ptr == 'l' || *line_ptr == 'L') {
543   list_types(sys);   list_types(sys);
544   continue;   continue;
# Line 346  read_hex(const struct systypes *sys) Line 552  read_hex(const struct systypes *sys)
552  }  }
553  #endif /* FEATURE_FDISK_WRITABLE */  #endif /* FEATURE_FDISK_WRITABLE */
554    
555    static void fdisk_fatal(const char *why)
556    {
557     if (listing) {
558     close_dev_fd();
559     longjmp(listingbuf, 1);
560     }
561     bb_error_msg_and_die(why, disk_device);
562    }
563    
564    static void
565    seek_sector(ullong secno)
566    {
567     secno *= sector_size;
568    #if ENABLE_FDISK_SUPPORT_LARGE_DISKS
569     if (lseek64(dev_fd, (off64_t)secno, SEEK_SET) == (off64_t) -1)
570     fdisk_fatal(unable_to_seek);
571    #else
572     if (secno > MAXINT(off_t)
573     || lseek(dev_fd, (off_t)secno, SEEK_SET) == (off_t) -1
574     ) {
575     fdisk_fatal(unable_to_seek);
576     }
577    #endif
578    }
579    
580    #if ENABLE_FEATURE_FDISK_WRITABLE
581    static void
582    write_sector(ullong secno, const void *buf)
583    {
584     seek_sector(secno);
585     xwrite(dev_fd, buf, sector_size);
586    }
587    #endif
588    
589    
590  #include "fdisk_aix.c"  #include "fdisk_aix.c"
591    
592  typedef struct {  typedef struct {
# Line 376  typedef struct { Line 617  typedef struct {
617   unsigned short csum;       /* Label xor'd checksum */   unsigned short csum;       /* Label xor'd checksum */
618  } sun_partition;  } sun_partition;
619  #define sunlabel ((sun_partition *)MBRbuffer)  #define sunlabel ((sun_partition *)MBRbuffer)
 #define SUNOS_SWAP 3  
 #define SUN_WHOLE_DISK 5  
620  STATIC_OSF void bsd_select(void);  STATIC_OSF void bsd_select(void);
621  STATIC_OSF void xbsd_print_disklabel(int);  STATIC_OSF void xbsd_print_disklabel(int);
622  #include "fdisk_osf.c"  #include "fdisk_osf.c"
623    
 #define SGI_VOLHDR      0x00  
 /* 1 and 2 were used for drive types no longer supported by SGI */  
 #define SGI_SWAP        0x03  
 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */  
 #define SGI_VOLUME      0x06  
 #define SGI_EFS         0x07  
 #define SGI_LVOL        0x08  
 #define SGI_RLVOL       0x09  
 #define SGI_XFS         0x0a  
 #define SGI_XFSLOG      0x0b  
 #define SGI_XLV         0x0c  
 #define SGI_XVM         0x0d  
 #define SGI_ENTIRE_DISK SGI_VOLUME  
624  #if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL  #if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
625  static uint16_t  static uint16_t
626  fdisk_swap16(uint16_t x)  fdisk_swap16(uint16_t x)
# Line 412  fdisk_swap32(uint32_t x) Line 638  fdisk_swap32(uint32_t x)
638  }  }
639  #endif  #endif
640    
641  STATIC_SGI const struct systypes sgi_sys_types[];  STATIC_SGI const char *const sgi_sys_types[];
642  STATIC_SGI unsigned sgi_get_num_sectors(int i);  STATIC_SGI unsigned sgi_get_num_sectors(int i);
643  STATIC_SGI int sgi_get_sysid(int i);  STATIC_SGI int sgi_get_sysid(int i);
644  STATIC_SGI void sgi_delete_partition(int i);  STATIC_SGI void sgi_delete_partition(int i);
# Line 431  STATIC_SGI void sgi_write_table(void); Line 657  STATIC_SGI void sgi_write_table(void);
657  STATIC_SGI void sgi_set_bootpartition(int i);  STATIC_SGI void sgi_set_bootpartition(int i);
658  #include "fdisk_sgi.c"  #include "fdisk_sgi.c"
659    
660  STATIC_SUN const struct systypes sun_sys_types[];  STATIC_SUN const char *const sun_sys_types[];
661  STATIC_SUN void sun_delete_partition(int i);  STATIC_SUN void sun_delete_partition(int i);
662  STATIC_SUN void sun_change_sysid(int i, int sys);  STATIC_SUN void sun_change_sysid(int i, int sys);
663  STATIC_SUN void sun_list_table(int xtra);  STATIC_SUN void sun_list_table(int xtra);
# Line 449  STATIC_SUN void verify_sun(void); Line 675  STATIC_SUN void verify_sun(void);
675  STATIC_SUN void sun_write_table(void);  STATIC_SUN void sun_write_table(void);
676  #include "fdisk_sun.c"  #include "fdisk_sun.c"
677    
 /* DOS partition types */  
   
 static const struct systypes i386_sys_types[] = {  
  { "\x00" "Empty" },  
  { "\x01" "FAT12" },  
  { "\x04" "FAT16 <32M" },  
  { "\x05" "Extended" },         /* DOS 3.3+ extended partition */  
  { "\x06" "FAT16" },            /* DOS 16-bit >=32M */  
  { "\x07" "HPFS/NTFS" },        /* OS/2 IFS, eg, HPFS or NTFS or QNX */  
  { "\x0a" "OS/2 Boot Manager" },/* OS/2 Boot Manager */  
  { "\x0b" "Win95 FAT32" },  
  { "\x0c" "Win95 FAT32 (LBA)" },/* LBA really is 'Extended Int 13h' */  
  { "\x0e" "Win95 FAT16 (LBA)" },  
  { "\x0f" "Win95 Ext'd (LBA)" },  
  { "\x11" "Hidden FAT12" },  
  { "\x12" "Compaq diagnostics" },  
  { "\x14" "Hidden FAT16 <32M" },  
  { "\x16" "Hidden FAT16" },  
  { "\x17" "Hidden HPFS/NTFS" },  
  { "\x1b" "Hidden Win95 FAT32" },  
  { "\x1c" "Hidden Win95 FAT32 (LBA)" },  
  { "\x1e" "Hidden Win95 FAT16 (LBA)" },  
  { "\x3c" "PartitionMagic recovery" },  
  { "\x41" "PPC PReP Boot" },  
  { "\x42" "SFS" },  
  { "\x63" "GNU HURD or SysV" }, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */  
  { "\x80" "Old Minix" },        /* Minix 1.4a and earlier */  
  { "\x81" "Minix / old Linux" },/* Minix 1.4b and later */  
  { "\x82" "Linux swap" },       /* also Solaris */  
  { "\x83" "Linux" },  
  { "\x84" "OS/2 hidden C: drive" },  
  { "\x85" "Linux extended" },  
  { "\x86" "NTFS volume set" },  
  { "\x87" "NTFS volume set" },  
  { "\x8e" "Linux LVM" },  
  { "\x9f" "BSD/OS" },           /* BSDI */  
  { "\xa0" "IBM Thinkpad hibernation" },  
  { "\xa5" "FreeBSD" },          /* various BSD flavours */  
  { "\xa6" "OpenBSD" },  
  { "\xa8" "Darwin UFS" },  
  { "\xa9" "NetBSD" },  
  { "\xab" "Darwin boot" },  
  { "\xb7" "BSDI fs" },  
  { "\xb8" "BSDI swap" },  
  { "\xbe" "Solaris boot" },  
  { "\xeb" "BeOS fs" },  
  { "\xee" "EFI GPT" },          /* Intel EFI GUID Partition Table */  
  { "\xef" "EFI (FAT-12/16/32)" },/* Intel EFI System Partition */  
  { "\xf0" "Linux/PA-RISC boot" },/* Linux/PA-RISC boot loader */  
  { "\xf2" "DOS secondary" },    /* DOS 3.3+ secondary */  
  { "\xfd" "Linux raid autodetect" },/* New (2.2.x) raid partition with  
  autodetect using persistent  
  superblock */  
 #if 0 /* ENABLE_WEIRD_PARTITION_TYPES */  
  { "\x02" "XENIX root" },  
  { "\x03" "XENIX usr" },  
  { "\x08" "AIX" },              /* AIX boot (AIX -- PS/2 port) or SplitDrive */  
  { "\x09" "AIX bootable" },     /* AIX data or Coherent */  
  { "\x10" "OPUS" },  
  { "\x18" "AST SmartSleep" },  
  { "\x24" "NEC DOS" },  
  { "\x39" "Plan 9" },  
  { "\x40" "Venix 80286" },  
  { "\x4d" "QNX4.x" },  
  { "\x4e" "QNX4.x 2nd part" },  
  { "\x4f" "QNX4.x 3rd part" },  
  { "\x50" "OnTrack DM" },  
  { "\x51" "OnTrack DM6 Aux1" }, /* (or Novell) */  
  { "\x52" "CP/M" },             /* CP/M or Microport SysV/AT */  
  { "\x53" "OnTrack DM6 Aux3" },  
  { "\x54" "OnTrackDM6" },  
  { "\x55" "EZ-Drive" },  
  { "\x56" "Golden Bow" },  
  { "\x5c" "Priam Edisk" },  
  { "\x61" "SpeedStor" },  
  { "\x64" "Novell Netware 286" },  
  { "\x65" "Novell Netware 386" },  
  { "\x70" "DiskSecure Multi-Boot" },  
  { "\x75" "PC/IX" },  
  { "\x93" "Amoeba" },  
  { "\x94" "Amoeba BBT" },       /* (bad block table) */  
  { "\xa7" "NeXTSTEP" },  
  { "\xbb" "Boot Wizard hidden" },  
  { "\xc1" "DRDOS/sec (FAT-12)" },  
  { "\xc4" "DRDOS/sec (FAT-16 < 32M)" },  
  { "\xc6" "DRDOS/sec (FAT-16)" },  
  { "\xc7" "Syrinx" },  
  { "\xda" "Non-FS data" },  
  { "\xdb" "CP/M / CTOS / ..." },/* CP/M or Concurrent CP/M or  
  Concurrent DOS or CTOS */  
  { "\xde" "Dell Utility" },     /* Dell PowerEdge Server utilities */  
  { "\xdf" "BootIt" },           /* BootIt EMBRM */  
  { "\xe1" "DOS access" },       /* DOS access or SpeedStor 12-bit FAT  
  extended partition */  
  { "\xe3" "DOS R/O" },          /* DOS R/O or SpeedStor */  
  { "\xe4" "SpeedStor" },        /* SpeedStor 16-bit FAT extended  
  partition < 1024 cyl. */  
  { "\xf1" "SpeedStor" },  
  { "\xf4" "SpeedStor" },        /* SpeedStor large partition */  
  { "\xfe" "LANstep" },          /* SpeedStor >1024 cyl. or LANstep */  
  { "\xff" "BBT" },              /* Xenix Bad Block Table */  
 #endif  
  { 0 }  
 };  
   
678    
679  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
680  /* start_sect and nr_sects are stored little endian on all machines */  /* start_sect and nr_sects are stored little endian on all machines */
# Line 602  get_nr_sects(const struct partition *p) Line 723  get_nr_sects(const struct partition *p)
723   return read4_little_endian(p->size4);   return read4_little_endian(p->size4);
724  }  }
725    
 /* normally O_RDWR, -l option gives O_RDONLY */  
 static int type_open = O_RDWR;  
   
   
 static int ext_index;               /* the prime extended partition */  
 static int listing;                    /* no aborts for fdisk -l */  
 static int dos_compatible_flag = ~0;  
 #if ENABLE_FEATURE_FDISK_WRITABLE  
 static int dos_changed;  
 static int nowarn;            /* no warnings for fdisk -l/-s */  
 #endif  
   
   
   
 static unsigned user_cylinders, user_heads, user_sectors;  
 static unsigned pt_heads, pt_sectors;  
 static unsigned kern_heads, kern_sectors;  
   
 static off_t extended_offset;            /* offset of link pointers */  
   
 static unsigned long long total_number_of_sectors;  
   
   
 static jmp_buf listingbuf;  
   
 static void fdisk_fatal(enum failure why)  
 {  
  const char *message;  
   
  if (listing) {  
  close(fd);  
  longjmp(listingbuf, 1);  
  }  
   
  switch (why) {  
  case unable_to_open:  
  message = "\nUnable to open %s";  
  break;  
  case unable_to_read:  
  message = "\nUnable to read %s";  
  break;  
  case unable_to_seek:  
  message = "\nUnable to seek on %s";  
  break;  
  case unable_to_write:  
  message = "\nUnable to write %s";  
  break;  
  case ioctl_error:  
  message = "\nBLKGETSIZE ioctl failed on %s";  
  break;  
  default:  
  message = "\nFatal error";  
  }  
   
  bb_error_msg_and_die(message, disk_device);  
 }  
   
 static void  
 seek_sector(off_t secno)  
 {  
  off_t offset = secno * sector_size;  
  if (lseek(fd, offset, SEEK_SET) == (off_t) -1)  
  fdisk_fatal(unable_to_seek);  
 }  
   
 #if ENABLE_FEATURE_FDISK_WRITABLE  
 static void  
 write_sector(off_t secno, char *buf)  
 {  
  seek_sector(secno);  
  if (write(fd, buf, sector_size) != sector_size)  
  fdisk_fatal(unable_to_write);  
 }  
 #endif  
   
726  /* Allocate a buffer and read a partition table sector */  /* Allocate a buffer and read a partition table sector */
727  static void  static void
728  read_pte(struct pte *pe, off_t offset)  read_pte(struct pte *pe, ullong offset)
729  {  {
730   pe->offset = offset;   pe->offset = offset;
731   pe->sectorbuffer = xmalloc(sector_size);   pe->sectorbuffer = xzalloc(sector_size);
732   seek_sector(offset);   seek_sector(offset);
733   if (read(fd, pe->sectorbuffer, sector_size) != sector_size)   /* xread would make us abort - bad for fdisk -l */
734     if (full_read(dev_fd, pe->sectorbuffer, sector_size) != sector_size)
735   fdisk_fatal(unable_to_read);   fdisk_fatal(unable_to_read);
736  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
737   pe->changed = 0;   pe->changed = 0;
# Line 705  get_partition_start(const struct pte *pe Line 752  get_partition_start(const struct pte *pe
752   * We might also do the opposite and warn in all cases except   * We might also do the opposite and warn in all cases except
753   * for "is probably nondos partition".   * for "is probably nondos partition".
754   */   */
755    #ifdef UNUSED
756  static int  static int
757  is_dos_partition(int t)  is_dos_partition(int t)
758  {  {
# Line 714  is_dos_partition(int t) Line 762  is_dos_partition(int t)
762   t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||   t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
763   t == 0xc1 || t == 0xc4 || t == 0xc6);   t == 0xc1 || t == 0xc4 || t == 0xc6);
764  }  }
765    #endif
766    
767  static void  static void
768  menu(void)  menu(void)
769  {  {
770     puts("Command Action");
771   if (LABEL_IS_SUN) {   if (LABEL_IS_SUN) {
772   puts(_("Command action"));   puts("a\ttoggle a read only flag");           /* sun */
773   puts(_("\ta\ttoggle a read only flag"));           /* sun */   puts("b\tedit bsd disklabel");
774   puts(_("\tb\tedit bsd disklabel"));   puts("c\ttoggle the mountable flag");         /* sun */
775   puts(_("\tc\ttoggle the mountable flag"));         /* sun */   puts("d\tdelete a partition");
776   puts(_("\td\tdelete a partition"));   puts("l\tlist known partition types");
777   puts(_("\tl\tlist known partition types"));   puts("n\tadd a new partition");
778   puts(_("\tm\tprint this menu"));   puts("o\tcreate a new empty DOS partition table");
779   puts(_("\tn\tadd a new partition"));   puts("p\tprint the partition table");
780   puts(_("\to\tcreate a new empty DOS partition table"));   puts("q\tquit without saving changes");
781   puts(_("\tp\tprint the partition table"));   puts("s\tcreate a new empty Sun disklabel");  /* sun */
782   puts(_("\tq\tquit without saving changes"));   puts("t\tchange a partition's system id");
783   puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */   puts("u\tchange display/entry units");
784   puts(_("\tt\tchange a partition's system id"));   puts("v\tverify the partition table");
785   puts(_("\tu\tchange display/entry units"));   puts("w\twrite table to disk and exit");
  puts(_("\tv\tverify the partition table"));  
  puts(_("\tw\twrite table to disk and exit"));  
786  #if ENABLE_FEATURE_FDISK_ADVANCED  #if ENABLE_FEATURE_FDISK_ADVANCED
787   puts(_("\tx\textra functionality (experts only)"));   puts("x\textra functionality (experts only)");
788  #endif  #endif
789   } else   } else if (LABEL_IS_SGI) {
790   if (LABEL_IS_SGI) {   puts("a\tselect bootable partition");    /* sgi flavour */
791   puts(_("Command action"));   puts("b\tedit bootfile entry");          /* sgi */
792   puts(_("\ta\tselect bootable partition"));    /* sgi flavour */   puts("c\tselect sgi swap partition");    /* sgi flavour */
793   puts(_("\tb\tedit bootfile entry"));          /* sgi */   puts("d\tdelete a partition");
794   puts(_("\tc\tselect sgi swap partition"));    /* sgi flavour */   puts("l\tlist known partition types");
795   puts(_("\td\tdelete a partition"));   puts("n\tadd a new partition");
796   puts(_("\tl\tlist known partition types"));   puts("o\tcreate a new empty DOS partition table");
797   puts(_("\tm\tprint this menu"));   puts("p\tprint the partition table");
798   puts(_("\tn\tadd a new partition"));   puts("q\tquit without saving changes");
799   puts(_("\to\tcreate a new empty DOS partition table"));   puts("s\tcreate a new empty Sun disklabel");  /* sun */
800   puts(_("\tp\tprint the partition table"));   puts("t\tchange a partition's system id");
801   puts(_("\tq\tquit without saving changes"));   puts("u\tchange display/entry units");
802   puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */   puts("v\tverify the partition table");
803   puts(_("\tt\tchange a partition's system id"));   puts("w\twrite table to disk and exit");
804   puts(_("\tu\tchange display/entry units"));   } else if (LABEL_IS_AIX) {
805   puts(_("\tv\tverify the partition table"));   puts("o\tcreate a new empty DOS partition table");
806   puts(_("\tw\twrite table to disk and exit"));   puts("q\tquit without saving changes");
807   } else   puts("s\tcreate a new empty Sun disklabel");  /* sun */
808   if (LABEL_IS_AIX) {   } else {
809   puts(_("Command action"));   puts("a\ttoggle a bootable flag");
810   puts(_("\tm\tprint this menu"));   puts("b\tedit bsd disklabel");
811   puts(_("\to\tcreate a new empty DOS partition table"));   puts("c\ttoggle the dos compatibility flag");
812   puts(_("\tq\tquit without saving changes"));   puts("d\tdelete a partition");
813   puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */   puts("l\tlist known partition types");
814   } else   puts("n\tadd a new partition");
815   {   puts("o\tcreate a new empty DOS partition table");
816   puts(_("Command action"));   puts("p\tprint the partition table");
817   puts(_("\ta\ttoggle a bootable flag"));   puts("q\tquit without saving changes");
818   puts(_("\tb\tedit bsd disklabel"));   puts("s\tcreate a new empty Sun disklabel");  /* sun */
819   puts(_("\tc\ttoggle the dos compatibility flag"));   puts("t\tchange a partition's system id");
820   puts(_("\td\tdelete a partition"));   puts("u\tchange display/entry units");
821   puts(_("\tl\tlist known partition types"));   puts("v\tverify the partition table");
822   puts(_("\tm\tprint this menu"));   puts("w\twrite table to disk and exit");
  puts(_("\tn\tadd a new partition"));  
  puts(_("\to\tcreate a new empty DOS partition table"));  
  puts(_("\tp\tprint the partition table"));  
  puts(_("\tq\tquit without saving changes"));  
  puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */  
  puts(_("\tt\tchange a partition's system id"));  
  puts(_("\tu\tchange display/entry units"));  
  puts(_("\tv\tverify the partition table"));  
  puts(_("\tw\twrite table to disk and exit"));  
823  #if ENABLE_FEATURE_FDISK_ADVANCED  #if ENABLE_FEATURE_FDISK_ADVANCED
824   puts(_("\tx\textra functionality (experts only)"));   puts("x\textra functionality (experts only)");
825  #endif  #endif
826   }   }
827  }  }
# Line 793  menu(void) Line 832  menu(void)
832  static void  static void
833  xmenu(void)  xmenu(void)
834  {  {
835     puts("Command Action");
836   if (LABEL_IS_SUN) {   if (LABEL_IS_SUN) {
837   puts(_("Command action"));   puts("a\tchange number of alternate cylinders");      /*sun*/
838   puts(_("\ta\tchange number of alternate cylinders"));      /*sun*/   puts("c\tchange number of cylinders");
839   puts(_("\tc\tchange number of cylinders"));   puts("d\tprint the raw data in the partition table");
840   puts(_("\td\tprint the raw data in the partition table"));   puts("e\tchange number of extra sectors per cylinder");/*sun*/
841   puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/   puts("h\tchange number of heads");
842   puts(_("\th\tchange number of heads"));   puts("i\tchange interleave factor");                  /*sun*/
843   puts(_("\ti\tchange interleave factor"));                  /*sun*/   puts("o\tchange rotation speed (rpm)");               /*sun*/
844   puts(_("\to\tchange rotation speed (rpm)"));               /*sun*/   puts("p\tprint the partition table");
845   puts(_("\tm\tprint this menu"));   puts("q\tquit without saving changes");
846   puts(_("\tp\tprint the partition table"));   puts("r\treturn to main menu");
847   puts(_("\tq\tquit without saving changes"));   puts("s\tchange number of sectors/track");
848   puts(_("\tr\treturn to main menu"));   puts("v\tverify the partition table");
849   puts(_("\ts\tchange number of sectors/track"));   puts("w\twrite table to disk and exit");
850   puts(_("\tv\tverify the partition table"));   puts("y\tchange number of physical cylinders");       /*sun*/
851   puts(_("\tw\twrite table to disk and exit"));   } else if (LABEL_IS_SGI) {
852   puts(_("\ty\tchange number of physical cylinders"));       /*sun*/   puts("b\tmove beginning of data in a partition"); /* !sun */
853   }  else   puts("c\tchange number of cylinders");
854   if (LABEL_IS_SGI) {   puts("d\tprint the raw data in the partition table");
855   puts(_("Command action"));   puts("e\tlist extended partitions");          /* !sun */
856   puts(_("\tb\tmove beginning of data in a partition")); /* !sun */   puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
857   puts(_("\tc\tchange number of cylinders"));   puts("h\tchange number of heads");
858   puts(_("\td\tprint the raw data in the partition table"));   puts("p\tprint the partition table");
859   puts(_("\te\tlist extended partitions"));          /* !sun */   puts("q\tquit without saving changes");
860   puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */   puts("r\treturn to main menu");
861   puts(_("\th\tchange number of heads"));   puts("s\tchange number of sectors/track");
862   puts(_("\tm\tprint this menu"));   puts("v\tverify the partition table");
863   puts(_("\tp\tprint the partition table"));   puts("w\twrite table to disk and exit");
864   puts(_("\tq\tquit without saving changes"));   } else if (LABEL_IS_AIX) {
865   puts(_("\tr\treturn to main menu"));   puts("b\tmove beginning of data in a partition"); /* !sun */
866   puts(_("\ts\tchange number of sectors/track"));   puts("c\tchange number of cylinders");
867   puts(_("\tv\tverify the partition table"));   puts("d\tprint the raw data in the partition table");
868   puts(_("\tw\twrite table to disk and exit"));   puts("e\tlist extended partitions");          /* !sun */
869   } else   puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
870   if (LABEL_IS_AIX) {   puts("h\tchange number of heads");
871   puts(_("Command action"));   puts("p\tprint the partition table");
872   puts(_("\tb\tmove beginning of data in a partition")); /* !sun */   puts("q\tquit without saving changes");
873   puts(_("\tc\tchange number of cylinders"));   puts("r\treturn to main menu");
874   puts(_("\td\tprint the raw data in the partition table"));   puts("s\tchange number of sectors/track");
875   puts(_("\te\tlist extended partitions"));          /* !sun */   puts("v\tverify the partition table");
876   puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */   puts("w\twrite table to disk and exit");
877   puts(_("\th\tchange number of heads"));   } else {
878   puts(_("\tm\tprint this menu"));   puts("b\tmove beginning of data in a partition"); /* !sun */
879   puts(_("\tp\tprint the partition table"));   puts("c\tchange number of cylinders");
880   puts(_("\tq\tquit without saving changes"));   puts("d\tprint the raw data in the partition table");
881   puts(_("\tr\treturn to main menu"));   puts("e\tlist extended partitions");          /* !sun */
882   puts(_("\ts\tchange number of sectors/track"));   puts("f\tfix partition order");               /* !sun, !aix, !sgi */
  puts(_("\tv\tverify the partition table"));  
  puts(_("\tw\twrite table to disk and exit"));  
  }  else {  
  puts(_("Command action"));  
  puts(_("\tb\tmove beginning of data in a partition")); /* !sun */  
  puts(_("\tc\tchange number of cylinders"));  
  puts(_("\td\tprint the raw data in the partition table"));  
  puts(_("\te\tlist extended partitions"));          /* !sun */  
  puts(_("\tf\tfix partition order"));               /* !sun, !aix, !sgi */  
883  #if ENABLE_FEATURE_SGI_LABEL  #if ENABLE_FEATURE_SGI_LABEL
884   puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */   puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
885  #endif  #endif
886   puts(_("\th\tchange number of heads"));   puts("h\tchange number of heads");
887   puts(_("\tm\tprint this menu"));   puts("p\tprint the partition table");
888   puts(_("\tp\tprint the partition table"));   puts("q\tquit without saving changes");
889   puts(_("\tq\tquit without saving changes"));   puts("r\treturn to main menu");
890   puts(_("\tr\treturn to main menu"));   puts("s\tchange number of sectors/track");
891   puts(_("\ts\tchange number of sectors/track"));   puts("v\tverify the partition table");
892   puts(_("\tv\tverify the partition table"));   puts("w\twrite table to disk and exit");
  puts(_("\tw\twrite table to disk and exit"));  
893   }   }
894  }  }
895  #endif /* ADVANCED mode */  #endif /* ADVANCED mode */
896    
897  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
898  static const struct systypes *  static const char *const *
899  get_sys_types(void)  get_sys_types(void)
900  {  {
901   return (   return (
# Line 877  get_sys_types(void) Line 907  get_sys_types(void)
907  #define get_sys_types() i386_sys_types  #define get_sys_types() i386_sys_types
908  #endif /* FEATURE_FDISK_WRITABLE */  #endif /* FEATURE_FDISK_WRITABLE */
909    
910  static const char *partition_type(unsigned char type)  static const char *
911    partition_type(unsigned char type)
912  {  {
913   int i;   int i;
914   const struct systypes *types = get_sys_types();   const char *const *types = get_sys_types();
915    
916   for (i = 0; types[i].name; i++)   for (i = 0; types[i]; i++)
917   if ((unsigned char )types[i].name[0] == type)   if ((unsigned char)types[i][0] == type)
918   return types[i].name + 1;   return types[i] + 1;
919    
920   return _("Unknown");   return "Unknown";
921  }  }
922    
923    
# Line 899  get_sysid(int i) Line 930  get_sysid(int i)
930   ptes[i].part_table->sys_ind);   ptes[i].part_table->sys_ind);
931  }  }
932    
933  void list_types(const struct systypes *sys)  static void
934    list_types(const char *const *sys)
935  {  {
936   unsigned last[4], done = 0, next = 0, size;   enum { COLS = 3 };
937    
938     unsigned last[COLS];
939     unsigned done, next, size;
940   int i;   int i;
941    
942   for (i = 0; sys[i].name; i++);   for (size = 0; sys[size]; size++)
943   size = i;   continue;
944    
945   for (i = 3; i >= 0; i--)   done = 0;
946   last[3 - i] = done += (size + i - done) / (i + 1);   for (i = COLS-1; i >= 0; i--) {
947   i = done = 0;   done += (size + i - done) / (i + 1);
948     last[COLS-1 - i] = done;
949     }
950    
951     i = done = next = 0;
952   do {   do {
953   printf("%c%2x  %-15.15s", i ? ' ' : '\n',   printf("%c%2x %-22.22s", i ? ' ' : '\n',
954   (unsigned char)sys[next].name[0],   (unsigned char)sys[next][0],
955   partition_type((unsigned char)sys[next].name[0]));   sys[next] + 1);
956   next = last[i++] + done;   next = last[i++] + done;
957   if (i > 3 || next >= last[i]) {   if (i >= COLS || next >= last[i]) {
958   i = 0;   i = 0;
959   next = ++done;   next = ++done;
960   }   }
961   } while (done < last[0]);   } while (done < last[0]);
962   putchar('\n');   bb_putchar('\n');
963  }  }
964  #endif /* FEATURE_FDISK_WRITABLE */  #endif /* FEATURE_FDISK_WRITABLE */
965    
# Line 943  clear_partition(struct partition *p) Line 981  clear_partition(struct partition *p)
981    
982  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
983  static void  static void
984  set_partition(int i, int doext, off_t start, off_t stop, int sysid)  set_partition(int i, int doext, ullong start, ullong stop, int sysid)
985  {  {
986   struct partition *p;   struct partition *p;
987   off_t offset;   ullong offset;
988    
989   if (doext) {   if (doext) {
990   p = ptes[i].ext_pointer;   p = ptes[i].ext_pointer;
# Line 959  set_partition(int i, int doext, off_t st Line 997  set_partition(int i, int doext, off_t st
997   p->sys_ind = sysid;   p->sys_ind = sysid;
998   set_start_sect(p, start - offset);   set_start_sect(p, start - offset);
999   set_nr_sects(p, stop - start + 1);   set_nr_sects(p, stop - start + 1);
1000   if (dos_compatible_flag && (start/(sectors*heads) > 1023))   if (dos_compatible_flag && (start / (g_sectors * g_heads) > 1023))
1001   start = heads*sectors*1024 - 1;   start = g_heads * g_sectors * 1024 - 1;
1002   set_hsc(p->head, p->sector, p->cyl, start);   set_hsc(p->head, p->sector, p->cyl, start);
1003   if (dos_compatible_flag && (stop/(sectors*heads) > 1023))   if (dos_compatible_flag && (stop / (g_sectors * g_heads) > 1023))
1004   stop = heads*sectors*1024 - 1;   stop = g_heads * g_sectors * 1024 - 1;
1005   set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);   set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
1006   ptes[i].changed = 1;   ptes[i].changed = 1;
1007  }  }
1008  #endif  #endif
1009    
1010  static int  static int
 test_c(const char **m, const char *mesg)  
 {  
  int val = 0;  
  if (!*m)  
  printf(_("You must set"));  
  else {  
  printf(" %s", *m);  
  val = 1;  
  }  
  *m = mesg;  
  return val;  
 }  
   
 static int  
1011  warn_geometry(void)  warn_geometry(void)
1012  {  {
1013   const char *m = NULL;   if (g_heads && g_sectors && g_cylinders)
  int prev = 0;  
   
  if (!heads)  
  prev = test_c(&m, _("heads"));  
  if (!sectors)  
  prev = test_c(&m, _("sectors"));  
  if (!cylinders)  
  prev = test_c(&m, _("cylinders"));  
  if (!m)  
1014   return 0;   return 0;
1015    
1016   printf("%s%s.\n"   printf("Unknown value(s) for:");
1017     if (!g_heads)
1018     printf(" heads");
1019     if (!g_sectors)
1020     printf(" sectors");
1021     if (!g_cylinders)
1022     printf(" cylinders");
1023     printf(
1024  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
1025   "You can do this from the extra functions menu.\n"   " (settable in the extra functions menu)"
1026  #endif  #endif
1027   , prev ? _(" and ") : " ", m);   "\n");
   
1028   return 1;   return 1;
1029  }  }
1030    
1031  static void update_units(void)  static void
1032    update_units(void)
1033  {  {
1034   int cyl_units = heads * sectors;   int cyl_units = g_heads * g_sectors;
1035    
1036   if (display_in_cyl_units && cyl_units)   if (display_in_cyl_units && cyl_units)
1037   units_per_sector = cyl_units;   units_per_sector = cyl_units;
# Line 1021  static void update_units(void) Line 1043  static void update_units(void)
1043  static void  static void
1044  warn_cylinders(void)  warn_cylinders(void)
1045  {  {
1046   if (LABEL_IS_DOS && cylinders > 1024 && !nowarn)   if (LABEL_IS_DOS && g_cylinders > 1024 && !nowarn)
1047   printf(_("\n"   printf("\n"
1048  "The number of cylinders for this disk is set to %d.\n"  "The number of cylinders for this disk is set to %d.\n"
1049  "There is nothing wrong with that, but this is larger than 1024,\n"  "There is nothing wrong with that, but this is larger than 1024,\n"
1050  "and could in certain setups cause problems with:\n"  "and could in certain setups cause problems with:\n"
1051  "1) software that runs at boot time (e.g., old versions of LILO)\n"  "1) software that runs at boot time (e.g., old versions of LILO)\n"
1052  "2) booting and partitioning software from other OSs\n"  "2) booting and partitioning software from other OSs\n"
1053  "   (e.g., DOS FDISK, OS/2 FDISK)\n"),  "   (e.g., DOS FDISK, OS/2 FDISK)\n",
1054   cylinders);   g_cylinders);
1055  }  }
1056  #endif  #endif
1057    
# Line 1046  read_extended(int ext) Line 1068  read_extended(int ext)
1068    
1069   p = pex->part_table;   p = pex->part_table;
1070   if (!get_start_sect(p)) {   if (!get_start_sect(p)) {
1071   printf(_("Bad offset in primary extended partition\n"));   printf("Bad offset in primary extended partition\n");
1072   return;   return;
1073   }   }
1074    
1075   while (IS_EXTENDED(p->sys_ind)) {   while (IS_EXTENDED(p->sys_ind)) {
1076   struct pte *pe = &ptes[partitions];   struct pte *pe = &ptes[g_partitions];
1077    
1078   if (partitions >= MAXIMUM_PARTS) {   if (g_partitions >= MAXIMUM_PARTS) {
1079   /* This is not a Linux restriction, but   /* This is not a Linux restriction, but
1080     this program uses arrays of size MAXIMUM_PARTS.     this program uses arrays of size MAXIMUM_PARTS.
1081     Do not try to 'improve' this test. */     Do not try to 'improve' this test. */
1082   struct pte *pre = &ptes[partitions-1];   struct pte *pre = &ptes[g_partitions - 1];
1083  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
1084   printf(_("Warning: deleting partitions after %d\n"),   printf("Warning: deleting partitions after %d\n",
1085   partitions);   g_partitions);
1086   pre->changed = 1;   pre->changed = 1;
1087  #endif  #endif
1088   clear_partition(pre->ext_pointer);   clear_partition(pre->ext_pointer);
# Line 1076  read_extended(int ext) Line 1098  read_extended(int ext)
1098   for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {   for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
1099   if (IS_EXTENDED(p->sys_ind)) {   if (IS_EXTENDED(p->sys_ind)) {
1100   if (pe->ext_pointer)   if (pe->ext_pointer)
1101   printf(_("Warning: extra link "   printf("Warning: extra link "
1102   "pointer in partition table"   "pointer in partition table"
1103   " %d\n"), partitions + 1);   " %d\n", g_partitions + 1);
1104   else   else
1105   pe->ext_pointer = p;   pe->ext_pointer = p;
1106   } else if (p->sys_ind) {   } else if (p->sys_ind) {
1107   if (pe->part_table)   if (pe->part_table)
1108   printf(_("Warning: ignoring extra "   printf("Warning: ignoring extra "
1109    "data in partition table"    "data in partition table"
1110    " %d\n"), partitions + 1);    " %d\n", g_partitions + 1);
1111   else   else
1112   pe->part_table = p;   pe->part_table = p;
1113   }   }
# Line 1106  read_extended(int ext) Line 1128  read_extended(int ext)
1128   }   }
1129    
1130   p = pe->ext_pointer;   p = pe->ext_pointer;
1131   partitions++;   g_partitions++;
1132   }   }
1133    
1134  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
1135   /* remove empty links */   /* remove empty links */
1136   remove:   remove:
1137   for (i = 4; i < partitions; i++) {   for (i = 4; i < g_partitions; i++) {
1138   struct pte *pe = &ptes[i];   struct pte *pe = &ptes[i];
1139    
1140   if (!get_nr_sects(pe->part_table) &&   if (!get_nr_sects(pe->part_table)
1141   (partitions > 5 || ptes[4].part_table->sys_ind)) {   && (g_partitions > 5 || ptes[4].part_table->sys_ind)
1142   printf("omitting empty partition (%d)\n", i+1);   ) {
1143     printf("Omitting empty partition (%d)\n", i+1);
1144   delete_partition(i);   delete_partition(i);
1145   goto remove;    /* numbering changed */   goto remove;    /* numbering changed */
1146   }   }
# Line 1131  create_doslabel(void) Line 1154  create_doslabel(void)
1154  {  {
1155   int i;   int i;
1156    
1157   printf(   printf(msg_building_new_label, "DOS disklabel");
  _("Building a new DOS disklabel. Changes will remain in memory only,\n"  
   "until you decide to write them. After that, of course, the previous\n"  
   "content won't be recoverable.\n\n"));  
1158    
1159   current_label_type = label_dos;   current_label_type = LABEL_DOS;
1160    
1161  #if ENABLE_FEATURE_OSF_LABEL  #if ENABLE_FEATURE_OSF_LABEL
1162   possibly_osf_label = 0;   possibly_osf_label = 0;
1163  #endif  #endif
1164   partitions = 4;   g_partitions = 4;
1165    
1166   for (i = 510-64; i < 510; i++)   for (i = 510-64; i < 510; i++)
1167   MBRbuffer[i] = 0;   MBRbuffer[i] = 0;
# Line 1149  create_doslabel(void) Line 1169  create_doslabel(void)
1169   extended_offset = 0;   extended_offset = 0;
1170   set_all_unchanged();   set_all_unchanged();
1171   set_changed(0);   set_changed(0);
1172   get_boot(create_empty_dos);   get_boot(CREATE_EMPTY_DOS);
1173  }  }
1174  #endif /* FEATURE_FDISK_WRITABLE */  #endif /* FEATURE_FDISK_WRITABLE */
1175    
# Line 1158  get_sectorsize(void) Line 1178  get_sectorsize(void)
1178  {  {
1179   if (!user_set_sector_size) {   if (!user_set_sector_size) {
1180   int arg;   int arg;
1181   if (ioctl(fd, BLKSSZGET, &arg) == 0)   if (ioctl(dev_fd, BLKSSZGET, &arg) == 0)
1182   sector_size = arg;   sector_size = arg;
1183   if (sector_size != DEFAULT_SECTOR_SIZE)   if (sector_size != DEFAULT_SECTOR_SIZE)
1184   printf(_("Note: sector size is %d (not %d)\n"),   printf("Note: sector size is %d "
1185     sector_size, DEFAULT_SECTOR_SIZE);   "(not " DEFAULT_SECTOR_SIZE_STR ")\n",
1186     sector_size);
1187   }   }
1188  }  }
1189    
# Line 1171  get_kernel_geometry(void) Line 1192  get_kernel_geometry(void)
1192  {  {
1193   struct hd_geometry geometry;   struct hd_geometry geometry;
1194    
1195   if (!ioctl(fd, HDIO_GETGEO, &geometry)) {   if (!ioctl(dev_fd, HDIO_GETGEO, &geometry)) {
1196   kern_heads = geometry.heads;   kern_heads = geometry.heads;
1197   kern_sectors = geometry.sectors;   kern_sectors = geometry.sectors;
1198   /* never use geometry.cylinders - it is truncated */   /* never use geometry.cylinders - it is truncated */
# Line 1215  static void Line 1236  static void
1236  get_geometry(void)  get_geometry(void)
1237  {  {
1238   int sec_fac;   int sec_fac;
  unsigned long long bytes;       /* really u64 */  
1239    
1240   get_sectorsize();   get_sectorsize();
1241   sec_fac = sector_size / 512;   sec_fac = sector_size / 512;
1242  #if ENABLE_FEATURE_SUN_LABEL  #if ENABLE_FEATURE_SUN_LABEL
1243   guess_device_type();   guess_device_type();
1244  #endif  #endif
1245   heads = cylinders = sectors = 0;   g_heads = g_cylinders = g_sectors = 0;
1246   kern_heads = kern_sectors = 0;   kern_heads = kern_sectors = 0;
1247   pt_heads = pt_sectors = 0;   pt_heads = pt_sectors = 0;
1248    
1249   get_kernel_geometry();   get_kernel_geometry();
1250   get_partition_table_geometry();   get_partition_table_geometry();
1251    
1252   heads = user_heads ? user_heads :   g_heads = user_heads ? user_heads :
1253   pt_heads ? pt_heads :   pt_heads ? pt_heads :
1254   kern_heads ? kern_heads : 255;   kern_heads ? kern_heads : 255;
1255   sectors = user_sectors ? user_sectors :   g_sectors = user_sectors ? user_sectors :
1256   pt_sectors ? pt_sectors :   pt_sectors ? pt_sectors :
1257   kern_sectors ? kern_sectors : 63;   kern_sectors ? kern_sectors : 63;
1258   if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {   total_number_of_sectors = bb_BLKGETSIZE_sectors(dev_fd);
  /* got bytes */  
  } else {  
  unsigned long longsectors;  
   
  if (ioctl(fd, BLKGETSIZE, &longsectors))  
  longsectors = 0;  
  bytes = ((unsigned long long) longsectors) << 9;  
  }  
   
  total_number_of_sectors = (bytes >> 9);  
1259    
1260   sector_offset = 1;   sector_offset = 1;
1261   if (dos_compatible_flag)   if (dos_compatible_flag)
1262   sector_offset = sectors;   sector_offset = g_sectors;
1263    
1264   cylinders = total_number_of_sectors / (heads * sectors * sec_fac);   g_cylinders = total_number_of_sectors / (g_heads * g_sectors * sec_fac);
1265   if (!cylinders)   if (!g_cylinders)
1266   cylinders = user_cylinders;   g_cylinders = user_cylinders;
1267  }  }
1268    
1269  /*  /*
1270   * Read MBR.  Returns:   * Opens disk_device and optionally reads MBR.
1271     *    FIXME: document what each 'what' value will do!
1272     * Returns:
1273   *   -1: no 0xaa55 flag present (possibly entire disk BSD)   *   -1: no 0xaa55 flag present (possibly entire disk BSD)
1274   *    0: found or created label   *    0: found or created label
1275   *    1: I/O error   *    1: I/O error
1276   */   */
1277  static int  #if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE
1278  get_boot(enum action what)  static int get_boot(enum action what)
1279    #else
1280    static int get_boot(void)
1281    #define get_boot(what) get_boot()
1282    #endif
1283  {  {
1284   int i;   int i, fd;
   
  partitions = 4;  
1285    
1286     g_partitions = 4;
1287   for (i = 0; i < 4; i++) {   for (i = 0; i < 4; i++) {
1288   struct pte *pe = &ptes[i];   struct pte *pe = &ptes[i];
   
1289   pe->part_table = pt_offset(MBRbuffer, i);   pe->part_table = pt_offset(MBRbuffer, i);
1290   pe->ext_pointer = NULL;   pe->ext_pointer = NULL;
1291   pe->offset = 0;   pe->offset = 0;
1292   pe->sectorbuffer = MBRbuffer;   pe->sectorbuffer = MBRbuffer;
1293  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
1294   pe->changed = (what == create_empty_dos);   pe->changed = (what == CREATE_EMPTY_DOS);
1295  #endif  #endif
1296   }   }
1297    
 #if ENABLE_FEATURE_SUN_LABEL  
  if (what == create_empty_sun && check_sun_label())  
  return 0;  
 #endif  
   
  memset(MBRbuffer, 0, 512);  
   
1298  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
1299   if (what == create_empty_dos)  // ALERT! highly idiotic design!
1300   goto got_dos_table;             /* skip reading disk */  // We end up here when we call get_boot() recursively
1301    // via get_boot() [table is bad] -> create_doslabel() -> get_boot(CREATE_EMPTY_DOS).
1302    // or get_boot() [table is bad] -> create_sunlabel() -> get_boot(CREATE_EMPTY_SUN).
1303    // (just factor out re-init of ptes[0,1,2,3] in a separate fn instead?)
1304    // So skip opening device _again_...
1305     if (what == CREATE_EMPTY_DOS  USE_FEATURE_SUN_LABEL(|| what == CREATE_EMPTY_SUN))
1306     goto created_table;
1307    
1308     fd = open(disk_device, (option_mask32 & OPT_l) ? O_RDONLY : O_RDWR);
1309    
1310   if ((fd = open(disk_device, type_open)) < 0) {   if (fd < 0) {
1311   if ((fd = open(disk_device, O_RDONLY)) < 0) {   fd = open(disk_device, O_RDONLY);
1312   if (what == try_only)   if (fd < 0) {
1313     if (what == TRY_ONLY)
1314   return 1;   return 1;
1315   fdisk_fatal(unable_to_open);   fdisk_fatal(unable_to_open);
1316   } else   }
1317   printf(_("You will not be able to write "   printf("'%s' is opened for read only\n", disk_device);
  "the partition table.\n"));  
1318   }   }
1319     xmove_fd(fd, dev_fd);
1320   if (512 != read(fd, MBRbuffer, 512)) {   if (512 != full_read(dev_fd, MBRbuffer, 512)) {
1321   if (what == try_only)   if (what == TRY_ONLY) {
1322     close_dev_fd();
1323   return 1;   return 1;
1324     }
1325   fdisk_fatal(unable_to_read);   fdisk_fatal(unable_to_read);
1326   }   }
1327  #else  #else
1328   if ((fd = open(disk_device, O_RDONLY)) < 0)   fd = open(disk_device, O_RDONLY);
1329     if (fd < 0)
1330   return 1;   return 1;
1331   if (512 != read(fd, MBRbuffer, 512))   if (512 != full_read(fd, MBRbuffer, 512)) {
1332     close(fd);
1333   return 1;   return 1;
1334     }
1335     xmove_fd(fd, dev_fd);
1336  #endif  #endif
1337    
1338   get_geometry();   get_geometry();
   
1339   update_units();   update_units();
1340    
1341  #if ENABLE_FEATURE_SUN_LABEL  #if ENABLE_FEATURE_SUN_LABEL
1342   if (check_sun_label())   if (check_sun_label())
1343   return 0;   return 0;
1344  #endif  #endif
   
1345  #if ENABLE_FEATURE_SGI_LABEL  #if ENABLE_FEATURE_SGI_LABEL
1346   if (check_sgi_label())   if (check_sgi_label())
1347   return 0;   return 0;
1348  #endif  #endif
   
1349  #if ENABLE_FEATURE_AIX_LABEL  #if ENABLE_FEATURE_AIX_LABEL
1350   if (check_aix_label())   if (check_aix_label())
1351   return 0;   return 0;
1352  #endif  #endif
   
1353  #if ENABLE_FEATURE_OSF_LABEL  #if ENABLE_FEATURE_OSF_LABEL
1354   if (check_osf_label()) {   if (check_osf_label()) {
1355   possibly_osf_label = 1;   possibly_osf_label = 1;
1356   if (!valid_part_table_flag(MBRbuffer)) {   if (!valid_part_table_flag(MBRbuffer)) {
1357   current_label_type = label_osf;   current_label_type = LABEL_OSF;
1358   return 0;   return 0;
1359   }   }
1360   printf(_("This disk has both DOS and BSD magic.\n"   printf("This disk has both DOS and BSD magic.\n"
1361   "Give the 'b' command to go to BSD mode.\n"));   "Give the 'b' command to go to BSD mode.\n");
1362   }   }
1363  #endif  #endif
1364    
 #if ENABLE_FEATURE_FDISK_WRITABLE  
  got_dos_table:  
 #endif  
   
  if (!valid_part_table_flag(MBRbuffer)) {  
1365  #if !ENABLE_FEATURE_FDISK_WRITABLE  #if !ENABLE_FEATURE_FDISK_WRITABLE
1366     if (!valid_part_table_flag(MBRbuffer))
1367   return -1;   return -1;
1368  #else  #else
1369   switch (what) {   if (!valid_part_table_flag(MBRbuffer)) {
1370   case fdisk:   if (what == OPEN_MAIN) {
1371   printf(_("Device contains neither a valid DOS "   printf("Device contains neither a valid DOS "
1372    "partition table, nor Sun, SGI or OSF "    "partition table, nor Sun, SGI or OSF "
1373    "disklabel\n"));    "disklabel\n");
1374  #ifdef __sparc__  #ifdef __sparc__
1375  #if ENABLE_FEATURE_SUN_LABEL   USE_FEATURE_SUN_LABEL(create_sunlabel();)
  create_sunlabel();  
 #endif  
1376  #else  #else
1377   create_doslabel();   create_doslabel();
1378  #endif  #endif
1379   return 0;   return 0;
  case try_only:  
  return -1;  
  case create_empty_dos:  
 #if ENABLE_FEATURE_SUN_LABEL  
  case create_empty_sun:  
 #endif  
  break;  
  default:  
  bb_error_msg_and_die(_("internal error"));  
1380   }   }
1381  #endif /* FEATURE_FDISK_WRITABLE */   /* TRY_ONLY: */
1382     return -1;
1383   }   }
1384     created_table:
1385    #endif /* FEATURE_FDISK_WRITABLE */
1386    
1387  #if ENABLE_FEATURE_FDISK_WRITABLE  
1388   warn_cylinders();   USE_FEATURE_FDISK_WRITABLE(warn_cylinders();)
 #endif  
1389   warn_geometry();   warn_geometry();
1390    
1391   for (i = 0; i < 4; i++) {   for (i = 0; i < 4; i++) {
1392   struct pte *pe = &ptes[i];   if (IS_EXTENDED(ptes[i].part_table->sys_ind)) {
1393     if (g_partitions != 4)
1394   if (IS_EXTENDED(pe->part_table->sys_ind)) {   printf("Ignoring extra extended "
1395   if (partitions != 4)   "partition %d\n", i + 1);
  printf(_("Ignoring extra extended "  
  "partition %d\n"), i + 1);  
1396   else   else
1397   read_extended(i);   read_extended(i);
1398   }   }
1399   }   }
1400    
1401   for (i = 3; i < partitions; i++) {   for (i = 3; i < g_partitions; i++) {
1402   struct pte *pe = &ptes[i];   struct pte *pe = &ptes[i];
   
1403   if (!valid_part_table_flag(pe->sectorbuffer)) {   if (!valid_part_table_flag(pe->sectorbuffer)) {
1404   printf(_("Warning: invalid flag 0x%02x,0x%02x of partition "   printf("Warning: invalid flag 0x%02x,0x%02x of partition "
1405   "table %d will be corrected by w(rite)\n"),   "table %d will be corrected by w(rite)\n",
1406   pe->sectorbuffer[510],   pe->sectorbuffer[510],
1407   pe->sectorbuffer[511],   pe->sectorbuffer[511],
1408   i + 1);   i + 1);
1409  #if ENABLE_FEATURE_FDISK_WRITABLE   USE_FEATURE_FDISK_WRITABLE(pe->changed = 1;)
  pe->changed = 1;  
 #endif  
1410   }   }
1411   }   }
1412    
# Line 1423  get_boot(enum action what) Line 1422  get_boot(enum action what)
1422   * There is no default if DFLT is not between LOW and HIGH.   * There is no default if DFLT is not between LOW and HIGH.
1423   */   */
1424  static unsigned  static unsigned
1425  read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, char *mesg)  read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg)
1426  {  {
1427   unsigned i;   unsigned i;
1428   int default_ok = 1;   int default_ok = 1;
# Line 1457  read_int(unsigned low, unsigned dflt, un Line 1456  read_int(unsigned low, unsigned dflt, un
1456   case 'c':   case 'c':
1457   case 'C':   case 'C':
1458   if (!display_in_cyl_units)   if (!display_in_cyl_units)
1459   i *= heads * sectors;   i *= g_heads * g_sectors;
1460   break;   break;
1461   case 'K':   case 'K':
1462   absolute = 1024;   absolute = 1024;
# Line 1477  read_int(unsigned low, unsigned dflt, un Line 1476  read_int(unsigned low, unsigned dflt, un
1476   break;   break;
1477   }   }
1478   if (absolute) {   if (absolute) {
1479   unsigned long long bytes;   ullong bytes;
1480   unsigned long unit;   unsigned long unit;
1481    
1482   bytes = (unsigned long long) i * absolute;   bytes = (ullong) i * absolute;
1483   unit = sector_size * units_per_sector;   unit = sector_size * units_per_sector;
1484   bytes += unit/2; /* round */   bytes += unit/2; /* round */
1485   bytes /= unit;   bytes /= unit;
# Line 1496  read_int(unsigned low, unsigned dflt, un Line 1495  read_int(unsigned low, unsigned dflt, un
1495   use_default = 0;   use_default = 0;
1496   }   }
1497   }   }
1498   if (use_default)   if (use_default) {
1499   printf(_("Using default value %u\n"), i = dflt);   i = dflt;
1500     printf("Using default value %u\n", i);
1501     }
1502   if (i >= low && i <= high)   if (i >= low && i <= high)
1503   break;   break;
1504   else   printf("Value is out of range\n");
  printf(_("Value is out of range\n"));  
1505   }   }
1506   return i;   return i;
1507  }  }
# Line 1512  get_partition(int warn, int max) Line 1512  get_partition(int warn, int max)
1512   struct pte *pe;   struct pte *pe;
1513   int i;   int i;
1514    
1515   i = read_int(1, 0, max, 0, _("Partition number")) - 1;   i = read_int(1, 0, max, 0, "Partition number") - 1;
1516   pe = &ptes[i];   pe = &ptes[i];
1517    
1518   if (warn) {   if (warn) {
# Line 1520  get_partition(int warn, int max) Line 1520  get_partition(int warn, int max)
1520   || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))   || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
1521   || (LABEL_IS_SGI && !sgi_get_num_sectors(i))   || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
1522   ) {   ) {
1523   printf(_("Warning: partition %d has empty type\n"), i+1);   printf("Warning: partition %d has empty type\n", i+1);
1524   }   }
1525   }   }
1526   return i;   return i;
# Line 1543  get_existing_partition(int warn, int max Line 1543  get_existing_partition(int warn, int max
1543   }   }
1544   }   }
1545   if (pno >= 0) {   if (pno >= 0) {
1546   printf(_("Selected partition %d\n"), pno+1);   printf("Selected partition %d\n", pno+1);
1547   return pno;   return pno;
1548   }   }
1549   printf(_("No partition is defined yet!\n"));   printf("No partition is defined yet!\n");
1550   return -1;   return -1;
1551    
1552   not_unique:   not_unique:
# Line 1570  get_nonexisting_partition(int warn, int Line 1570  get_nonexisting_partition(int warn, int
1570   }   }
1571   }   }
1572   if (pno >= 0) {   if (pno >= 0) {
1573   printf(_("Selected partition %d\n"), pno+1);   printf("Selected partition %d\n", pno+1);
1574   return pno;   return pno;
1575   }   }
1576   printf(_("All primary partitions have been defined already!\n"));   printf("All primary partitions have been defined already!\n");
1577   return -1;   return -1;
1578    
1579   not_unique:   not_unique:
# Line 1586  change_units(void) Line 1586  change_units(void)
1586  {  {
1587   display_in_cyl_units = !display_in_cyl_units;   display_in_cyl_units = !display_in_cyl_units;
1588   update_units();   update_units();
1589   printf(_("Changing display/entry units to %s\n"),   printf("Changing display/entry units to %s\n",
1590   str_units(PLURAL));   str_units(PLURAL));
1591  }  }
1592    
# Line 1597  toggle_active(int i) Line 1597  toggle_active(int i)
1597   struct partition *p = pe->part_table;   struct partition *p = pe->part_table;
1598    
1599   if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)   if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
1600   printf(_("WARNING: Partition %d is an extended partition\n"), i + 1);   printf("WARNING: Partition %d is an extended partition\n", i + 1);
1601   p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);   p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1602   pe->changed = 1;   pe->changed = 1;
1603  }  }
# Line 1605  toggle_active(int i) Line 1605  toggle_active(int i)
1605  static void  static void
1606  toggle_dos_compatibility_flag(void)  toggle_dos_compatibility_flag(void)
1607  {  {
1608   dos_compatible_flag = ~dos_compatible_flag;   dos_compatible_flag = 1 - dos_compatible_flag;
1609   if (dos_compatible_flag) {   if (dos_compatible_flag) {
1610   sector_offset = sectors;   sector_offset = g_sectors;
1611   printf(_("DOS Compatibility flag is set\n"));   printf("DOS Compatibility flag is set\n");
1612   }   } else {
  else {  
1613   sector_offset = 1;   sector_offset = 1;
1614   printf(_("DOS Compatibility flag is not set\n"));   printf("DOS Compatibility flag is not set\n");
1615   }   }
1616  }  }
1617    
# Line 1642  delete_partition(int i) Line 1641  delete_partition(int i)
1641    
1642   if (i < 4) {   if (i < 4) {
1643   if (IS_EXTENDED(p->sys_ind) && i == ext_index) {   if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
1644   partitions = 4;   g_partitions = 4;
1645   ptes[ext_index].ext_pointer = NULL;   ptes[ext_index].ext_pointer = NULL;
1646   extended_offset = 0;   extended_offset = 0;
1647   }   }
# Line 1652  delete_partition(int i) Line 1651  delete_partition(int i)
1651    
1652   if (!q->sys_ind && i > 4) {   if (!q->sys_ind && i > 4) {
1653   /* the last one in the chain - just delete */   /* the last one in the chain - just delete */
1654   --partitions;   --g_partitions;
1655   --i;   --i;
1656   clear_partition(ptes[i].ext_pointer);   clear_partition(ptes[i].ext_pointer);
1657   ptes[i].changed = 1;   ptes[i].changed = 1;
# Line 1665  delete_partition(int i) Line 1664  delete_partition(int i)
1664   set_start_sect(p, get_start_sect(q));   set_start_sect(p, get_start_sect(q));
1665   set_nr_sects(p, get_nr_sects(q));   set_nr_sects(p, get_nr_sects(q));
1666   ptes[i-1].changed = 1;   ptes[i-1].changed = 1;
1667   } else if (partitions > 5) {    /* 5 will be moved to 4 */   } else if (g_partitions > 5) {    /* 5 will be moved to 4 */
1668   /* the first logical in a longer chain */   /* the first logical in a longer chain */
1669   pe = &ptes[5];   pe = &ptes[5];
1670    
# Line 1677  delete_partition(int i) Line 1676  delete_partition(int i)
1676   pe->changed = 1;   pe->changed = 1;
1677   }   }
1678    
1679   if (partitions > 5) {   if (g_partitions > 5) {
1680   partitions--;   g_partitions--;
1681   while (i < partitions) {   while (i < g_partitions) {
1682   ptes[i] = ptes[i+1];   ptes[i] = ptes[i+1];
1683   i++;   i++;
1684   }   }
# Line 1699  change_sysid(void) Line 1698  change_sysid(void)
1698     let the user select a partition, since get_existing_partition()     let the user select a partition, since get_existing_partition()
1699     only works for Linux like partition tables. */     only works for Linux like partition tables. */
1700   if (!LABEL_IS_SGI) {   if (!LABEL_IS_SGI) {
1701   i = get_existing_partition(0, partitions);   i = get_existing_partition(0, g_partitions);
1702   } else {   } else {
1703   i = get_partition(0, partitions);   i = get_partition(0, g_partitions);
1704   }   }
1705   if (i == -1)   if (i == -1)
1706   return;   return;
# Line 1711  change_sysid(void) Line 1710  change_sysid(void)
1710   /* if changing types T to 0 is allowed, then   /* if changing types T to 0 is allowed, then
1711     the reverse change must be allowed, too */     the reverse change must be allowed, too */
1712   if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {   if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
1713   printf(_("Partition %d does not exist yet!\n"), i + 1);   printf("Partition %d does not exist yet!\n", i + 1);
1714   return;   return;
1715   }   }
1716   while (1) {   while (1) {
1717   sys = read_hex (get_sys_types());   sys = read_hex(get_sys_types());
1718    
1719   if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {   if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
1720   printf(_("Type 0 means free space to many systems\n"   printf("Type 0 means free space to many systems\n"
1721     "(but not to Linux). Having partitions of\n"     "(but not to Linux). Having partitions of\n"
1722     "type 0 is probably unwise. You can delete\n"     "type 0 is probably unwise.\n");
    "a partition using the 'd' command.\n"));  
1723   /* break; */   /* break; */
1724   }   }
1725    
1726   if (!LABEL_IS_SUN && !LABEL_IS_SGI) {   if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
1727   if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {   if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
1728   printf(_("You cannot change a partition into"   printf("You cannot change a partition into"
1729     " an extended one or vice versa\n"     " an extended one or vice versa\n");
    "Delete it first.\n"));  
1730   break;   break;
1731   }   }
1732   }   }
1733    
1734   if (sys < 256) {   if (sys < 256) {
1735    #if ENABLE_FEATURE_SUN_LABEL
1736   if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)   if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
1737   printf(_("Consider leaving partition 3 "   printf("Consider leaving partition 3 "
1738     "as Whole disk (5),\n"     "as Whole disk (5),\n"
1739     "as SunOS/Solaris expects it and "     "as SunOS/Solaris expects it and "
1740     "even Linux likes it.\n\n"));     "even Linux likes it\n\n");
1741    #endif
1742    #if ENABLE_FEATURE_SGI_LABEL
1743   if (LABEL_IS_SGI &&   if (LABEL_IS_SGI &&
1744   (   (
1745   (i == 10 && sys != SGI_ENTIRE_DISK) ||   (i == 10 && sys != SGI_ENTIRE_DISK) ||
1746   (i == 8 && sys != 0)   (i == 8 && sys != 0)
1747   )   )
1748   ){   ) {
1749   printf(_("Consider leaving partition 9 "   printf("Consider leaving partition 9 "
1750     "as volume header (0),\nand "     "as volume header (0),\nand "
1751     "partition 11 as entire volume (6)"     "partition 11 as entire volume (6)"
1752     "as IRIX expects it.\n\n"));     "as IRIX expects it\n\n");
1753   }   }
1754    #endif
1755   if (sys == origsys)   if (sys == origsys)
1756   break;   break;
1757   if (LABEL_IS_SUN) {   if (LABEL_IS_SUN) {
# Line 1760  change_sysid(void) Line 1761  change_sysid(void)
1761   } else   } else
1762   p->sys_ind = sys;   p->sys_ind = sys;
1763    
1764   printf(_("Changed system type of partition %d "   printf("Changed system type of partition %d "
1765   "to %x (%s)\n"), i + 1, sys,   "to %x (%s)\n", i + 1, sys,
1766   partition_type(sys));   partition_type(sys));
1767   ptes[i].changed = 1;   ptes[i].changed = 1;
1768   if (is_dos_partition(origsys) ||   //if (is_dos_partition(origsys) || is_dos_partition(sys))
1769   is_dos_partition(sys))   // dos_changed = 1;
  dos_changed = 1;  
1770   break;   break;
1771   }   }
1772   }   }
# Line 1782  change_sysid(void) Line 1782  change_sysid(void)
1782  static void  static void
1783  linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)  linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
1784  {  {
1785   int spc = heads * sectors;   int spc = g_heads * g_sectors;
1786    
1787   *c = ls / spc;   *c = ls / spc;
1788   ls = ls % spc;   ls = ls % spc;
1789   *h = ls / sectors;   *h = ls / g_sectors;
1790   *s = ls % sectors + 1;  /* sectors count from 1 */   *s = ls % g_sectors + 1;  /* sectors count from 1 */
1791  }  }
1792    
1793  static void  static void
# Line 1798  check_consistency(const struct partition Line 1798  check_consistency(const struct partition
1798   unsigned lbc, lbh, lbs;          /* logical beginning c, h, s */   unsigned lbc, lbh, lbs;          /* logical beginning c, h, s */
1799   unsigned lec, leh, les;          /* logical ending c, h, s */   unsigned lec, leh, les;          /* logical ending c, h, s */
1800    
1801   if (!heads || !sectors || (partition >= 4))   if (!g_heads || !g_sectors || (partition >= 4))
1802   return;         /* do not check extended partitions */   return;         /* do not check extended partitions */
1803    
1804  /* physical beginning c, h, s */  /* physical beginning c, h, s */
# Line 1818  check_consistency(const struct partition Line 1818  check_consistency(const struct partition
1818   linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);   linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
1819    
1820  /* Same physical / logical beginning? */  /* Same physical / logical beginning? */
1821   if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {   if (g_cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
1822   printf(_("Partition %d has different physical/logical "   printf("Partition %d has different physical/logical "
1823   "beginnings (non-Linux?):\n"), partition + 1);   "beginnings (non-Linux?):\n", partition + 1);
1824   printf(_("     phys=(%d, %d, %d) "), pbc, pbh, pbs);   printf("     phys=(%d, %d, %d) ", pbc, pbh, pbs);
1825   printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);   printf("logical=(%d, %d, %d)\n", lbc, lbh, lbs);
1826   }   }
1827    
1828  /* Same physical / logical ending? */  /* Same physical / logical ending? */
1829   if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {   if (g_cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
1830   printf(_("Partition %d has different physical/logical "   printf("Partition %d has different physical/logical "
1831   "endings:\n"), partition + 1);   "endings:\n", partition + 1);
1832   printf(_("     phys=(%d, %d, %d) "), pec, peh, pes);   printf("     phys=(%d, %d, %d) ", pec, peh, pes);
1833   printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);   printf("logical=(%d, %d, %d)\n", lec, leh, les);
1834   }   }
1835    
1836  /* Ending on cylinder boundary? */  /* Ending on cylinder boundary? */
1837   if (peh != (heads - 1) || pes != sectors) {   if (peh != (g_heads - 1) || pes != g_sectors) {
1838   printf(_("Partition %i does not end on cylinder boundary.\n"),   printf("Partition %i does not end on cylinder boundary\n",
1839   partition + 1);   partition + 1);
1840   }   }
1841  }  }
# Line 1847  list_disk_geometry(void) Line 1847  list_disk_geometry(void)
1847   long megabytes = bytes/1000000;   long megabytes = bytes/1000000;
1848    
1849   if (megabytes < 10000)   if (megabytes < 10000)
1850   printf(_("\nDisk %s: %ld MB, %lld bytes\n"),   printf("\nDisk %s: %ld MB, %lld bytes\n",
1851     disk_device, megabytes, bytes);     disk_device, megabytes, bytes);
1852   else   else
1853   printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),   printf("\nDisk %s: %ld.%ld GB, %lld bytes\n",
1854     disk_device, megabytes/1000, (megabytes/100)%10, bytes);     disk_device, megabytes/1000, (megabytes/100)%10, bytes);
1855   printf(_("%d heads, %d sectors/track, %d cylinders"),   printf("%d heads, %d sectors/track, %d cylinders",
1856     heads, sectors, cylinders);     g_heads, g_sectors, g_cylinders);
1857   if (units_per_sector == 1)   if (units_per_sector == 1)
1858   printf(_(", total %llu sectors"),   printf(", total %llu sectors",
1859     total_number_of_sectors / (sector_size/512));     total_number_of_sectors / (sector_size/512));
1860   printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),   printf("\nUnits = %s of %d * %d = %d bytes\n\n",
1861     str_units(PLURAL),     str_units(PLURAL),
1862     units_per_sector, sector_size, units_per_sector * sector_size);     units_per_sector, sector_size, units_per_sector * sector_size);
1863  }  }
# Line 1872  wrong_p_order(int *prev) Line 1872  wrong_p_order(int *prev)
1872  {  {
1873   const struct pte *pe;   const struct pte *pe;
1874   const struct partition *p;   const struct partition *p;
1875   off_t last_p_start_pos = 0, p_start_pos;   ullong last_p_start_pos = 0, p_start_pos;
1876   int i, last_i = 0;   int i, last_i = 0;
1877    
1878   for (i = 0 ; i < partitions; i++) {   for (i = 0; i < g_partitions; i++) {
1879   if (i == 4) {   if (i == 4) {
1880   last_i = 4;   last_i = 4;
1881   last_p_start_pos = 0;   last_p_start_pos = 0;
1882   }   }
1883   pe = &ptes[i];   pe = &ptes[i];
1884   if ((p = pe->part_table)->sys_ind) {   p = pe->part_table;
1885     if (p->sys_ind) {
1886   p_start_pos = get_partition_start(pe);   p_start_pos = get_partition_start(pe);
1887    
1888   if (last_p_start_pos > p_start_pos) {   if (last_p_start_pos > p_start_pos) {
# Line 1920  fix_chain_of_logicals(void) Line 1921  fix_chain_of_logicals(void)
1921   /* Stage 1: sort sectors but leave sector of part 4 */   /* Stage 1: sort sectors but leave sector of part 4 */
1922   /* (Its sector is the global extended_offset.) */   /* (Its sector is the global extended_offset.) */
1923   stage1:   stage1:
1924   for (j = 5; j < partitions-1; j++) {   for (j = 5; j < g_partitions - 1; j++) {
1925   oj = ptes[j].offset;   oj = ptes[j].offset;
1926   ojj = ptes[j+1].offset;   ojj = ptes[j+1].offset;
1927   if (oj > ojj) {   if (oj > ojj) {
# Line 1940  fix_chain_of_logicals(void) Line 1941  fix_chain_of_logicals(void)
1941    
1942   /* Stage 2: sort starting sectors */   /* Stage 2: sort starting sectors */
1943   stage2:   stage2:
1944   for (j = 4; j < partitions-1; j++) {   for (j = 4; j < g_partitions - 1; j++) {
1945   pj = ptes[j].part_table;   pj = ptes[j].part_table;
1946   pjj = ptes[j+1].part_table;   pjj = ptes[j+1].part_table;
1947   sj = get_start_sect(pj);   sj = get_start_sect(pj);
# Line 1958  fix_chain_of_logicals(void) Line 1959  fix_chain_of_logicals(void)
1959   }   }
1960    
1961   /* Probably something was changed */   /* Probably something was changed */
1962   for (j = 4; j < partitions; j++)   for (j = 4; j < g_partitions; j++)
1963   ptes[j].changed = 1;   ptes[j].changed = 1;
1964  }  }
1965    
# Line 1970  fix_partition_table_order(void) Line 1971  fix_partition_table_order(void)
1971   int i,k;   int i,k;
1972    
1973   if (!wrong_p_order(NULL)) {   if (!wrong_p_order(NULL)) {
1974   printf(_("Nothing to do. Ordering is correct already.\n\n"));   printf("Ordering is already correct\n\n");
1975   return;   return;
1976   }   }
1977    
# Line 2034  list_table(int xtra) Line 2035  list_table(int xtra)
2035   if (w < 5)   if (w < 5)
2036   w = 5;   w = 5;
2037    
2038   //              1 12345678901 12345678901 12345678901  12   //            1 12345678901 12345678901 12345678901  12
2039   printf(_("%*s Boot      Start         End      Blocks  Id System\n"),   printf("%*s Boot      Start         End      Blocks  Id System\n",
2040     w+1, _("Device"));     w+1, "Device");
2041    
2042   for (i = 0; i < partitions; i++) {   for (i = 0; i < g_partitions; i++) {
2043   const struct pte *pe = &ptes[i];   const struct pte *pe = &ptes[i];
2044   off_t psects;   ullong psects;
2045   off_t pblocks;   ullong pblocks;
2046   unsigned podd;   unsigned podd;
2047    
2048   p = pe->part_table;   p = pe->part_table;
# Line 2063  list_table(int xtra) Line 2064  list_table(int xtra)
2064   partname(disk_device, i+1, w+2),   partname(disk_device, i+1, w+2),
2065   !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */   !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
2066   ? '*' : '?',   ? '*' : '?',
2067   (unsigned long long) cround(get_partition_start(pe)),           /* start */   (ullong) cround(get_partition_start(pe)),           /* start */
2068   (unsigned long long) cround(get_partition_start(pe) + psects    /* end */   (ullong) cround(get_partition_start(pe) + psects    /* end */
2069   - (psects ? 1 : 0)),   - (psects ? 1 : 0)),
2070   (unsigned long long) pblocks, podd ? '+' : ' ', /* odd flag on end */   (ullong) pblocks, podd ? '+' : ' ', /* odd flag on end */
2071   p->sys_ind,                                     /* type id */   p->sys_ind,                                     /* type id */
2072   partition_type(p->sys_ind));                    /* type name */   partition_type(p->sys_ind));                    /* type name */
2073    
# Line 2078  list_table(int xtra) Line 2079  list_table(int xtra)
2079     is a sgi, sun or aix labeled disk... */     is a sgi, sun or aix labeled disk... */
2080   if (LABEL_IS_DOS && wrong_p_order(NULL)) {   if (LABEL_IS_DOS && wrong_p_order(NULL)) {
2081   /* FIXME */   /* FIXME */
2082   printf(_("\nPartition table entries are not in disk order\n"));   printf("\nPartition table entries are not in disk order\n");
2083   }   }
2084  }  }
2085    
# Line 2090  x_list_table(int extend) Line 2091  x_list_table(int extend)
2091   const struct partition *p;   const struct partition *p;
2092   int i;   int i;
2093    
2094   printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),   printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n",
2095   disk_device, heads, sectors, cylinders);   disk_device, g_heads, g_sectors, g_cylinders);
2096   printf(_("Nr AF  Hd Sec  Cyl  Hd Sec  Cyl      Start       Size ID\n"));   printf("Nr AF  Hd Sec  Cyl  Hd Sec  Cyl      Start       Size ID\n");
2097   for (i = 0 ; i < partitions; i++) {   for (i = 0; i < g_partitions; i++) {
2098   pe = &ptes[i];   pe = &ptes[i];
2099   p = (extend ? pe->ext_pointer : pe->part_table);   p = (extend ? pe->ext_pointer : pe->part_table);
2100   if (p != NULL) {   if (p != NULL) {
# Line 2113  x_list_table(int extend) Line 2114  x_list_table(int extend)
2114    
2115  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
2116  static void  static void
2117  fill_bounds(off_t *first, off_t *last)  fill_bounds(ullong *first, ullong *last)
2118  {  {
2119   int i;   int i;
2120   const struct pte *pe = &ptes[0];   const struct pte *pe = &ptes[0];
2121   const struct partition *p;   const struct partition *p;
2122    
2123   for (i = 0; i < partitions; pe++,i++) {   for (i = 0; i < g_partitions; pe++,i++) {
2124   p = pe->part_table;   p = pe->part_table;
2125   if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {   if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
2126   first[i] = 0xffffffff;   first[i] = 0xffffffff;
# Line 2132  fill_bounds(off_t *first, off_t *last) Line 2133  fill_bounds(off_t *first, off_t *last)
2133  }  }
2134    
2135  static void  static void
2136  check(int n, unsigned h, unsigned s, unsigned c, off_t start)  check(int n, unsigned h, unsigned s, unsigned c, ullong start)
2137  {  {
2138   off_t total, real_s, real_c;   ullong total, real_s, real_c;
2139    
2140   real_s = sector(s) - 1;   real_s = sector(s) - 1;
2141   real_c = cylinder(s, c);   real_c = cylinder(s, c);
2142   total = (real_c * sectors + real_s) * heads + h;   total = (real_c * g_sectors + real_s) * g_heads + h;
2143   if (!total)   if (!total)
2144   printf(_("Warning: partition %d contains sector 0\n"), n);   printf("Partition %d contains sector 0\n", n);
2145   if (h >= heads)   if (h >= g_heads)
2146   printf(_("Partition %d: head %d greater than maximum %d\n"),   printf("Partition %d: head %d greater than maximum %d\n",
2147   n, h + 1, heads);   n, h + 1, g_heads);
2148   if (real_s >= sectors)   if (real_s >= g_sectors)
2149   printf(_("Partition %d: sector %d greater than "   printf("Partition %d: sector %d greater than "
2150   "maximum %d\n"), n, s, sectors);   "maximum %d\n", n, s, g_sectors);
2151   if (real_c >= cylinders)   if (real_c >= g_cylinders)
2152   printf(_("Partitions %d: cylinder %llu greater than "   printf("Partition %d: cylinder %llu greater than "
2153   "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);   "maximum %d\n", n, real_c + 1, g_cylinders);
2154   if (cylinders <= 1024 && start != total)   if (g_cylinders <= 1024 && start != total)
2155   printf(_("Partition %d: previous sectors %llu disagrees with "   printf("Partition %d: previous sectors %llu disagrees with "
2156   "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);   "total %llu\n", n, start, total);
2157  }  }
2158    
2159  static void  static void
# Line 2160  verify(void) Line 2161  verify(void)
2161  {  {
2162   int i, j;   int i, j;
2163   unsigned total = 1;   unsigned total = 1;
2164   off_t first[partitions], last[partitions];   ullong first[g_partitions], last[g_partitions];
2165   struct partition *p;   struct partition *p;
2166    
2167   if (warn_geometry())   if (warn_geometry())
# Line 2176  verify(void) Line 2177  verify(void)
2177   }   }
2178    
2179   fill_bounds(first, last);   fill_bounds(first, last);
2180   for (i = 0; i < partitions; i++) {   for (i = 0; i < g_partitions; i++) {
2181   struct pte *pe = &ptes[i];   struct pte *pe = &ptes[i];
2182    
2183   p = pe->part_table;   p = pe->part_table;
2184   if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {   if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
2185   check_consistency(p, i);   check_consistency(p, i);
2186   if (get_partition_start(pe) < first[i])   if (get_partition_start(pe) < first[i])
2187   printf(_("Warning: bad start-of-data in "   printf("Warning: bad start-of-data in "
2188   "partition %d\n"), i + 1);   "partition %d\n", i + 1);
2189   check(i + 1, p->end_head, p->end_sector, p->end_cyl,   check(i + 1, p->end_head, p->end_sector, p->end_cyl,
2190   last[i]);   last[i]);
2191   total += last[i] + 1 - first[i];   total += last[i] + 1 - first[i];
2192   for (j = 0; j < i; j++)   for (j = 0; j < i; j++) {
2193   if ((first[i] >= first[j] && first[i] <= last[j])   if ((first[i] >= first[j] && first[i] <= last[j])
2194   || ((last[i] <= last[j] && last[i] >= first[j]))) {   || ((last[i] <= last[j] && last[i] >= first[j]))) {
2195   printf(_("Warning: partition %d overlaps "   printf("Warning: partition %d overlaps "
2196   "partition %d.\n"), j + 1, i + 1);   "partition %d\n", j + 1, i + 1);
2197   total += first[i] >= first[j] ?   total += first[i] >= first[j] ?
2198   first[i] : first[j];   first[i] : first[j];
2199   total -= last[i] <= last[j] ?   total -= last[i] <= last[j] ?
2200   last[i] : last[j];   last[i] : last[j];
2201     }
2202   }   }
2203   }   }
2204   }   }
2205    
2206   if (extended_offset) {   if (extended_offset) {
2207   struct pte *pex = &ptes[ext_index];   struct pte *pex = &ptes[ext_index];
2208   off_t e_last = get_start_sect(pex->part_table) +   ullong e_last = get_start_sect(pex->part_table) +
2209   get_nr_sects(pex->part_table) - 1;   get_nr_sects(pex->part_table) - 1;
2210    
2211   for (i = 4; i < partitions; i++) {   for (i = 4; i < g_partitions; i++) {
2212   total++;   total++;
2213   p = ptes[i].part_table;   p = ptes[i].part_table;
2214   if (!p->sys_ind) {   if (!p->sys_ind) {
2215   if (i != 4 || i + 1 < partitions)   if (i != 4 || i + 1 < g_partitions)
2216   printf(_("Warning: partition %d "   printf("Warning: partition %d "
2217   "is empty\n"), i + 1);   "is empty\n", i + 1);
2218     } else if (first[i] < extended_offset || last[i] > e_last) {
2219     printf("Logical partition %d not entirely in "
2220     "partition %d\n", i + 1, ext_index + 1);
2221   }   }
  else if (first[i] < extended_offset ||  
  last[i] > e_last)  
  printf(_("Logical partition %d not entirely in "  
  "partition %d\n"), i + 1, ext_index + 1);  
2222   }   }
2223   }   }
2224    
2225   if (total > heads * sectors * cylinders)   if (total > g_heads * g_sectors * g_cylinders)
2226   printf(_("Total allocated sectors %d greater than the maximum "   printf("Total allocated sectors %d greater than the maximum "
2227   "%d\n"), total, heads * sectors * cylinders);   "%d\n", total, g_heads * g_sectors * g_cylinders);
2228   else if ((total = heads * sectors * cylinders - total) != 0)   else {
2229   printf(_("%d unallocated sectors\n"), total);   total = g_heads * g_sectors * g_cylinders - total;
2230     if (total != 0)
2231     printf("%d unallocated sectors\n", total);
2232     }
2233  }  }
2234    
2235  static void  static void
# Line 2235  add_partition(int n, int sys) Line 2239  add_partition(int n, int sys)
2239   int i, num_read = 0;   int i, num_read = 0;
2240   struct partition *p = ptes[n].part_table;   struct partition *p = ptes[n].part_table;
2241   struct partition *q = ptes[ext_index].part_table;   struct partition *q = ptes[ext_index].part_table;
2242   long long llimit;   ullong limit, temp;
2243   off_t start, stop = 0, limit, temp,   ullong start, stop = 0;
2244   first[partitions], last[partitions];   ullong first[g_partitions], last[g_partitions];
2245    
2246   if (p && p->sys_ind) {   if (p && p->sys_ind) {
2247   printf(_("Partition %d is already defined.  Delete "   printf(msg_part_already_defined, n + 1);
  "it before re-adding it.\n"), n + 1);  
2248   return;   return;
2249   }   }
2250   fill_bounds(first, last);   fill_bounds(first, last);
2251   if (n < 4) {   if (n < 4) {
2252   start = sector_offset;   start = sector_offset;
2253   if (display_in_cyl_units || !total_number_of_sectors)   if (display_in_cyl_units || !total_number_of_sectors)
2254   llimit = heads * sectors * cylinders - 1;   limit = (ullong) g_heads * g_sectors * g_cylinders - 1;
2255   else   else
2256   llimit = total_number_of_sectors - 1;   limit = total_number_of_sectors - 1;
  limit = llimit;  
  if (limit != llimit)  
  limit = 0x7fffffff;  
2257   if (extended_offset) {   if (extended_offset) {
2258   first[ext_index] = extended_offset;   first[ext_index] = extended_offset;
2259   last[ext_index] = get_start_sect(q) +   last[ext_index] = get_start_sect(q) +
# Line 2264  add_partition(int n, int sys) Line 2264  add_partition(int n, int sys)
2264   limit = get_start_sect(q) + get_nr_sects(q) - 1;   limit = get_start_sect(q) + get_nr_sects(q) - 1;
2265   }   }
2266   if (display_in_cyl_units)   if (display_in_cyl_units)
2267   for (i = 0; i < partitions; i++)   for (i = 0; i < g_partitions; i++)
2268   first[i] = (cround(first[i]) - 1) * units_per_sector;   first[i] = (cround(first[i]) - 1) * units_per_sector;
2269    
2270   snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));   snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
2271   do {   do {
2272   temp = start;   temp = start;
2273   for (i = 0; i < partitions; i++) {   for (i = 0; i < g_partitions; i++) {
2274   int lastplusoff;   int lastplusoff;
2275    
2276   if (start == ptes[i].offset)   if (start == ptes[i].offset)
# Line 2282  add_partition(int n, int sys) Line 2282  add_partition(int n, int sys)
2282   if (start > limit)   if (start > limit)
2283   break;   break;
2284   if (start >= temp+units_per_sector && num_read) {   if (start >= temp+units_per_sector && num_read) {
2285   printf(_("Sector %"OFF_FMT"d is already allocated\n"), temp);   printf("Sector %lld is already allocated\n", temp);
2286   temp = start;   temp = start;
2287   num_read = 0;   num_read = 0;
2288   }   }
2289   if (!num_read && start == temp) {   if (!num_read && start == temp) {
2290   off_t saved_start;   ullong saved_start;
2291    
2292   saved_start = start;   saved_start = start;
2293   start = read_int(cround(saved_start), cround(saved_start), cround(limit),   start = read_int(cround(saved_start), cround(saved_start), cround(limit),
# Line 2310  add_partition(int n, int sys) Line 2310  add_partition(int n, int sys)
2310   }   }
2311   }   }
2312    
2313   for (i = 0; i < partitions; i++) {   for (i = 0; i < g_partitions; i++) {
2314   struct pte *pe = &ptes[i];   struct pte *pe = &ptes[i];
2315    
2316   if (start < pe->offset && limit >= pe->offset)   if (start < pe->offset && limit >= pe->offset)
# Line 2319  add_partition(int n, int sys) Line 2319  add_partition(int n, int sys)
2319   limit = first[i] - 1;   limit = first[i] - 1;
2320   }   }
2321   if (start > limit) {   if (start > limit) {
2322   printf(_("No free sectors available\n"));   printf("No free sectors available\n");
2323   if (n > 4)   if (n > 4)
2324   partitions--;   g_partitions--;
2325   return;   return;
2326   }   }
2327   if (cround(start) == cround(limit)) {   if (cround(start) == cround(limit)) {
2328   stop = limit;   stop = limit;
2329   } else {   } else {
2330   snprintf(mesg, sizeof(mesg),   snprintf(mesg, sizeof(mesg),
2331   _("Last %s or +size or +sizeM or +sizeK"),   "Last %s or +size or +sizeM or +sizeK",
2332   str_units(SINGULAR));   str_units(SINGULAR));
2333   stop = read_int(cround(start), cround(limit), cround(limit),   stop = read_int(cround(start), cround(limit), cround(limit),
2334   cround(start), mesg);   cround(start), mesg);
# Line 2354  add_partition(int n, int sys) Line 2354  add_partition(int n, int sys)
2354   pe4->part_table = pt_offset(pe4->sectorbuffer, 0);   pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2355   pe4->ext_pointer = pe4->part_table + 1;   pe4->ext_pointer = pe4->part_table + 1;
2356   pe4->changed = 1;   pe4->changed = 1;
2357   partitions = 5;   g_partitions = 5;
2358   }   }
2359  }  }
2360    
2361  static void  static void
2362  add_logical(void)  add_logical(void)
2363  {  {
2364   if (partitions > 5 || ptes[4].part_table->sys_ind) {   if (g_partitions > 5 || ptes[4].part_table->sys_ind) {
2365   struct pte *pe = &ptes[partitions];   struct pte *pe = &ptes[g_partitions];
2366    
2367   pe->sectorbuffer = xzalloc(sector_size);   pe->sectorbuffer = xzalloc(sector_size);
2368   pe->part_table = pt_offset(pe->sectorbuffer, 0);   pe->part_table = pt_offset(pe->sectorbuffer, 0);
2369   pe->ext_pointer = pe->part_table + 1;   pe->ext_pointer = pe->part_table + 1;
2370   pe->offset = 0;   pe->offset = 0;
2371   pe->changed = 1;   pe->changed = 1;
2372   partitions++;   g_partitions++;
2373   }   }
2374   add_partition(partitions - 1, LINUX_NATIVE);   add_partition(g_partitions - 1, LINUX_NATIVE);
2375  }  }
2376    
2377  static void  static void
# Line 2383  new_partition(void) Line 2383  new_partition(void)
2383   return;   return;
2384    
2385   if (LABEL_IS_SUN) {   if (LABEL_IS_SUN) {
2386   add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);   add_sun_partition(get_partition(0, g_partitions), LINUX_NATIVE);
2387   return;   return;
2388   }   }
2389   if (LABEL_IS_SGI) {   if (LABEL_IS_SGI) {
2390   sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);   sgi_add_partition(get_partition(0, g_partitions), LINUX_NATIVE);
2391   return;   return;
2392   }   }
2393   if (LABEL_IS_AIX) {   if (LABEL_IS_AIX) {
2394   printf(_("\tSorry - this fdisk cannot handle AIX disk labels."   printf("Sorry - this fdisk cannot handle AIX disk labels.\n"
2395   "\n\tIf you want to add DOS-type partitions, create"  "If you want to add DOS-type partitions, create a new empty DOS partition\n"
2396   "\n\ta new empty DOS partition table first. (Use o.)"  "table first (use 'o'). This will destroy the present disk contents.\n");
  "\n\tWARNING: "  
  "This will destroy the present disk contents.\n"));  
2397   return;   return;
2398   }   }
2399    
2400   for (i = 0; i < 4; i++)   for (i = 0; i < 4; i++)
2401   free_primary += !ptes[i].part_table->sys_ind;   free_primary += !ptes[i].part_table->sys_ind;
2402    
2403   if (!free_primary && partitions >= MAXIMUM_PARTS) {   if (!free_primary && g_partitions >= MAXIMUM_PARTS) {
2404   printf(_("The maximum number of partitions has been created\n"));   printf("The maximum number of partitions has been created\n");
2405   return;   return;
2406   }   }
2407    
# Line 2411  new_partition(void) Line 2409  new_partition(void)
2409   if (extended_offset)   if (extended_offset)
2410   add_logical();   add_logical();
2411   else   else
2412   printf(_("You must delete some partition and add "   printf("You must delete some partition and add "
2413   "an extended partition first\n"));   "an extended partition first\n");
2414   } else {   } else {
2415   char c, line[LINE_LENGTH];   char c, line[80];
2416   snprintf(line, sizeof(line), "%s\n   %s\n   p   primary "   snprintf(line, sizeof(line),
2417   "partition (1-4)\n",   "Command action\n"
2418   "Command action", (extended_offset ?   "   %s\n"
2419   "l   logical (5 or over)" : "e   extended"));   "   p   primary partition (1-4)\n",
2420     (extended_offset ?
2421     "l   logical (5 or over)" : "e   extended"));
2422   while (1) {   while (1) {
2423   c = read_nonempty(line);   c = read_nonempty(line);
2424   if (c == 'p' || c == 'P') {   if (c == 'p' || c == 'P') {
# Line 2427  new_partition(void) Line 2427  new_partition(void)
2427   add_partition(i, LINUX_NATIVE);   add_partition(i, LINUX_NATIVE);
2428   return;   return;
2429   }   }
2430   else if (c == 'l' && extended_offset) {   if (c == 'l' && extended_offset) {
2431   add_logical();   add_logical();
2432   return;   return;
2433   }   }
2434   else if (c == 'e' && !extended_offset) {   if (c == 'e' && !extended_offset) {
2435   i = get_nonexisting_partition(0, 4);   i = get_nonexisting_partition(0, 4);
2436   if (i >= 0)   if (i >= 0)
2437   add_partition(i, EXTENDED);   add_partition(i, EXTENDED);
2438   return;   return;
2439   }   }
2440   else   printf("Invalid partition number "
2441   printf(_("Invalid partition number "   "for type '%c'\n", c);
  "for type '%c'\n"), c);  
2442   }   }
2443   }   }
2444  }  }
# Line 2453  write_table(void) Line 2452  write_table(void)
2452   for (i = 0; i < 3; i++)   for (i = 0; i < 3; i++)
2453   if (ptes[i].changed)   if (ptes[i].changed)
2454   ptes[3].changed = 1;   ptes[3].changed = 1;
2455   for (i = 3; i < partitions; i++) {   for (i = 3; i < g_partitions; i++) {
2456   struct pte *pe = &ptes[i];   struct pte *pe = &ptes[i];
2457    
2458   if (pe->changed) {   if (pe->changed) {
# Line 2476  write_table(void) Line 2475  write_table(void)
2475   sun_write_table();   sun_write_table();
2476   }   }
2477    
2478   printf(_("The partition table has been altered!\n\n"));   printf("The partition table has been altered!\n\n");
2479   reread_partition_table(1);   reread_partition_table(1);
2480  }  }
2481    
# Line 2485  reread_partition_table(int leave) Line 2484  reread_partition_table(int leave)
2484  {  {
2485   int i;   int i;
2486    
2487   printf(_("Calling ioctl() to re-read partition table\n"));   printf("Calling ioctl() to re-read partition table\n");
2488   sync();   sync();
2489   sleep(2); /* Huh? */   /* sleep(2); Huh? */
2490   i = ioctl(fd, BLKRRPART);   i = ioctl_or_perror(dev_fd, BLKRRPART, NULL,
2491  #if 0   "WARNING: rereading partition table "
  else {  
  /* some kernel versions (1.2.x) seem to have trouble  
    rereading the partition table, but if asked to do it  
    twice, the second time works. - biro@yggdrasil.com */  
  sync();  
  sleep(2);  
  i = ioctl(fd, BLKRRPART);  
  }  
 #endif  
   
  if (i) {  
  bb_perror_msg("WARNING: rereading partition table "  
2492   "failed, kernel still uses old table");   "failed, kernel still uses old table");
  }  
   
2493  #if 0  #if 0
2494   if (dos_changed)   if (dos_changed)
2495   printf(   printf(
2496   _("\nWARNING: If you have created or modified any DOS 6.x\n"   "\nWARNING: If you have created or modified any DOS 6.x\n"
2497   "partitions, please see the fdisk manual page for additional\n"   "partitions, please see the fdisk manual page for additional\n"
2498   "information.\n"));   "information\n");
2499  #endif  #endif
2500    
2501   if (leave) {   if (leave) {
2502   if (ENABLE_FEATURE_CLEAN_UP)   if (ENABLE_FEATURE_CLEAN_UP)
2503   close(fd);   close_dev_fd();
2504   exit(i != 0);   exit(i != 0);
2505   }   }
2506  }  }
# Line 2533  print_buffer(char *pbuffer) Line 2518  print_buffer(char *pbuffer)
2518   printf("0x%03X:", i);   printf("0x%03X:", i);
2519   printf(" %02X", (unsigned char) pbuffer[i]);   printf(" %02X", (unsigned char) pbuffer[i]);
2520   if (l == MAX_PER_LINE - 1) {   if (l == MAX_PER_LINE - 1) {
2521   puts("");   bb_putchar('\n');
2522   l = -1;   l = -1;
2523   }   }
2524   }   }
2525   if (l > 0)   if (l > 0)
2526   puts("");   bb_putchar('\n');
2527   puts("");   bb_putchar('\n');
2528  }  }
2529    
2530  static void  static void
# Line 2547  print_raw(void) Line 2532  print_raw(void)
2532  {  {
2533   int i;   int i;
2534    
2535   printf(_("Device: %s\n"), disk_device);   printf("Device: %s\n", disk_device);
2536   if (LABEL_IS_SGI || LABEL_IS_SUN)   if (LABEL_IS_SGI || LABEL_IS_SUN)
2537   print_buffer(MBRbuffer);   print_buffer(MBRbuffer);
2538   else {   else {
2539   for (i = 3; i < partitions; i++)   for (i = 3; i < g_partitions; i++)
2540   print_buffer(ptes[i].sectorbuffer);   print_buffer(ptes[i].sectorbuffer);
2541   }   }
2542  }  }
# Line 2561  move_begin(int i) Line 2546  move_begin(int i)
2546  {  {
2547   struct pte *pe = &ptes[i];   struct pte *pe = &ptes[i];
2548   struct partition *p = pe->part_table;   struct partition *p = pe->part_table;
2549   off_t new, first;   ullong new, first;
2550    
2551   if (warn_geometry())   if (warn_geometry())
2552   return;   return;
2553   if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {   if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
2554   printf(_("Partition %d has no data area\n"), i + 1);   printf("Partition %d has no data area\n", i + 1);
2555   return;   return;
2556   }   }
2557   first = get_partition_start(pe);   first = get_partition_start(pe);
2558   new = read_int(first, first, first + get_nr_sects(p) - 1, first,   new = read_int(first, first, first + get_nr_sects(p) - 1, first,
2559     _("New beginning of data")) - pe->offset;     "New beginning of data") - pe->offset;
2560    
2561   if (new != get_nr_sects(p)) {   if (new != get_nr_sects(p)) {
2562   first = get_nr_sects(p) + get_start_sect(p) - new;   first = get_nr_sects(p) + get_start_sect(p) - new;
# Line 2587  xselect(void) Line 2572  xselect(void)
2572   char c;   char c;
2573    
2574   while (1) {   while (1) {
2575   putchar('\n');   bb_putchar('\n');
2576   c = tolower(read_nonempty(_("Expert command (m for help): ")));   c = tolower(read_nonempty("Expert command (m for help): "));
2577   switch (c) {   switch (c) {
2578   case 'a':   case 'a':
2579   if (LABEL_IS_SUN)   if (LABEL_IS_SUN)
# Line 2596  xselect(void) Line 2581  xselect(void)
2581   break;   break;
2582   case 'b':   case 'b':
2583   if (LABEL_IS_DOS)   if (LABEL_IS_DOS)
2584   move_begin(get_partition(0, partitions));   move_begin(get_partition(0, g_partitions));
2585   break;   break;
2586   case 'c':   case 'c':
2587   user_cylinders = cylinders =   user_cylinders = g_cylinders =
2588   read_int(1, cylinders, 1048576, 0,   read_int(1, g_cylinders, 1048576, 0,
2589   _("Number of cylinders"));   "Number of cylinders");
2590   if (LABEL_IS_SUN)   if (LABEL_IS_SUN)
2591   sun_set_ncyl(cylinders);   sun_set_ncyl(g_cylinders);
2592   if (LABEL_IS_DOS)   if (LABEL_IS_DOS)
2593   warn_cylinders();   warn_cylinders();
2594   break;   break;
# Line 2628  xselect(void) Line 2613  xselect(void)
2613  #endif  #endif
2614   break;   break;
2615   case 'h':   case 'h':
2616   user_heads = heads = read_int(1, heads, 256, 0,   user_heads = g_heads = read_int(1, g_heads, 256, 0,
2617   _("Number of heads"));   "Number of heads");
2618   update_units();   update_units();
2619   break;   break;
2620   case 'i':   case 'i':
# Line 2647  xselect(void) Line 2632  xselect(void)
2632   x_list_table(0);   x_list_table(0);
2633   break;   break;
2634   case 'q':   case 'q':
2635   close(fd);   if (ENABLE_FEATURE_CLEAN_UP)
2636   puts("");   close_dev_fd();
2637   exit(0);   bb_putchar('\n');
2638     exit(EXIT_SUCCESS);
2639   case 'r':   case 'r':
2640   return;   return;
2641   case 's':   case 's':
2642   user_sectors = sectors = read_int(1, sectors, 63, 0,   user_sectors = g_sectors = read_int(1, g_sectors, 63, 0,
2643     _("Number of sectors"));     "Number of sectors");
2644   if (dos_compatible_flag) {   if (dos_compatible_flag) {
2645   sector_offset = sectors;   sector_offset = g_sectors;
2646   printf(_("Warning: setting sector offset for DOS "   printf("Warning: setting sector offset for DOS "
2647   "compatiblity\n"));   "compatiblity\n");
2648   }   }
2649   update_units();   update_units();
2650   break;   break;
# Line 2698  is_ide_cdrom_or_tape(const char *device) Line 2684  is_ide_cdrom_or_tape(const char *device)
2684   return 0;   return 0;
2685    
2686   snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);   snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
2687   procf = fopen(buf, "r");   procf = fopen_for_read(buf);
2688   if (procf != NULL && fgets(buf, sizeof(buf), procf))   if (procf != NULL && fgets(buf, sizeof(buf), procf))
2689   is_ide = (!strncmp(buf, "cdrom", 5) ||   is_ide = (!strncmp(buf, "cdrom", 5) ||
2690    !strncmp(buf, "tape", 4));    !strncmp(buf, "tape", 4));
# Line 2715  is_ide_cdrom_or_tape(const char *device) Line 2701  is_ide_cdrom_or_tape(const char *device)
2701    
2702    
2703  static void  static void
2704  trydev(const char *device, int user_specified)  open_list_and_close(const char *device, int user_specified)
2705  {  {
2706   int gb;   int gb;
2707    
# Line 2725  trydev(const char *device, int user_spec Line 2711  trydev(const char *device, int user_spec
2711   if (!user_specified)   if (!user_specified)
2712   if (is_ide_cdrom_or_tape(device))   if (is_ide_cdrom_or_tape(device))
2713   return;   return;
2714   fd = open(disk_device, type_open);  
2715   if (fd >= 0) {   /* Open disk_device, save file descriptor to dev_fd */
2716   gb = get_boot(try_only);   errno = 0;
2717   if (gb > 0) {   /* I/O error */   gb = get_boot(TRY_ONLY);
2718   close(fd);   if (gb > 0) {   /* I/O error */
  } else if (gb < 0) { /* no DOS signature */  
  list_disk_geometry();  
  if (LABEL_IS_AIX) {  
  return;  
  }  
 #if ENABLE_FEATURE_OSF_LABEL  
  if (bsd_trydev(device) < 0)  
 #endif  
  printf(_("Disk %s doesn't contain a valid "  
  "partition table\n"), device);  
  close(fd);  
  } else {  
  close(fd);  
  list_table(0);  
 #if ENABLE_FEATURE_FDISK_WRITABLE  
  if (!LABEL_IS_SUN && partitions > 4){  
  delete_partition(ext_index);  
  }  
 #endif  
  }  
  } else {  
2719   /* Ignore other errors, since we try IDE   /* Ignore other errors, since we try IDE
2720     and SCSI hard disks which may not be     and SCSI hard disks which may not be
2721     installed on the system. */     installed on the system. */
2722   if (errno == EACCES) {   if (user_specified || errno == EACCES)
2723   printf(_("Cannot open %s\n"), device);   bb_perror_msg("can't open '%s'", device);
2724   return;   return;
2725     }
2726    
2727     if (gb < 0) { /* no DOS signature */
2728     list_disk_geometry();
2729     if (LABEL_IS_AIX)
2730     goto ret;
2731    #if ENABLE_FEATURE_OSF_LABEL
2732     if (bsd_trydev(device) < 0)
2733    #endif
2734     printf("Disk %s doesn't contain a valid "
2735     "partition table\n", device);
2736     } else {
2737     list_table(0);
2738    #if ENABLE_FEATURE_FDISK_WRITABLE
2739     if (!LABEL_IS_SUN && g_partitions > 4) {
2740     delete_partition(ext_index);
2741   }   }
2742    #endif
2743   }   }
2744     ret:
2745     close_dev_fd();
2746  }  }
2747    
2748  /* for fdisk -l: try all things in /proc/partitions  /* for fdisk -l: try all things in /proc/partitions
2749     that look like a partition name (do not end in a digit) */     that look like a partition name (do not end in a digit) */
2750  static void  static void
2751  tryprocpt(void)  list_devs_in_proc_partititons(void)
2752  {  {
2753   FILE *procpt;   FILE *procpt;
2754   char line[100], ptname[100], devname[120], *s;   char line[100], ptname[100], devname[120], *s;
# Line 2776  tryprocpt(void) Line 2760  tryprocpt(void)
2760   if (sscanf(line, " %d %d %d %[^\n ]",   if (sscanf(line, " %d %d %d %[^\n ]",
2761   &ma, &mi, &sz, ptname) != 4)   &ma, &mi, &sz, ptname) != 4)
2762   continue;   continue;
2763   for (s = ptname; *s; s++);   for (s = ptname; *s; s++)
2764     continue;
2765   if (isdigit(s[-1]))   if (isdigit(s[-1]))
2766   continue;   continue;
2767   sprintf(devname, "/dev/%s", ptname);   sprintf(devname, "/dev/%s", ptname);
2768   trydev(devname, 0);   open_list_and_close(devname, 0);
2769   }   }
2770  #if ENABLE_FEATURE_CLEAN_UP  #if ENABLE_FEATURE_CLEAN_UP
2771   fclose(procpt);   fclose(procpt);
# Line 2791  tryprocpt(void) Line 2776  tryprocpt(void)
2776  static void  static void
2777  unknown_command(int c)  unknown_command(int c)
2778  {  {
2779   printf(_("%c: unknown command\n"), c);   printf("%c: unknown command\n", c);
2780  }  }
2781  #endif  #endif
2782    
2783    int fdisk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
2784  int fdisk_main(int argc, char **argv)  int fdisk_main(int argc, char **argv)
2785  {  {
  char *str_b, *str_C, *str_H, *str_S;  
2786   unsigned opt;   unsigned opt;
2787   /*   /*
2788   *  fdisk -v   *  fdisk -v
# Line 2807  int fdisk_main(int argc, char **argv) Line 2792  int fdisk_main(int argc, char **argv)
2792   *   *
2793   * Options -C, -H, -S set the geometry.   * Options -C, -H, -S set the geometry.
2794   */   */
2795   enum {   INIT_G();
2796   OPT_b = 1 << 0,  
2797   OPT_C = 1 << 1,   close_dev_fd(); /* needed: fd 3 must not stay closed */
2798   OPT_H = 1 << 2,  
2799   OPT_l = 1 << 3,   opt_complementary = "b+:C+:H+:S+"; /* numeric params */
2800   OPT_S = 1 << 4,   opt = getopt32(argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"),
2801   OPT_u = 1 << 5,   &sector_size, &user_cylinders, &user_heads, &user_sectors);
  OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,  
  };  
  opt = getopt32(argc, argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"),  
  &str_b, &str_C, &str_H, &str_S);  
2802   argc -= optind;   argc -= optind;
2803   argv += optind;   argv += optind;
2804   if (opt & OPT_b) { // -b   if (opt & OPT_b) { // -b
# Line 2825  int fdisk_main(int argc, char **argv) Line 2806  int fdisk_main(int argc, char **argv)
2806     so cannot be combined with multiple disks,     so cannot be combined with multiple disks,
2807     and the same goes for the C/H/S options.     and the same goes for the C/H/S options.
2808   */   */
2809   sector_size = xatoi_u(str_b);   if (sector_size != 512 && sector_size != 1024
2810   if (sector_size != 512 && sector_size != 1024 &&   && sector_size != 2048)
  sector_size != 2048)  
2811   bb_show_usage();   bb_show_usage();
2812   sector_offset = 2;   sector_offset = 2;
2813   user_set_sector_size = 1;   user_set_sector_size = 1;
2814   }   }
2815   if (opt & OPT_C) user_cylinders = xatoi_u(str_C); // -C   if (user_heads <= 0 || user_heads >= 256)
2816   if (opt & OPT_H) { // -H   user_heads = 0;
2817   user_heads = xatoi_u(str_H);   if (user_sectors <= 0 || user_sectors >= 64)
2818   if (user_heads <= 0 || user_heads >= 256)   user_sectors = 0;
2819   user_heads = 0;   if (opt & OPT_u)
2820   }   display_in_cyl_units = 0; // -u
  //if (opt & OPT_l) // -l  
  if (opt & OPT_S) { // -S  
  user_sectors = xatoi_u(str_S);  
  if (user_sectors <= 0 || user_sectors >= 64)  
  user_sectors = 0;  
  }  
  if (opt & OPT_u) display_in_cyl_units = 0; // -u  
  //if (opt & OPT_s) // -s  
   
  if (user_set_sector_size && argc != 1)  
  printf(_("Warning: the -b (set sector size) option should"  
  " be used with one specified device\n"));  
2821    
2822  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
2823   if (opt & OPT_l) {   if (opt & OPT_l) {
2824   nowarn = 1;   nowarn = 1;
2825  #endif  #endif
2826   type_open = O_RDONLY;   if (*argv) {
  if (argc > 0) {  
  int k;  
 #if defined(__GNUC__)  
  /* avoid gcc warning:  
    variable `k' might be clobbered by `longjmp' */  
  (void)&k;  
 #endif  
2827   listing = 1;   listing = 1;
2828   for (k = 0; k < argc; k++)   do {
2829   trydev(argv[k], 1);   open_list_and_close(*argv, 1);
2830     } while (*++argv);
2831   } else {   } else {
2832   /* we no longer have default device names */   /* we don't have device names, */
2833   /* but, we can use /proc/partitions instead */   /* use /proc/partitions instead */
2834   tryprocpt();   list_devs_in_proc_partititons();
2835   }   }
2836   return 0;   return 0;
2837  #if ENABLE_FEATURE_FDISK_WRITABLE  #if ENABLE_FEATURE_FDISK_WRITABLE
# Line 2878  int fdisk_main(int argc, char **argv) Line 2840  int fdisk_main(int argc, char **argv)
2840    
2841  #if ENABLE_FEATURE_FDISK_BLKSIZE  #if ENABLE_FEATURE_FDISK_BLKSIZE
2842   if (opt & OPT_s) {   if (opt & OPT_s) {
  long size;  
2843   int j;   int j;
2844    
2845   nowarn = 1;   nowarn = 1;
  type_open = O_RDONLY;  
   
2846   if (argc <= 0)   if (argc <= 0)
2847   bb_show_usage();   bb_show_usage();
   
2848   for (j = 0; j < argc; j++) {   for (j = 0; j < argc; j++) {
2849   disk_device = argv[j];   unsigned long long size;
2850   fd = open(disk_device, type_open);   fd = xopen(argv[j], O_RDONLY);
2851   if (fd < 0)   size = bb_BLKGETSIZE_sectors(fd) / 2;
  fdisk_fatal(unable_to_open);  
  if (ioctl(fd, BLKGETSIZE, &size))  
  fdisk_fatal(ioctl_error);  
2852   close(fd);   close(fd);
2853   if (argc == 1)   if (argc == 1)
2854   printf("%ld\n", size/2);   printf("%lld\n", size);
2855   else   else
2856   printf("%s: %ld\n", argv[j], size/2);   printf("%s: %lld\n", argv[j], size);
2857   }   }
2858   return 0;   return 0;
2859   }   }
# Line 2909  int fdisk_main(int argc, char **argv) Line 2864  int fdisk_main(int argc, char **argv)
2864   bb_show_usage();   bb_show_usage();
2865    
2866   disk_device = argv[0];   disk_device = argv[0];
2867   get_boot(fdisk);   get_boot(OPEN_MAIN);
2868    
2869   if (LABEL_IS_OSF) {   if (LABEL_IS_OSF) {
2870   /* OSF label, and no DOS label */   /* OSF label, and no DOS label */
2871   printf(_("Detected an OSF/1 disklabel on %s, entering "   printf("Detected an OSF/1 disklabel on %s, entering "
2872   "disklabel mode.\n"), disk_device);   "disklabel mode\n", disk_device);
2873   bsd_select();   bsd_select();
2874   /*Why do we do this?  It seems to be counter-intuitive*/   /*Why do we do this?  It seems to be counter-intuitive*/
2875   current_label_type = label_dos;   current_label_type = LABEL_DOS;
2876   /* If we return we may want to make an empty DOS label? */   /* If we return we may want to make an empty DOS label? */
2877   }   }
2878    
2879   while (1) {   while (1) {
2880   int c;   int c;
2881   putchar('\n');   bb_putchar('\n');
2882   c = tolower(read_nonempty(_("Command (m for help): ")));   c = tolower(read_nonempty("Command (m for help): "));
2883   switch (c) {   switch (c) {
2884   case 'a':   case 'a':
2885   if (LABEL_IS_DOS)   if (LABEL_IS_DOS)
2886   toggle_active(get_partition(1, partitions));   toggle_active(get_partition(1, g_partitions));
2887   else if (LABEL_IS_SUN)   else if (LABEL_IS_SUN)
2888   toggle_sunflags(get_partition(1, partitions),   toggle_sunflags(get_partition(1, g_partitions),
2889   0x01);   0x01);
2890   else if (LABEL_IS_SGI)   else if (LABEL_IS_SGI)
2891   sgi_set_bootpartition(   sgi_set_bootpartition(
2892   get_partition(1, partitions));   get_partition(1, g_partitions));
2893   else   else
2894   unknown_command(c);   unknown_command(c);
2895   break;   break;
2896   case 'b':   case 'b':
2897   if (LABEL_IS_SGI) {   if (LABEL_IS_SGI) {
2898   printf(_("\nThe current boot file is: %s\n"),   printf("\nThe current boot file is: %s\n",
2899   sgi_get_bootfile());   sgi_get_bootfile());
2900   if (read_maybe_empty(_("Please enter the name of the "   if (read_maybe_empty("Please enter the name of the "
2901     "new boot file: ")) == '\n')     "new boot file: ") == '\n')
2902   printf(_("Boot file unchanged\n"));   printf("Boot file unchanged\n");
2903   else   else
2904   sgi_set_bootfile(line_ptr);   sgi_set_bootfile(line_ptr);
2905   }   }
# Line 2957  int fdisk_main(int argc, char **argv) Line 2912  int fdisk_main(int argc, char **argv)
2912   if (LABEL_IS_DOS)   if (LABEL_IS_DOS)
2913   toggle_dos_compatibility_flag();   toggle_dos_compatibility_flag();
2914   else if (LABEL_IS_SUN)   else if (LABEL_IS_SUN)
2915   toggle_sunflags(get_partition(1, partitions),   toggle_sunflags(get_partition(1, g_partitions),
2916   0x10);   0x10);
2917   else if (LABEL_IS_SGI)   else if (LABEL_IS_SGI)
2918   sgi_set_swappartition(   sgi_set_swappartition(
2919   get_partition(1, partitions));   get_partition(1, g_partitions));
2920   else   else
2921   unknown_command(c);   unknown_command(c);
2922   break;   break;
# Line 2973  int fdisk_main(int argc, char **argv) Line 2928  int fdisk_main(int argc, char **argv)
2928     get_existing_partition() only works for Linux-like     get_existing_partition() only works for Linux-like
2929     partition tables */     partition tables */
2930   if (!LABEL_IS_SGI) {   if (!LABEL_IS_SGI) {
2931   j = get_existing_partition(1, partitions);   j = get_existing_partition(1, g_partitions);
2932   } else {   } else {
2933   j = get_partition(1, partitions);   j = get_partition(1, g_partitions);
2934   }   }
2935   if (j >= 0)   if (j >= 0)
2936   delete_partition(j);   delete_partition(j);
# Line 3002  int fdisk_main(int argc, char **argv) Line 2957  int fdisk_main(int argc, char **argv)
2957   list_table(0);   list_table(0);
2958   break;   break;
2959   case 'q':   case 'q':
2960   close(fd);   if (ENABLE_FEATURE_CLEAN_UP)
2961   puts("");   close_dev_fd();
2962     bb_putchar('\n');
2963   return 0;   return 0;
2964   case 's':   case 's':
2965  #if ENABLE_FEATURE_SUN_LABEL  #if ENABLE_FEATURE_SUN_LABEL
# Line 3025  int fdisk_main(int argc, char **argv) Line 2981  int fdisk_main(int argc, char **argv)
2981  #if ENABLE_FEATURE_FDISK_ADVANCED  #if ENABLE_FEATURE_FDISK_ADVANCED
2982   case 'x':   case 'x':
2983   if (LABEL_IS_SGI) {   if (LABEL_IS_SGI) {
2984   printf(_("\n\tSorry, no experts menu for SGI "   printf("\n\tSorry, no experts menu for SGI "
2985   "partition tables available.\n\n"));   "partition tables available\n\n");
2986   } else   } else
2987   xselect();   xselect();
2988   break;   break;

Legend:
Removed from v.815  
changed lines
  Added in v.816