aboutsummaryrefslogtreecommitdiff
path: root/sfdisk.c
diff options
context:
space:
mode:
Diffstat (limited to 'sfdisk.c')
-rw-r--r--sfdisk.c4426
1 files changed, 2281 insertions, 2145 deletions
diff --git a/sfdisk.c b/sfdisk.c
index 5dc44eacc..116a019ab 100644
--- a/sfdisk.c
+++ b/sfdisk.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * sfdisk version 3.0 - aeb - 950813 3 * sfdisk version 3.0 - aeb - 950813
3 * 4 *
@@ -39,52 +40,53 @@
39 40
40#include "internal.h" 41#include "internal.h"
41#include <stdio.h> 42#include <stdio.h>
42#include <stdlib.h> /* atoi, free */ 43#include <stdlib.h> /* atoi, free */
43#include <stdarg.h> /* varargs */ 44#include <stdarg.h> /* varargs */
44#include <unistd.h> /* read, write */ 45#include <unistd.h> /* read, write */
45#include <fcntl.h> /* O_RDWR */ 46#include <fcntl.h> /* O_RDWR */
46#include <errno.h> /* ERANGE */ 47#include <errno.h> /* ERANGE */
47#include <string.h> /* index() */ 48#include <string.h> /* index() */
48#include <ctype.h> 49#include <ctype.h>
49#include <getopt.h> 50#include <getopt.h>
50#include <sys/ioctl.h> 51#include <sys/ioctl.h>
51#include <sys/stat.h> 52#include <sys/stat.h>
52#include <linux/unistd.h> /* _syscall */ 53#include <linux/unistd.h> /* _syscall */
53#include <linux/hdreg.h> /* HDIO_GETGEO */ 54#include <linux/hdreg.h> /* HDIO_GETGEO */
54#include <linux/fs.h> /* BLKGETSIZE */ 55#include <linux/fs.h> /* BLKGETSIZE */
55 56
56 57
57static const char sfdisk_usage[] = 58static const char sfdisk_usage[] =
58"sfdisk [options] device ...\n" 59 "sfdisk [options] device ...\n"
59"device: something like /dev/hda or /dev/sda\n" 60 "device: something like /dev/hda or /dev/sda\n"
60"useful options:\n" 61 "useful options:\n"
61" -s [or --show-size]: list size of a partition\n" 62 " -s [or --show-size]: list size of a partition\n"
62" -c [or --id]: print or change partition Id\n" 63 " -c [or --id]: print or change partition Id\n"
63" -l [or --list]: list partitions of each device\n" 64 " -l [or --list]: list partitions of each device\n"
64" -d [or --dump]: idem, but in a format suitable for later input\n" 65 " -d [or --dump]: idem, but in a format suitable for later input\n"
65" -i [or --increment]: number cylinders etc. from 1 instead of from 0\n" 66 " -i [or --increment]: number cylinders etc. from 1 instead of from 0\n"
66" -uS, -uB, -uC, -uM: accept/report in units of sectors/blocks/cylinders/MB\n" 67 " -uS, -uB, -uC, -uM: accept/report in units of sectors/blocks/cylinders/MB\n"
67" -T [or --list-types]:list the known partition types\n" 68 " -T [or --list-types]:list the known partition types\n"
68" -D [or --DOS]: for DOS-compatibility: waste a little space\n" 69 " -D [or --DOS]: for DOS-compatibility: waste a little space\n"
69" -R [or --re-read]: make kernel reread partition table\n" 70 " -R [or --re-read]: make kernel reread partition table\n"
70" -N# : change only the partition with number #\n" 71 " -N# : change only the partition with number #\n"
71" -n : do not actually write to disk\n" 72 " -n : do not actually write to disk\n"
72" -O file : save the sectors that will be overwritten to file\n" 73 " -O file : save the sectors that will be overwritten to file\n"
73" -I file : restore these sectors again\n" 74 " -I file : restore these sectors again\n"
74" -v [or --version]: print version\n" 75 " -v [or --version]: print version\n"
75" -? [or --help]: print this message\n" 76 " -? [or --help]: print this message\n"
76"dangerous options:\n" 77 "dangerous options:\n"
77" -g [or --show-geometry]: print the kernel's idea of the geometry\n" 78 " -g [or --show-geometry]: print the kernel's idea of the geometry\n"
78" -x [or --show-extended]: also list extended partitions on output\n\n" 79 " -x [or --show-extended]: also list extended partitions on output\n\n"
79" or expect descriptors for them on input\n" 80 " or expect descriptors for them on input\n"
80" -L [or --Linux]: do not complain about things irrelevant for Linux\n" 81 " -L [or --Linux]: do not complain about things irrelevant for Linux\n"
81" -q [or --quiet]: suppress warning messages\n" 82 " -q [or --quiet]: suppress warning messages\n"
82" You can override the detected geometry using:\n" 83 " You can override the detected geometry using:\n"
83" -C# [or --cylinders #]:set the number of cylinders to use\n" 84 " -C# [or --cylinders #]:set the number of cylinders to use\n"
84" -H# [or --heads #]: set the number of heads to use\n" 85 " -H# [or --heads #]: set the number of heads to use\n"
85" -S# [or --sectors #]: set the number of sectors to use\n" 86 " -S# [or --sectors #]: set the number of sectors to use\n"
86"You can disable all consistency checking with:\n" 87
87" -f [or --force]: do what I say, even if it is stupid\n"; 88 "You can disable all consistency checking with:\n"
89 " -f [or --force]: do what I say, even if it is stupid\n";
88 90
89 91
90 92
@@ -100,14 +102,14 @@ static struct systypes i386_sys_types[] = {
100 {0x02, "XENIX root"}, 102 {0x02, "XENIX root"},
101 {0x03, "XENIX usr"}, 103 {0x03, "XENIX usr"},
102 {0x04, "FAT16 <32M"}, 104 {0x04, "FAT16 <32M"},
103 {0x05, "Extended"}, /* DOS 3.3+ extended partition */ 105 {0x05, "Extended"}, /* DOS 3.3+ extended partition */
104 {0x06, "FAT16"}, /* DOS 16-bit >=32M */ 106 {0x06, "FAT16"}, /* DOS 16-bit >=32M */
105 {0x07, "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */ 107 {0x07, "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
106 {0x08, "AIX"}, /* AIX boot (AIX -- PS/2 port or SplitDrive) */ 108 {0x08, "AIX"}, /* AIX boot (AIX -- PS/2 port or SplitDrive) */
107 {0x09, "AIX bootable"}, /* AIX data or Coherent */ 109 {0x09, "AIX bootable"}, /* AIX data or Coherent */
108 {0x0a, "OS/2 Boot Manager"},/* OS/2 Boot Manager */ 110 {0x0a, "OS/2 Boot Manager"}, /* OS/2 Boot Manager */
109 {0x0b, "Win95 FAT32"}, 111 {0x0b, "Win95 FAT32"},
110 {0x0c, "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */ 112 {0x0c, "Win95 FAT32 (LBA)"}, /* LBA really is `Extended Int 13h' */
111 {0x0e, "Win95 FAT16 (LBA)"}, 113 {0x0e, "Win95 FAT16 (LBA)"},
112 {0x0f, "Win95 Ext'd (LBA)"}, 114 {0x0f, "Win95 Ext'd (LBA)"},
113 {0x10, "OPUS"}, 115 {0x10, "OPUS"},
@@ -130,7 +132,7 @@ static struct systypes i386_sys_types[] = {
130 {0x4f, "QNX4.x 3rd part"}, 132 {0x4f, "QNX4.x 3rd part"},
131 {0x50, "OnTrack DM"}, 133 {0x50, "OnTrack DM"},
132 {0x51, "OnTrack DM6 Aux1"}, /* (or Novell) */ 134 {0x51, "OnTrack DM6 Aux1"}, /* (or Novell) */
133 {0x52, "CP/M"}, /* CP/M or Microport SysV/AT */ 135 {0x52, "CP/M"}, /* CP/M or Microport SysV/AT */
134 {0x53, "OnTrack DM6 Aux3"}, 136 {0x53, "OnTrack DM6 Aux3"},
135 {0x54, "OnTrackDM6"}, 137 {0x54, "OnTrackDM6"},
136 {0x55, "EZ-Drive"}, 138 {0x55, "EZ-Drive"},
@@ -142,16 +144,16 @@ static struct systypes i386_sys_types[] = {
142 {0x65, "Novell Netware 386"}, 144 {0x65, "Novell Netware 386"},
143 {0x70, "DiskSecure Multi-Boot"}, 145 {0x70, "DiskSecure Multi-Boot"},
144 {0x75, "PC/IX"}, 146 {0x75, "PC/IX"},
145 {0x80, "Old Minix"}, /* Minix 1.4a and earlier */ 147 {0x80, "Old Minix"}, /* Minix 1.4a and earlier */
146 {0x81, "Minix / old Linux"},/* Minix 1.4b and later */ 148 {0x81, "Minix / old Linux"}, /* Minix 1.4b and later */
147 {0x82, "Linux swap"}, /* also Solaris */ 149 {0x82, "Linux swap"}, /* also Solaris */
148 {0x83, "Linux"}, 150 {0x83, "Linux"},
149 {0x84, "OS/2 hidden C: drive"}, 151 {0x84, "OS/2 hidden C: drive"},
150 {0x85, "Linux extended"}, 152 {0x85, "Linux extended"},
151 {0x86, "NTFS volume set"}, 153 {0x86, "NTFS volume set"},
152 {0x87, "NTFS volume set"}, 154 {0x87, "NTFS volume set"},
153 {0x93, "Amoeba"}, 155 {0x93, "Amoeba"},
154 {0x94, "Amoeba BBT"}, /* (bad block table) */ 156 {0x94, "Amoeba BBT"}, /* (bad block table) */
155 {0xa0, "IBM Thinkpad hibernation"}, 157 {0xa0, "IBM Thinkpad hibernation"},
156 {0xa5, "BSD/386"}, 158 {0xa5, "BSD/386"},
157 {0xa6, "OpenBSD"}, 159 {0xa6, "OpenBSD"},
@@ -162,19 +164,19 @@ static struct systypes i386_sys_types[] = {
162 {0xc4, "DRDOS/sec (FAT-16 < 32M)"}, 164 {0xc4, "DRDOS/sec (FAT-16 < 32M)"},
163 {0xc6, "DRDOS/sec (FAT-16)"}, 165 {0xc6, "DRDOS/sec (FAT-16)"},
164 {0xc7, "Syrinx"}, 166 {0xc7, "Syrinx"},
165 {0xdb, "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or Concurrent DOS or CTOS */ 167 {0xdb, "CP/M / CTOS / ..."}, /* CP/M or Concurrent CP/M or Concurrent DOS or CTOS */
166 {0xe1, "DOS access"}, /* DOS access or SpeedStor 12-bit FAT extended partition */ 168 {0xe1, "DOS access"}, /* DOS access or SpeedStor 12-bit FAT extended partition */
167 {0xe3, "DOS R/O"}, /* DOS R/O or SpeedStor */ 169 {0xe3, "DOS R/O"}, /* DOS R/O or SpeedStor */
168 {0xe4, "SpeedStor"}, /* SpeedStor 16-bit FAT extended partition < 1024 cyl. */ 170 {0xe4, "SpeedStor"}, /* SpeedStor 16-bit FAT extended partition < 1024 cyl. */
169 {0xeb, "BeOS fs"}, 171 {0xeb, "BeOS fs"},
170 {0xf1, "SpeedStor"}, 172 {0xf1, "SpeedStor"},
171 {0xf4, "SpeedStor"}, /* SpeedStor large partition */ 173 {0xf4, "SpeedStor"}, /* SpeedStor large partition */
172 {0xf2, "DOS secondary"}, /* DOS 3.3+ secondary */ 174 {0xf2, "DOS secondary"}, /* DOS 3.3+ secondary */
173 {0xfd, "Linux raid autodetect"},/* New (2.2.x) raid partition with autodetect 175 {0xfd, "Linux raid autodetect"}, /* New (2.2.x) raid partition with autodetect
174 using persistent superblock */ 176 using persistent superblock */
175 {0xfe, "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */ 177 {0xfe, "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
176 {0xff, "BBT"}, /* Xenix Bad Block Table */ 178 {0xff, "BBT"}, /* Xenix Bad Block Table */
177 { 0, 0 } 179 {0, 0}
178}; 180};
179 181
180#define SIZE(a) (sizeof(a)/sizeof(a[0])) 182#define SIZE(a) (sizeof(a)/sizeof(a[0]))
@@ -193,51 +195,51 @@ static struct systypes i386_sys_types[] = {
193 */ 195 */
194static int exit_status = 0; 196static int exit_status = 0;
195 197
196static int force = 0; /* 1: do what I say, even if it is stupid ... */ 198static int force = 0; /* 1: do what I say, even if it is stupid ... */
197static int quiet = 0; /* 1: suppress all warnings */ 199static int quiet = 0; /* 1: suppress all warnings */
198static int Linux = 0; /* 1: suppress warnings irrelevant for Linux */ 200static int Linux = 0; /* 1: suppress warnings irrelevant for Linux */
199static int DOS = 0; /* 1: shift extended partitions by #sectors, not 1 */ 201static int DOS = 0; /* 1: shift extended partitions by #sectors, not 1 */
200static int dump = 0; /* 1: list in a format suitable for later input */ 202static int dump = 0; /* 1: list in a format suitable for later input */
201static int verify = 0; /* 1: check that listed partition is reasonable */ 203static int verify = 0; /* 1: check that listed partition is reasonable */
202static int no_write = 0; /* 1: do not actually write to disk */ 204static int no_write = 0; /* 1: do not actually write to disk */
203static int no_reread = 0; /* 1: skip the BLKRRPART ioctl test at startup */ 205static int no_reread = 0; /* 1: skip the BLKRRPART ioctl test at startup */
204static int leave_last = 0; /* 1: don't allocate the last cylinder */ 206static int leave_last = 0; /* 1: don't allocate the last cylinder */
205static int opt_list = 0; 207static int opt_list = 0;
206static char *save_sector_file = NULL; 208static char *save_sector_file = NULL;
207static char *restore_sector_file = NULL; 209static char *restore_sector_file = NULL;
208 210
209static void 211static void warn(char *s, ...)
210warn(char *s, ...) { 212{
211 va_list p; 213 va_list p;
212 214
213 va_start(p, s); 215 va_start(p, s);
214 fflush(stdout); 216 fflush(stdout);
215 if (!quiet) 217 if (!quiet)
216 vfprintf (stderr, s, p); 218 vfprintf(stderr, s, p);
217 va_end(p); 219 va_end(p);
218} 220}
219 221
220static void 222static void error(char *s, ...)
221error(char *s, ...) { 223{
222 va_list p; 224 va_list p;
223 225
224 va_start(p, s); 226 va_start(p, s);
225 fflush(stdout); 227 fflush(stdout);
226 fprintf(stderr, "\n" PROGNAME ": "); 228 fprintf(stderr, "\n" PROGNAME ": ");
227 vfprintf(stderr, s, p); 229 vfprintf(stderr, s, p);
228 va_end(p); 230 va_end(p);
229} 231}
230 232
231static void 233static void fatal(char *s, ...)
232fatal(char *s, ...) { 234{
233 va_list p; 235 va_list p;
234 236
235 va_start(p, s); 237 va_start(p, s);
236 fflush(stdout); 238 fflush(stdout);
237 fprintf(stderr, "\n" PROGNAME ": "); 239 fprintf(stderr, "\n" PROGNAME ": ");
238 vfprintf(stderr, s, p); 240 vfprintf(stderr, s, p);
239 va_end(p); 241 va_end(p);
240 exit(1); 242 exit(1);
241} 243}
242 244
243/* 245/*
@@ -254,33 +256,34 @@ fatal(char *s, ...) {
254 */ 256 */
255#ifndef __alpha__ 257#ifndef __alpha__
256static 258static
257_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, 259_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
258 loff_t *, res, uint, wh); 260 loff_t *, res, uint, wh);
259#endif 261#endif
260 262
261static int 263static int sseek(char *dev, unsigned int fd, unsigned long s)
262sseek(char *dev, unsigned int fd, unsigned long s) { 264{
263 loff_t in, out; 265 loff_t in, out;
264 in = ((loff_t) s << 9); 266
265 out = 1; 267 in = ((loff_t) s << 9);
268 out = 1;
266 269
267#ifndef __alpha__ 270#ifndef __alpha__
268 if (_llseek (fd, in>>32, in & 0xffffffff, &out, SEEK_SET) != 0) { 271 if (_llseek(fd, in >> 32, in & 0xffffffff, &out, SEEK_SET) != 0) {
269#else 272#else
270 if ((out = lseek(fd, in, SEEK_SET)) != in) { 273 if ((out = lseek(fd, in, SEEK_SET)) != in) {
271#endif 274#endif
272 perror("llseek"); 275 perror("llseek");
273 error("seek error on %s - cannot seek to %lu\n", dev, s); 276 error("seek error on %s - cannot seek to %lu\n", dev, s);
274 return 0; 277 return 0;
275 } 278 }
276 279
277 if (in != out) { 280 if (in != out) {
278 error("seek error: wanted 0x%08x%08x, got 0x%08x%08x\n", 281 error("seek error: wanted 0x%08x%08x, got 0x%08x%08x\n",
279 (uint)(in>>32), (uint)(in & 0xffffffff), 282 (uint) (in >> 32), (uint) (in & 0xffffffff),
280 (uint)(out>>32), (uint)(out & 0xffffffff)); 283 (uint) (out >> 32), (uint) (out & 0xffffffff));
281 return 0; 284 return 0;
282 } 285 }
283 return 1; 286 return 1;
284} 287}
285 288
286/* 289/*
@@ -292,196 +295,196 @@ sseek(char *dev, unsigned int fd, unsigned long s) {
292 * have to be modified and written back. 295 * have to be modified and written back.
293 */ 296 */
294struct sector { 297struct sector {
295 struct sector *next; 298 struct sector *next;
296 unsigned long sectornumber; 299 unsigned long sectornumber;
297 int to_be_written; 300 int to_be_written;
298 char data[512]; 301 char data[512];
299} *sectorhead; 302} *sectorhead;
300 303
301static void 304static void free_sectors(void)
302free_sectors(void) { 305{
303 struct sector *s; 306 struct sector *s;
304 307
305 while (sectorhead) { 308 while (sectorhead) {
306 s = sectorhead; 309 s = sectorhead;
307 sectorhead = s->next; 310 sectorhead = s->next;
308 free(s); 311 free(s);
309 } 312 }
310} 313}
311 314
312static struct sector * 315static struct sector *get_sector(char *dev, int fd, unsigned long sno)
313get_sector(char *dev, int fd, unsigned long sno) { 316{
314 struct sector *s; 317 struct sector *s;
315
316 for(s = sectorhead; s; s = s->next)
317 if(s->sectornumber == sno)
318 return s;
319 318
320 if (!sseek(dev, fd, sno)) 319 for (s = sectorhead; s; s = s->next)
321 return 0; 320 if (s->sectornumber == sno)
321 return s;
322 322
323 if (!(s = (struct sector *) malloc(sizeof(struct sector)))) 323 if (!sseek(dev, fd, sno))
324 fatal("out of memory - giving up\n"); 324 return 0;
325 325
326 if (read(fd, s->data, sizeof(s->data)) != sizeof(s->data)) { 326 if (!(s = (struct sector *) malloc(sizeof(struct sector))))
327 perror("read"); 327 fatal("out of memory - giving up\n");
328 error("read error on %s - cannot read sector %lu\n", dev, sno);
329 free(s);
330 return 0;
331 }
332 328
333 s->next = sectorhead; 329 if (read(fd, s->data, sizeof(s->data)) != sizeof(s->data)) {
334 sectorhead = s; 330 perror("read");
335 s->sectornumber = sno; 331 error("read error on %s - cannot read sector %lu\n", dev, sno);
336 s->to_be_written = 0; 332 free(s);
333 return 0;
334 }
337 335
338 return s; 336 s->next = sectorhead;
339} 337 sectorhead = s;
338 s->sectornumber = sno;
339 s->to_be_written = 0;
340 340
341static int 341 return s;
342msdos_signature (struct sector *s) {
343 if (*(unsigned short *) (s->data + 0x1fe) != 0xaa55) {
344 error("ERROR: sector %lu does not have an msdos signature\n",
345 s->sectornumber);
346 return 0;
347 }
348 return 1;
349} 342}
350 343
351static int 344static int msdos_signature(struct sector *s)
352write_sectors(char *dev, int fd) { 345{
353 struct sector *s; 346 if (*(unsigned short *) (s->data + 0x1fe) != 0xaa55) {
354 347 error("ERROR: sector %lu does not have an msdos signature\n",
355 for (s = sectorhead; s; s = s->next) 348 s->sectornumber);
356 if (s->to_be_written) {
357 if (!sseek(dev, fd, s->sectornumber))
358 return 0; 349 return 0;
359 if (write(fd, s->data, sizeof(s->data)) != sizeof(s->data)) {
360 perror("write");
361 error("write error on %s - cannot write sector %lu\n",
362 dev, s->sectornumber);
363 return 0;
364 }
365 s->to_be_written = 0;
366 } 350 }
367 return 1; 351 return 1;
368} 352}
369 353
370static void 354static int write_sectors(char *dev, int fd)
371ulong_to_chars(unsigned long u, char *uu) { 355{
372 int i; 356 struct sector *s;
373 357
374 for(i=0; i<4; i++) { 358 for (s = sectorhead; s; s = s->next)
375 uu[i] = (u & 0xff); 359 if (s->to_be_written) {
376 u >>= 8; 360 if (!sseek(dev, fd, s->sectornumber))
377 } 361 return 0;
362 if (write(fd, s->data, sizeof(s->data)) != sizeof(s->data)) {
363 perror("write");
364 error("write error on %s - cannot write sector %lu\n",
365 dev, s->sectornumber);
366 return 0;
367 }
368 s->to_be_written = 0;
369 }
370 return 1;
378} 371}
379 372
380static unsigned long 373static void ulong_to_chars(unsigned long u, char *uu)
381chars_to_ulong(unsigned char *uu) { 374{
382 int i; 375 int i;
383 unsigned long u = 0;
384 376
385 for(i=3; i>=0; i--) 377 for (i = 0; i < 4; i++) {
386 u = (u << 8) | uu[i]; 378 uu[i] = (u & 0xff);
387 return u; 379 u >>= 8;
380 }
388} 381}
389 382
390static int 383static unsigned long chars_to_ulong(unsigned char *uu)
391save_sectors(char *dev, int fdin) { 384{
392 struct sector *s; 385 int i;
393 char ss[516]; 386 unsigned long u = 0;
394 int fdout;
395
396 fdout = open(save_sector_file, O_WRONLY | O_CREAT, 0444);
397 if (fdout < 0) {
398 perror(save_sector_file);
399 error("cannot open partition sector save file (%s)\n",
400 save_sector_file);
401 return 0;
402 }
403 387
404 for (s = sectorhead; s; s = s->next) 388 for (i = 3; i >= 0; i--)
405 if (s->to_be_written) { 389 u = (u << 8) | uu[i];
406 ulong_to_chars(s->sectornumber, ss); 390 return u;
407 if (!sseek(dev, fdin, s->sectornumber)) 391}
408 return 0; 392
409 if (read(fdin, ss+4, 512) != 512) { 393static int save_sectors(char *dev, int fdin)
410 perror("read"); 394{
411 error("read error on %s - cannot read sector %lu\n", 395 struct sector *s;
412 dev, s->sectornumber); 396 char ss[516];
413 return 0; 397 int fdout;
414 } 398
415 if (write(fdout, ss, sizeof(ss)) != sizeof(ss)) { 399 fdout = open(save_sector_file, O_WRONLY | O_CREAT, 0444);
416 perror("write"); 400 if (fdout < 0) {
417 error("write error on %s\n"), save_sector_file; 401 perror(save_sector_file);
402 error("cannot open partition sector save file (%s)\n",
403 save_sector_file);
418 return 0; 404 return 0;
419 }
420 } 405 }
421 return 1; 406
407 for (s = sectorhead; s; s = s->next)
408 if (s->to_be_written) {
409 ulong_to_chars(s->sectornumber, ss);
410 if (!sseek(dev, fdin, s->sectornumber))
411 return 0;
412 if (read(fdin, ss + 4, 512) != 512) {
413 perror("read");
414 error("read error on %s - cannot read sector %lu\n",
415 dev, s->sectornumber);
416 return 0;
417 }
418 if (write(fdout, ss, sizeof(ss)) != sizeof(ss)) {
419 perror("write");
420 error("write error on %s\n"), save_sector_file;
421 return 0;
422 }
423 }
424 return 1;
422} 425}
423 426
424static void reread_disk_partition(char *dev, int fd); 427static void reread_disk_partition(char *dev, int fd);
425 428
426static int 429static int restore_sectors(char *dev)
427restore_sectors(char *dev) { 430{
428 int fdin, fdout, ct; 431 int fdin, fdout, ct;
429 struct stat statbuf; 432 struct stat statbuf;
430 char *ss0, *ss; 433 char *ss0, *ss;
431 unsigned long sno; 434 unsigned long sno;
432 435
433 if (stat(restore_sector_file, &statbuf) < 0) { 436 if (stat(restore_sector_file, &statbuf) < 0) {
434 perror(restore_sector_file); 437 perror(restore_sector_file);
435 error("cannot stat partition restore file (%s)\n", 438 error("cannot stat partition restore file (%s)\n",
436 restore_sector_file); 439 restore_sector_file);
437 return 0; 440 return 0;
438 } 441 }
439 if (statbuf.st_size % 516) { 442 if (statbuf.st_size % 516) {
440 error("partition restore file has wrong size - not restoring\n"); 443 error("partition restore file has wrong size - not restoring\n");
441 return 0; 444 return 0;
442 } 445 }
443 if (!(ss = (char *) malloc(statbuf.st_size))) { 446 if (!(ss = (char *) malloc(statbuf.st_size))) {
444 error("out of memory?\n"); 447 error("out of memory?\n");
445 return 0; 448 return 0;
446 } 449 }
447 fdin = open(restore_sector_file, O_RDONLY); 450 fdin = open(restore_sector_file, O_RDONLY);
448 if (fdin < 0) { 451 if (fdin < 0) {
449 perror(restore_sector_file); 452 perror(restore_sector_file);
450 error("cannot open partition restore file (%s)\n", 453 error("cannot open partition restore file (%s)\n",
451 restore_sector_file); 454 restore_sector_file);
452 return 0; 455 return 0;
453 } 456 }
454 if (read(fdin, ss, statbuf.st_size) != statbuf.st_size) { 457 if (read(fdin, ss, statbuf.st_size) != statbuf.st_size) {
455 perror("read"); 458 perror("read");
456 error("error reading %s\n"), restore_sector_file; 459 error("error reading %s\n"), restore_sector_file;
457 return 0; 460 return 0;
458 } 461 }
459 462
460 fdout = open(dev, O_WRONLY); 463 fdout = open(dev, O_WRONLY);
461 if (fdout < 0) { 464 if (fdout < 0) {
462 perror(dev); 465 perror(dev);
463 error("cannot open device %s for writing\n"), dev; 466 error("cannot open device %s for writing\n"), dev;
464 return 0; 467 return 0;
465 } 468 }
466 469
467 ss0 = ss; 470 ss0 = ss;
468 ct = statbuf.st_size/516; 471 ct = statbuf.st_size / 516;
469 while(ct--) { 472 while (ct--) {
470 sno = chars_to_ulong(ss); 473 sno = chars_to_ulong(ss);
471 if (!sseek(dev, fdout, sno)) 474 if (!sseek(dev, fdout, sno))
472 return 0; 475 return 0;
473 if (write(fdout, ss+4, 512) != 512) { 476 if (write(fdout, ss + 4, 512) != 512) {
474 perror(dev); 477 perror(dev);
475 error("error writing sector %lu on %s\n", sno, dev); 478 error("error writing sector %lu on %s\n", sno, dev);
476 return 0; 479 return 0;
480 }
481 ss += 516;
477 } 482 }
478 ss += 516; 483 free(ss0);
479 }
480 free(ss0);
481 484
482 reread_disk_partition(dev, fdout); 485 reread_disk_partition(dev, fdout);
483 486
484 return 1; 487 return 1;
485} 488}
486 489
487/* 490/*
@@ -511,105 +514,111 @@ struct geometry {
511 unsigned long heads, sectors, cylinders; 514 unsigned long heads, sectors, cylinders;
512} B, F, U; 515} B, F, U;
513 516
514static void 517static void get_cylindersize(char *dev, int fd, int silent)
515get_cylindersize(char *dev, int fd, int silent) { 518{
516 struct hd_geometry g; 519 struct hd_geometry g;
517 int ioctl_ok = 0; 520 int ioctl_ok = 0;
518 521
519 B.heads = B.sectors = B.cylinders = 0; 522 B.heads = B.sectors = B.cylinders = 0;
520 523
521 if (!ioctl(fd, HDIO_GETGEO, &g)) { 524 if (!ioctl(fd, HDIO_GETGEO, &g)) {
522 ioctl_ok = 1; 525 ioctl_ok = 1;
523 526
524 B.heads = g.heads; 527 B.heads = g.heads;
525 B.sectors = g.sectors; 528 B.sectors = g.sectors;
526 B.cylinders = g.cylinders; 529 B.cylinders = g.cylinders;
527 } 530 }
528 531
529 if (U.heads) 532 if (U.heads)
530 B.heads = U.heads; 533 B.heads = U.heads;
531 if (U.sectors) 534 if (U.sectors)
532 B.sectors = U.sectors; 535 B.sectors = U.sectors;
533 if (U.cylinders) 536 if (U.cylinders)
534 B.cylinders = U.cylinders; 537 B.cylinders = U.cylinders;
535 538
536 B.cylindersize = B.heads * B.sectors; 539 B.cylindersize = B.heads * B.sectors;
537 540
538 if (ioctl_ok) { 541 if (ioctl_ok) {
539 if (g.start && !force) { 542 if (g.start && !force) {
540 warn( 543 warn
541 "Warning: start=%d - this looks like a partition rather than\n" 544 ("Warning: start=%d - this looks like a partition rather than\n"
542 "the entire disk. Using fdisk on it is probably meaningless.\n" 545 "the entire disk. Using fdisk on it is probably meaningless.\n"
543 "[Use the --force option if you really want this]\n", g.start); 546 "[Use the --force option if you really want this]\n",
544 exit(1); 547 g.start);
545 } 548 exit(1);
546 if (B.heads != g.heads) 549 }
547 warn("Warning: HDIO_GETGEO says that there are %d heads\n", 550 if (B.heads != g.heads)
548 g.heads); 551 warn("Warning: HDIO_GETGEO says that there are %d heads\n",
549 if (B.sectors != g.sectors) 552 g.heads);
550 warn("Warning: HDIO_GETGEO says that there are %d sectors\n", 553 if (B.sectors != g.sectors)
551 g.sectors); 554 warn("Warning: HDIO_GETGEO says that there are %d sectors\n",
552 if (B.cylinders != g.cylinders) 555 g.sectors);
553 warn("Warning: HDIO_GETGEO says that there are %d cylinders\n", 556 if (B.cylinders != g.cylinders)
554 g.cylinders); 557 warn("Warning: HDIO_GETGEO says that there are %d cylinders\n",
555 } else if (!silent) 558 g.cylinders);
556 if (!B.heads || !B.sectors || !B.cylinders) 559 } else if (!silent)
557 printf("Disk %s: cannot get geometry\n", dev); 560 if (!B.heads || !B.sectors || !B.cylinders)
558 if (B.sectors > 63) 561 printf("Disk %s: cannot get geometry\n", dev);
559 warn("Warning: unlikely number of sectors (%d - usually at most 63\n" 562 if (B.sectors > 63)
560 "This will give problems with all software that uses C/H/S addressing.\n", 563 warn
561 B.sectors); 564 ("Warning: unlikely number of sectors (%d - usually at most 63\n"
562 if (!silent) 565 "This will give problems with all software that uses C/H/S addressing.\n",
563 printf("\nDisk %s: %lu cylinders, %lu heads, %lu sectors/track\n", 566 B.sectors);
564 dev, B.cylinders, B.heads, B.sectors); 567 if (!silent)
565} 568 printf("\nDisk %s: %lu cylinders, %lu heads, %lu sectors/track\n",
566 569 dev, B.cylinders, B.heads, B.sectors);
567typedef struct { unsigned char h,s,c; } chs; /* has some c bits in s */ 570}
568static chs zero_chs = { 0,0,0 }; 571
569 572typedef struct {
570typedef struct { unsigned long h,s,c; } longchs; 573 unsigned char h, s, c;
574} chs; /* has some c bits in s */
575static chs zero_chs = { 0, 0, 0 };
576
577typedef struct {
578 unsigned long h, s, c;
579} longchs;
571static longchs zero_longchs; 580static longchs zero_longchs;
572 581
573static chs 582static chs longchs_to_chs(longchs aa, struct geometry G)
574longchs_to_chs (longchs aa, struct geometry G) { 583{
575 chs a; 584 chs a;
576 585
577 if (aa.h < 256 && aa.s < 64 && aa.c < 1024) { 586 if (aa.h < 256 && aa.s < 64 && aa.c < 1024) {
578 a.h = aa.h; 587 a.h = aa.h;
579 a.s = aa.s | ((aa.c >> 2) & 0xc0); 588 a.s = aa.s | ((aa.c >> 2) & 0xc0);
580 a.c = (aa.c & 0xff); 589 a.c = (aa.c & 0xff);
581 } else if (G.heads && G.sectors) { 590 } else if (G.heads && G.sectors) {
582 a.h = G.heads - 1; 591 a.h = G.heads - 1;
583 a.s = G.sectors | 0xc0; 592 a.s = G.sectors | 0xc0;
584 a.c = 0xff; 593 a.c = 0xff;
585 } else 594 } else
586 a = zero_chs; 595 a = zero_chs;
587 return a; 596 return a;
588} 597}
589 598
590static longchs 599static longchs chs_to_longchs(chs a)
591chs_to_longchs (chs a) { 600{
592 longchs aa; 601 longchs aa;
593 602
594 aa.h = a.h; 603 aa.h = a.h;
595 aa.s = (a.s & 0x3f); 604 aa.s = (a.s & 0x3f);
596 aa.c = (a.s & 0xc0); 605 aa.c = (a.s & 0xc0);
597 aa.c = (aa.c << 2) + a.c; 606 aa.c = (aa.c << 2) + a.c;
598 return aa;
599}
600
601static longchs
602ulong_to_longchs (unsigned long sno, struct geometry G) {
603 longchs aa;
604
605 if (G.heads && G.sectors && G.cylindersize) {
606 aa.s = 1 + sno % G.sectors;
607 aa.h = (sno / G.sectors) % G.heads;
608 aa.c = sno / G.cylindersize;
609 return aa; 607 return aa;
610 } else { 608}
611 return zero_longchs; 609
612 } 610static longchs ulong_to_longchs(unsigned long sno, struct geometry G)
611{
612 longchs aa;
613
614 if (G.heads && G.sectors && G.cylindersize) {
615 aa.s = 1 + sno % G.sectors;
616 aa.h = (sno / G.sectors) % G.heads;
617 aa.c = sno / G.cylindersize;
618 return aa;
619 } else {
620 return zero_longchs;
621 }
613} 622}
614 623
615//static unsigned long 624//static unsigned long
@@ -617,9 +626,9 @@ ulong_to_longchs (unsigned long sno, struct geometry G) {
617// return (aa.c*G.cylindersize + aa.h*G.sectors + aa.s - 1); 626// return (aa.c*G.cylindersize + aa.h*G.sectors + aa.s - 1);
618//} 627//}
619 628
620static chs 629static chs ulong_to_chs(unsigned long sno, struct geometry G)
621ulong_to_chs (unsigned long sno, struct geometry G) { 630{
622 return longchs_to_chs(ulong_to_longchs(sno, G), G); 631 return longchs_to_chs(ulong_to_longchs(sno, G), G);
623} 632}
624 633
625//static unsigned long 634//static unsigned long
@@ -627,34 +636,34 @@ ulong_to_chs (unsigned long sno, struct geometry G) {
627// return longchs_to_ulong(chs_to_longchs(a), G); 636// return longchs_to_ulong(chs_to_longchs(a), G);
628//} 637//}
629 638
630static int 639static int is_equal_chs(chs a, chs b)
631is_equal_chs (chs a, chs b) { 640{
632 return (a.h == b.h && a.s == b.s && a.c == b.c); 641 return (a.h == b.h && a.s == b.s && a.c == b.c);
633} 642}
634 643
635static int 644static int chs_ok(chs a, char *v, char *w)
636chs_ok (chs a, char *v, char *w) { 645{
637 longchs aa = chs_to_longchs(a); 646 longchs aa = chs_to_longchs(a);
638 int ret = 1; 647 int ret = 1;
639 648
640 if (is_equal_chs(a, zero_chs)) 649 if (is_equal_chs(a, zero_chs))
641 return 1; 650 return 1;
642 if (B.heads && aa.h >= B.heads) { 651 if (B.heads && aa.h >= B.heads) {
643 warn("%s of partition %s has impossible value for head: " 652 warn("%s of partition %s has impossible value for head: "
644 "%d (should be in 0-%d)\n", w, v, aa.h, B.heads-1); 653 "%d (should be in 0-%d)\n", w, v, aa.h, B.heads - 1);
645 ret = 0; 654 ret = 0;
646 } 655 }
647 if (B.sectors && (aa.s == 0 || aa.s > B.sectors)) { 656 if (B.sectors && (aa.s == 0 || aa.s > B.sectors)) {
648 warn("%s of partition %s has impossible value for sector: " 657 warn("%s of partition %s has impossible value for sector: "
649 "%d (should be in 1-%d)\n", w, v, aa.s, B.sectors); 658 "%d (should be in 1-%d)\n", w, v, aa.s, B.sectors);
650 ret = 0; 659 ret = 0;
651 } 660 }
652 if (B.cylinders && aa.c >= B.cylinders) { 661 if (B.cylinders && aa.c >= B.cylinders) {
653 warn("%s of partition %s has impossible value for cylinders: " 662 warn("%s of partition %s has impossible value for cylinders: "
654 "%d (should be in 0-%d)\n", w, v, aa.c, B.cylinders-1); 663 "%d (should be in 0-%d)\n", w, v, aa.c, B.cylinders - 1);
655 ret = 0; 664 ret = 0;
656 } 665 }
657 return ret; 666 return ret;
658} 667}
659 668
660/* 669/*
@@ -675,34 +684,33 @@ chs_ok (chs a, char *v, char *w) {
675 684
676/* List of partition types now in i386_sys_types.c */ 685/* List of partition types now in i386_sys_types.c */
677 686
678static const char * 687static const char *sysname(unsigned char type)
679sysname(unsigned char type) { 688{
680 struct systypes *s; 689 struct systypes *s;
681 690
682 for (s = i386_sys_types; s->name; s++) 691 for (s = i386_sys_types; s->name; s++)
683 if (s->type == type) 692 if (s->type == type)
684 return s->name; 693 return s->name;
685 return "Unknown"; 694 return "Unknown";
686} 695}
687 696
688static void 697static void list_types(void)
689list_types(void) { 698{
690 struct systypes *s; 699 struct systypes *s;
691 700
692 printf("Id Name\n\n"); 701 printf("Id Name\n\n");
693 for (s = i386_sys_types; s->name; s++) 702 for (s = i386_sys_types; s->name; s++)
694 printf("%2x %s\n", s->type, s->name); 703 printf("%2x %s\n", s->type, s->name);
695} 704}
696 705
697static int 706static int is_extended(unsigned char type)
698is_extended(unsigned char type) { 707{
699 return (type == EXTENDED_PARTITION 708 return (type == EXTENDED_PARTITION
700 || type == LINUX_EXTENDED 709 || type == LINUX_EXTENDED || type == WIN98_EXTENDED);
701 || type == WIN98_EXTENDED);
702} 710}
703 711
704static int 712static int is_bsd(unsigned char type)
705is_bsd(unsigned char type) { 713{
706 return (type == BSD_PARTITION); 714 return (type == BSD_PARTITION);
707} 715}
708 716
@@ -713,61 +721,64 @@ is_bsd(unsigned char type) {
713/* MS/DOS partition */ 721/* MS/DOS partition */
714 722
715struct partition { 723struct partition {
716 unsigned char bootable; /* 0 or 0x80 */ 724 unsigned char bootable; /* 0 or 0x80 */
717 chs begin_chs; 725 chs begin_chs;
718 unsigned char sys_type; 726 unsigned char sys_type;
719 chs end_chs; 727 chs end_chs;
720 unsigned int start_sect; /* starting sector counting from 0 */ 728 unsigned int start_sect; /* starting sector counting from 0 */
721 unsigned int nr_sects; /* nr of sectors in partition */ 729 unsigned int nr_sects; /* nr of sectors in partition */
722}; 730};
723 731
724/* Unfortunately, partitions are not aligned, and non-Intel machines 732/* Unfortunately, partitions are not aligned, and non-Intel machines
725 are unhappy with non-aligned integers. So, we need a copy by hand. */ 733 are unhappy with non-aligned integers. So, we need a copy by hand. */
726static int 734static int copy_to_int(unsigned char *cp)
727copy_to_int(unsigned char *cp) { 735{
728 unsigned int m; 736 unsigned int m;
729 737
730 m = *cp++; 738 m = *cp++;
731 m += (*cp++ << 8); 739 m += (*cp++ << 8);
732 m += (*cp++ << 16); 740 m += (*cp++ << 16);
733 m += (*cp++ << 24); 741 m += (*cp++ << 24);
734 return m; 742 return m;
735} 743}
736 744
737static void 745static void copy_from_int(int m, char *cp)
738copy_from_int(int m, char *cp) { 746{
739 *cp++ = (m & 0xff); m >>= 8; 747 *cp++ = (m & 0xff);
740 *cp++ = (m & 0xff); m >>= 8; 748 m >>= 8;
741 *cp++ = (m & 0xff); m >>= 8; 749 *cp++ = (m & 0xff);
742 *cp++ = (m & 0xff); 750 m >>= 8;
743} 751 *cp++ = (m & 0xff);
744 752 m >>= 8;
745static void 753 *cp++ = (m & 0xff);
746copy_to_part(char *cp, struct partition *p) { 754}
747 p->bootable = *cp++; 755
748 p->begin_chs.h = *cp++; 756static void copy_to_part(char *cp, struct partition *p)
749 p->begin_chs.s = *cp++; 757{
750 p->begin_chs.c = *cp++; 758 p->bootable = *cp++;
751 p->sys_type = *cp++; 759 p->begin_chs.h = *cp++;
752 p->end_chs.h = *cp++; 760 p->begin_chs.s = *cp++;
753 p->end_chs.s = *cp++; 761 p->begin_chs.c = *cp++;
754 p->end_chs.c = *cp++; 762 p->sys_type = *cp++;
755 p->start_sect = copy_to_int(cp); 763 p->end_chs.h = *cp++;
756 p->nr_sects = copy_to_int(cp+4); 764 p->end_chs.s = *cp++;
757} 765 p->end_chs.c = *cp++;
758 766 p->start_sect = copy_to_int(cp);
759static void 767 p->nr_sects = copy_to_int(cp + 4);
760copy_from_part(struct partition *p, char *cp) { 768}
761 *cp++ = p->bootable; 769
762 *cp++ = p->begin_chs.h; 770static void copy_from_part(struct partition *p, char *cp)
763 *cp++ = p->begin_chs.s; 771{
764 *cp++ = p->begin_chs.c; 772 *cp++ = p->bootable;
765 *cp++ = p->sys_type; 773 *cp++ = p->begin_chs.h;
766 *cp++ = p->end_chs.h; 774 *cp++ = p->begin_chs.s;
767 *cp++ = p->end_chs.s; 775 *cp++ = p->begin_chs.c;
768 *cp++ = p->end_chs.c; 776 *cp++ = p->sys_type;
769 copy_from_int(p->start_sect, cp); 777 *cp++ = p->end_chs.h;
770 copy_from_int(p->nr_sects, cp+4); 778 *cp++ = p->end_chs.s;
779 *cp++ = p->end_chs.c;
780 copy_from_int(p->start_sect, cp);
781 copy_from_int(p->nr_sects, cp + 4);
771} 782}
772 783
773/* Roughly speaking, Linux doesn't use any of the above fields except 784/* Roughly speaking, Linux doesn't use any of the above fields except
@@ -777,122 +788,125 @@ copy_from_part(struct partition *p, char *cp) {
777 for equality with EXTENDED_PARTITION (and these Disk Manager types). */ 788 for equality with EXTENDED_PARTITION (and these Disk Manager types). */
778 789
779struct part_desc { 790struct part_desc {
780 unsigned long start; 791 unsigned long start;
781 unsigned long size; 792 unsigned long size;
782 unsigned long sector, offset; /* disk location of this info */ 793 unsigned long sector, offset; /* disk location of this info */
783 struct partition p; 794 struct partition p;
784 struct part_desc *ep; /* extended partition containing this one */ 795 struct part_desc *ep; /* extended partition containing this one */
785 int ptype; 796 int ptype;
786#define DOS_TYPE 0 797#define DOS_TYPE 0
787#define BSD_TYPE 1 798#define BSD_TYPE 1
788} zero_part_desc; 799} zero_part_desc;
789 800
790struct part_desc * 801struct part_desc *outer_extended_partition(struct part_desc *p)
791outer_extended_partition(struct part_desc *p) { 802{
792 while (p->ep) 803 while (p->ep)
793 p = p->ep; 804 p = p->ep;
794 return p; 805 return p;
795} 806}
796 807
797static int 808static int is_parent(struct part_desc *pp, struct part_desc *p)
798is_parent(struct part_desc *pp, struct part_desc *p) { 809{
799 while (p) { 810 while (p) {
800 if (pp == p) 811 if (pp == p)
801 return 1; 812 return 1;
802 p = p->ep; 813 p = p->ep;
803 } 814 }
804 return 0; 815 return 0;
805} 816}
806 817
807struct disk_desc { 818struct disk_desc {
808 struct part_desc partitions[128]; 819 struct part_desc partitions[128];
809 int partno; 820 int partno;
810} oldp, newp; 821} oldp, newp;
811 822
812/* determine where on the disk this information goes */ 823/* determine where on the disk this information goes */
813static void 824static void add_sector_and_offset(struct disk_desc *z)
814add_sector_and_offset(struct disk_desc *z) { 825{
815 int pno; 826 int pno;
816 struct part_desc *p; 827 struct part_desc *p;
828
829 for (pno = 0; pno < z->partno; pno++) {
830 p = &(z->partitions[pno]);
831 p->offset = 0x1be + (pno % 4) * sizeof(struct partition);
817 832
818 for (pno = 0; pno < z->partno; pno++) { 833 p->sector = (p->ep ? p->ep->start : 0);
819 p = &(z->partitions[pno]); 834 }
820 p->offset = 0x1be + (pno%4)*sizeof(struct partition);
821 p->sector = (p->ep ? p->ep->start : 0);
822 }
823} 835}
824 836
825/* tell the kernel to reread the partition tables */ 837/* tell the kernel to reread the partition tables */
826static int 838static int reread_ioctl(int fd)
827reread_ioctl(int fd) { 839{
828 if(ioctl(fd, BLKRRPART)) { 840 if (ioctl(fd, BLKRRPART)) {
829 perror("BLKRRPART"); 841 perror("BLKRRPART");
830 return -1; 842 return -1;
831 } 843 }
832 return 0; 844 return 0;
833} 845}
834 846
835static int 847static int is_blockdev(int fd)
836is_blockdev(int fd) { 848{
837 struct stat statbuf; 849 struct stat statbuf;
838 850
839 return(fstat(fd, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)); 851 return (fstat(fd, &statbuf) == 0 && S_ISBLK(statbuf.st_mode));
840} 852}
841 853
842/* reread after writing */ 854/* reread after writing */
843static void 855static void reread_disk_partition(char *dev, int fd)
844reread_disk_partition(char *dev, int fd) { 856{
845 printf("Re-reading the partition table ...\n"); 857 printf("Re-reading the partition table ...\n");
846 fflush(stdout); 858 fflush(stdout);
847 sync(); 859 sync();
848 sleep(3); /* superfluous since 1.3.20 */ 860 sleep(3); /* superfluous since 1.3.20 */
849 861
850 if(reread_ioctl(fd) && is_blockdev(fd)) 862 if (reread_ioctl(fd) && is_blockdev(fd))
851 printf("The command to re-read the partition table failed\n" 863 printf("The command to re-read the partition table failed\n"
852 "Reboot your system now, before using mkfs\n"); 864 "Reboot your system now, before using mkfs\n");
853 865
854 if (close(fd)) { 866 if (close(fd)) {
855 perror(dev); 867 perror(dev);
856 printf("Error closing %s\n", dev); 868 printf("Error closing %s\n", dev);
857 } 869 }
858 printf("\n"); 870 printf("\n");
859} 871}
860 872
861/* find Linux name of this partition, assuming that it will have a name */ 873/* find Linux name of this partition, assuming that it will have a name */
862static int 874static int index_to_linux(int pno, struct disk_desc *z)
863index_to_linux(int pno, struct disk_desc *z) { 875{
864 int i, ct = 1; 876 int i, ct = 1;
865 struct part_desc *p = &(z->partitions[0]); 877 struct part_desc *p = &(z->partitions[0]);
866 for (i=0; i<pno; i++,p++) 878
867 if(i < 4 || (p->size > 0 && !is_extended(p->p.sys_type))) 879 for (i = 0; i < pno; i++, p++)
868 ct++; 880 if (i < 4 || (p->size > 0 && !is_extended(p->p.sys_type)))
869 return ct; 881 ct++;
870} 882 return ct;
871 883}
872static int 884
873linux_to_index(int lpno, struct disk_desc *z) { 885static int linux_to_index(int lpno, struct disk_desc *z)
874 int i, ct = 0; 886{
875 struct part_desc *p = &(z->partitions[0]); 887 int i, ct = 0;
876 for (i=0; i<z->partno && ct < lpno; i++,p++) 888 struct part_desc *p = &(z->partitions[0]);
877 if((i < 4 || (p->size > 0 && !is_extended(p->p.sys_type))) 889
878 && ++ct == lpno) 890 for (i = 0; i < z->partno && ct < lpno; i++, p++)
879 return i; 891 if ((i < 4 || (p->size > 0 && !is_extended(p->p.sys_type)))
880 return -1; 892 && ++ct == lpno)
893 return i;
894 return -1;
881} 895}
882 896
883static int 897static int asc_to_index(char *pnam, struct disk_desc *z)
884asc_to_index(char *pnam, struct disk_desc *z) { 898{
885 int pnum, pno; 899 int pnum, pno;
886 900
887 if (*pnam == '#') { 901 if (*pnam == '#') {
888 pno = atoi(pnam+1); 902 pno = atoi(pnam + 1);
889 } else { 903 } else {
890 pnum = atoi(pnam); 904 pnum = atoi(pnam);
891 pno = linux_to_index(pnum, z); 905 pno = linux_to_index(pnum, z);
892 } 906 }
893 if (!(pno >= 0 && pno < z->partno)) 907 if (!(pno >= 0 && pno < z->partno))
894 fatal("%s: no such partition\n"), pnam; 908 fatal("%s: no such partition\n"), pnam;
895 return pno; 909 return pno;
896} 910}
897 911
898/* 912/*
@@ -910,523 +924,573 @@ static int one_only = 0;
910static int one_only_pno; 924static int one_only_pno;
911static int increment = 0; 925static int increment = 0;
912 926
913static void 927static void set_format(char c)
914set_format(char c) { 928{
915 switch(c) { 929 switch (c) {
916 default: 930 default:
917 printf("unrecognized format - using sectors\n"); 931 printf("unrecognized format - using sectors\n");
918 case 'S': specified_format = F_SECTOR; break; 932 case 'S':
919 case 'B': specified_format = F_BLOCK; break; 933 specified_format = F_SECTOR;
920 case 'C': specified_format = F_CYLINDER; break; 934 break;
921 case 'M': specified_format = F_MEGABYTE; break; 935 case 'B':
922 } 936 specified_format = F_BLOCK;
937 break;
938 case 'C':
939 specified_format = F_CYLINDER;
940 break;
941 case 'M':
942 specified_format = F_MEGABYTE;
943 break;
944 }
923} 945}
924 946
925static unsigned long 947static unsigned long unitsize(int format)
926unitsize(int format) { 948{
927 default_format = (B.cylindersize ? F_CYLINDER : F_MEGABYTE); 949 default_format = (B.cylindersize ? F_CYLINDER : F_MEGABYTE);
928 if (!format && !(format = specified_format)) 950 if (!format && !(format = specified_format))
929 format = default_format; 951 format = default_format;
930 952
931 switch(format) { 953 switch (format) {
932 default: 954 default:
933 case F_CYLINDER: 955 case F_CYLINDER:
934 if(B.cylindersize) 956 if (B.cylindersize)
935 return B.cylindersize; 957 return B.cylindersize;
936 case F_SECTOR: 958 case F_SECTOR:
937 return 1; 959 return 1;
938 case F_BLOCK: 960 case F_BLOCK:
939 return 2; 961 return 2;
940 case F_MEGABYTE: 962 case F_MEGABYTE:
941 return 2048; 963 return 2048;
942 } 964 }
943} 965}
944 966
945static unsigned long 967static unsigned long get_disksize(int format)
946get_disksize(int format) { 968{
947 unsigned long cs = B.cylinders; 969 unsigned long cs = B.cylinders;
948 if (cs && leave_last) 970
949 cs--; 971 if (cs && leave_last)
950 return (cs * B.cylindersize) / unitsize(format); 972 cs--;
973 return (cs * B.cylindersize) / unitsize(format);
951} 974}
952 975
953static void 976static void out_partition_header(char *dev, int format, struct geometry G)
954out_partition_header(char *dev, int format, struct geometry G) { 977{
955 if (dump) { 978 if (dump) {
956 printf("# partition table of %s\n", dev); 979 printf("# partition table of %s\n", dev);
957 printf("unit: sectors\n\n"); 980 printf("unit: sectors\n\n");
958 return; 981 return;
959 } 982 }
960 983
961 default_format = (G.cylindersize ? F_CYLINDER : F_MEGABYTE); 984 default_format = (G.cylindersize ? F_CYLINDER : F_MEGABYTE);
962 if (!format && !(format = specified_format)) 985 if (!format && !(format = specified_format))
963 format = default_format; 986 format = default_format;
964 987
965 switch(format) { 988 switch (format) {
966 default: 989 default:
967 printf("unimplemented format - using %s\n", 990 printf("unimplemented format - using %s\n",
968 G.cylindersize ? "cylinders" : "sectors"); 991 G.cylindersize ? "cylinders" : "sectors");
969 case F_CYLINDER: 992 case F_CYLINDER:
970 if (G.cylindersize) { 993 if (G.cylindersize) {
971 printf("Units = cylinders of %lu bytes, blocks of 1024 bytes" 994 printf("Units = cylinders of %lu bytes, blocks of 1024 bytes"
972 ", counting from %d\n\n", 995 ", counting from %d\n\n",
973 G.cylindersize<<9, increment); 996 G.cylindersize << 9, increment);
974 printf(" Device Boot Start End #cyls #blocks Id System\n"); 997 printf
975 break; 998 (" Device Boot Start End #cyls #blocks Id System\n");
976 } 999 break;
977 /* fall through */ 1000 }
978 case F_SECTOR: 1001 /* fall through */
979 printf("Units = sectors of 512 bytes, counting from %d\n\n", 1002 case F_SECTOR:
980 increment); 1003 printf("Units = sectors of 512 bytes, counting from %d\n\n",
981 printf(" Device Boot Start End #sectors Id System\n"); 1004 increment);
982 break; 1005 printf
983 case F_BLOCK: 1006 (" Device Boot Start End #sectors Id System\n");
984 printf("Units = blocks of 1024 bytes, counting from %d\n\n", 1007 break;
985 increment); 1008 case F_BLOCK:
986 printf(" Device Boot Start End #blocks Id System\n"); 1009 printf("Units = blocks of 1024 bytes, counting from %d\n\n",
987 break; 1010 increment);
988 case F_MEGABYTE: 1011 printf
989 printf("Units = megabytes of 1048576 bytes, blocks of 1024 bytes" 1012 (" Device Boot Start End #blocks Id System\n");
990 ", counting from %d\n\n", increment); 1013 break;
991 printf(" Device Boot Start End MB #blocks Id System\n"); 1014 case F_MEGABYTE:
992 break; 1015 printf("Units = megabytes of 1048576 bytes, blocks of 1024 bytes"
993 } 1016 ", counting from %d\n\n", increment);
1017 printf
1018 (" Device Boot Start End MB #blocks Id System\n");
1019 break;
1020 }
994} 1021}
995 1022
996static void 1023static void
997out_rounddown(int width, unsigned long n, unsigned long unit, int inc) { 1024out_rounddown(int width, unsigned long n, unsigned long unit, int inc)
998 printf("%*lu", width, inc + n/unit); 1025{
999 if (unit != 1) 1026 printf("%*lu", width, inc + n / unit);
1000 putchar((n % unit) ? '+' : ' '); 1027 if (unit != 1)
1001 putchar(' '); 1028 putchar((n % unit) ? '+' : ' ');
1029 putchar(' ');
1002} 1030}
1003 1031
1004static void 1032static void
1005out_roundup(int width, unsigned long n, unsigned long unit, int inc) { 1033out_roundup(int width, unsigned long n, unsigned long unit, int inc)
1006 if (n == (unsigned long)(-1)) 1034{
1007 printf("%*s", width, "-"); 1035 if (n == (unsigned long) (-1))
1008 else 1036 printf("%*s", width, "-");
1009 printf("%*lu", width, inc + n/unit); 1037 else
1010 if (unit != 1) 1038 printf("%*lu", width, inc + n / unit);
1011 putchar(((n+1) % unit) ? '-' : ' '); 1039 if (unit != 1)
1012 putchar(' '); 1040 putchar(((n + 1) % unit) ? '-' : ' ');
1041 putchar(' ');
1013} 1042}
1014 1043
1015static void 1044static void
1016out_roundup_size(int width, unsigned long n, unsigned long unit) { 1045out_roundup_size(int width, unsigned long n, unsigned long unit)
1017 printf("%*lu", width, (n+unit-1)/unit); 1046{
1018 if (unit != 1) 1047 printf("%*lu", width, (n + unit - 1) / unit);
1019 putchar((n % unit) ? '-' : ' '); 1048 if (unit != 1)
1020 putchar(' '); 1049 putchar((n % unit) ? '-' : ' ');
1050 putchar(' ');
1021} 1051}
1022 1052
1023static int 1053static int get_fdisk_geometry(struct part_desc *p)
1024get_fdisk_geometry(struct part_desc *p) { 1054{
1025 chs b = p->p.end_chs; 1055 chs b = p->p.end_chs;
1026 longchs bb = chs_to_longchs(b); 1056 longchs bb = chs_to_longchs(b);
1027 F.heads = bb.h+1; 1057
1028 F.sectors = bb.s; 1058 F.heads = bb.h + 1;
1029 F.cylindersize = F.heads*F.sectors; 1059 F.sectors = bb.s;
1030 return (F.sectors != B.sectors || F.heads != B.heads); 1060 F.cylindersize = F.heads * F.sectors;
1061 return (F.sectors != B.sectors || F.heads != B.heads);
1031} 1062}
1032 1063
1033static void 1064static void
1034out_partition(char *dev, int format, struct part_desc *p, 1065out_partition(char *dev, int format, struct part_desc *p,
1035 struct disk_desc *z, struct geometry G) { 1066 struct disk_desc *z, struct geometry G)
1036 unsigned long start, end, size; 1067{
1037 int pno, lpno; 1068 unsigned long start, end, size;
1038 1069 int pno, lpno;
1039 if (!format && !(format = specified_format)) 1070
1040 format = default_format; 1071 if (!format && !(format = specified_format))
1041 1072 format = default_format;
1042 pno = p - &(z->partitions[0]); /* our index */ 1073
1043 lpno = index_to_linux(pno, z); /* name of next one that has a name */ 1074 pno = p - &(z->partitions[0]); /* our index */
1044 if(pno == linux_to_index(lpno, z)) /* was that us? */ 1075 lpno = index_to_linux(pno, z); /* name of next one that has a name */
1045 printf("%8s%-2u", dev, lpno); /* yes */ 1076 if (pno == linux_to_index(lpno, z)) /* was that us? */
1046 else if(show_extended) 1077 printf("%8s%-2u", dev, lpno); /* yes */
1047 printf(" - "); 1078 else if (show_extended)
1048 else 1079 printf(" - ");
1049 return; 1080 else
1050 putchar(dump ? ':' : ' '); 1081 return;
1051 1082 putchar(dump ? ':' : ' ');
1052 start = p->start; 1083
1053 end = p->start + p->size - 1; 1084 start = p->start;
1054 size = p->size; 1085 end = p->start + p->size - 1;
1055 1086 size = p->size;
1056 if (dump) { 1087
1057 printf(" start=%9lu", start); 1088 if (dump) {
1058 printf(", size=%8lu", size); 1089 printf(" start=%9lu", start);
1059 if (p->ptype == DOS_TYPE) { 1090 printf(", size=%8lu", size);
1060 printf(", Id=%2x", p->p.sys_type); 1091 if (p->ptype == DOS_TYPE) {
1061 if (p->p.bootable == 0x80) 1092 printf(", Id=%2x", p->p.sys_type);
1062 printf(", bootable"); 1093 if (p->p.bootable == 0x80)
1094 printf(", bootable");
1095 }
1096 printf("\n");
1097 return;
1063 } 1098 }
1064 printf("\n"); 1099
1065 return; 1100 if (p->ptype != DOS_TYPE || p->p.bootable == 0)
1066 } 1101 printf(" ");
1067 1102 else if (p->p.bootable == 0x80)
1068 if(p->ptype != DOS_TYPE || p->p.bootable == 0) 1103 printf(" * ");
1069 printf(" "); 1104 else
1070 else if(p->p.bootable == 0x80) 1105 printf(" ? "); /* garbage */
1071 printf(" * "); 1106
1072 else 1107 switch (format) {
1073 printf(" ? "); /* garbage */ 1108 case F_CYLINDER:
1074 1109 if (G.cylindersize) {
1075 switch(format) { 1110 out_rounddown(6, start, G.cylindersize, increment);
1076 case F_CYLINDER: 1111 out_roundup(6, end, G.cylindersize, increment);
1077 if (G.cylindersize) { 1112 out_roundup_size(6, size, G.cylindersize);
1078 out_rounddown(6, start, G.cylindersize, increment); 1113 out_rounddown(8, size, 2, 0);
1079 out_roundup(6, end, G.cylindersize, increment); 1114 break;
1080 out_roundup_size(6, size, G.cylindersize); 1115 }
1081 out_rounddown(8, size, 2, 0); 1116 /* fall through */
1082 break; 1117 default:
1083 } 1118 case F_SECTOR:
1084 /* fall through */ 1119 out_rounddown(9, start, 1, increment);
1085 default: 1120 out_roundup(9, end, 1, increment);
1086 case F_SECTOR: 1121 out_rounddown(9, size, 1, 0);
1087 out_rounddown(9, start, 1, increment); 1122 break;
1088 out_roundup(9, end, 1, increment); 1123 case F_BLOCK:
1089 out_rounddown(9, size, 1, 0);
1090 break;
1091 case F_BLOCK:
1092#if 0 1124#if 0
1093 printf("%8lu,%3lu ", 1125 printf("%8lu,%3lu ",
1094 p->sector/2, ((p->sector & 1) ? 512 : 0) + p->offset); 1126 p->sector / 2, ((p->sector & 1) ? 512 : 0) + p->offset);
1095#endif 1127#endif
1096 out_rounddown(8, start, 2, increment); 1128 out_rounddown(8, start, 2, increment);
1097 out_roundup(8, end, 2, increment); 1129 out_roundup(8, end, 2, increment);
1098 out_rounddown(8, size, 2, 0); 1130 out_rounddown(8, size, 2, 0);
1099 break; 1131 break;
1100 case F_MEGABYTE: 1132 case F_MEGABYTE:
1101 out_rounddown(5, start, 2048, increment); 1133 out_rounddown(5, start, 2048, increment);
1102 out_roundup(5, end, 2048, increment); 1134 out_roundup(5, end, 2048, increment);
1103 out_roundup_size(5, size, 2048); 1135 out_roundup_size(5, size, 2048);
1104 out_rounddown(8, size, 2, 0); 1136 out_rounddown(8, size, 2, 0);
1105 break;
1106 }
1107 if (p->ptype == DOS_TYPE) {
1108 printf(" %2x %s\n",
1109 p->p.sys_type, sysname(p->p.sys_type));
1110 } else {
1111 printf("\n");
1112 }
1113
1114 /* Is chs as we expect? */
1115 if (!quiet && p->ptype == DOS_TYPE) {
1116 chs a, b;
1117 longchs aa, bb;
1118 a = (size ? ulong_to_chs(start,G) : zero_chs);
1119 b = p->p.begin_chs;
1120 aa = chs_to_longchs(a);
1121 bb = chs_to_longchs(b);
1122 if(a.s && !is_equal_chs(a, b))
1123 printf("\t\tstart: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1124 aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1125 a = (size ? ulong_to_chs(end,G) : zero_chs);
1126 b = p->p.end_chs;
1127 aa = chs_to_longchs(a);
1128 bb = chs_to_longchs(b);
1129 if(a.s && !is_equal_chs(a, b))
1130 printf("\t\tend: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1131 aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1132 if(G.cylinders && G.cylinders < 1024 && bb.c > G.cylinders)
1133 printf("partition ends on cylinder %ld, beyond the end of the disk\n",
1134 bb.c);
1135 }
1136}
1137
1138static void
1139out_partitions(char *dev, struct disk_desc *z) {
1140 struct part_desc *p;
1141 int pno, format = 0;
1142
1143 if (z->partno == 0)
1144 printf("No partitions found\n");
1145 else {
1146 for (pno=0; pno < z->partno; pno++) {
1147 p = &(z->partitions[pno]);
1148 if (p->size != 0 && p->p.sys_type != 0) {
1149 if (get_fdisk_geometry(p))
1150 printf(
1151 "Warning: The first partition looks like it was made\n"
1152 " for C/H/S=*/%ld/%ld (instead of %ld/%ld/%ld).\n"
1153 "For this listing I'll assume that geometry.\n",
1154 F.heads, F.sectors, B.cylinders, B.heads, B.sectors);
1155 break; 1137 break;
1156 }
1157 } 1138 }
1158 out_partition_header(dev, format, F); 1139 if (p->ptype == DOS_TYPE) {
1159 for(pno=0; pno < z->partno; pno++) { 1140 printf(" %2x %s\n", p->p.sys_type, sysname(p->p.sys_type));
1160 out_partition(dev, format, &(z->partitions[pno]), z, F); 1141 } else {
1161 if(show_extended && pno%4==3) 1142 printf("\n");
1162 printf("\n"); 1143 }
1144
1145 /* Is chs as we expect? */
1146 if (!quiet && p->ptype == DOS_TYPE) {
1147 chs a, b;
1148 longchs aa, bb;
1149
1150 a = (size ? ulong_to_chs(start, G) : zero_chs);
1151 b = p->p.begin_chs;
1152 aa = chs_to_longchs(a);
1153 bb = chs_to_longchs(b);
1154 if (a.s && !is_equal_chs(a, b))
1155 printf
1156 ("\t\tstart: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1157 aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1158 a = (size ? ulong_to_chs(end, G) : zero_chs);
1159 b = p->p.end_chs;
1160 aa = chs_to_longchs(a);
1161 bb = chs_to_longchs(b);
1162 if (a.s && !is_equal_chs(a, b))
1163 printf
1164 ("\t\tend: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1165 aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1166 if (G.cylinders && G.cylinders < 1024 && bb.c > G.cylinders)
1167 printf
1168 ("partition ends on cylinder %ld, beyond the end of the disk\n",
1169 bb.c);
1163 } 1170 }
1164 }
1165} 1171}
1166 1172
1167static int 1173static void out_partitions(char *dev, struct disk_desc *z)
1168disj(struct part_desc *p, struct part_desc *q) { 1174{
1169 return 1175 struct part_desc *p;
1170 ((p->start + p->size <= q->start) 1176 int pno, format = 0;
1171 || (is_extended(p->p.sys_type) 1177
1172 && q->start + q->size <= p->start + p->size)); 1178 if (z->partno == 0)
1179 printf("No partitions found\n");
1180 else {
1181 for (pno = 0; pno < z->partno; pno++) {
1182 p = &(z->partitions[pno]);
1183 if (p->size != 0 && p->p.sys_type != 0) {
1184 if (get_fdisk_geometry(p))
1185 printf
1186 ("Warning: The first partition looks like it was made\n"
1187 " for C/H/S=*/%ld/%ld (instead of %ld/%ld/%ld).\n"
1188 "For this listing I'll assume that geometry.\n",
1189 F.heads, F.sectors, B.cylinders, B.heads,
1190 B.sectors);
1191 break;
1192 }
1193 }
1194 out_partition_header(dev, format, F);
1195 for (pno = 0; pno < z->partno; pno++) {
1196 out_partition(dev, format, &(z->partitions[pno]), z, F);
1197 if (show_extended && pno % 4 == 3)
1198 printf("\n");
1199 }
1200 }
1173} 1201}
1174 1202
1175static char * 1203static int disj(struct part_desc *p, struct part_desc *q)
1176pnumber(struct part_desc *p, struct disk_desc *z) { 1204{
1177 static char buf[20]; 1205 return ((p->start + p->size <= q->start)
1178 int this, next; 1206 || (is_extended(p->p.sys_type)
1179 struct part_desc *p0 = &(z->partitions[0]); 1207 && q->start + q->size <= p->start + p->size));
1208}
1209
1210static char *pnumber(struct part_desc *p, struct disk_desc *z)
1211{
1212 static char buf[20];
1213 int this, next;
1214 struct part_desc *p0 = &(z->partitions[0]);
1180 1215
1181 this = index_to_linux(p-p0, z); 1216 this = index_to_linux(p - p0, z);
1182 next = index_to_linux(p-p0+1, z); 1217 next = index_to_linux(p - p0 + 1, z);
1183 1218
1184 if (next > this) 1219 if (next > this)
1185 sprintf(buf, "%d", this); 1220 sprintf(buf, "%d", this);
1186 else 1221 else
1187 sprintf(buf, "[%d]", this); 1222 sprintf(buf, "[%d]", this);
1188 return buf; 1223 return buf;
1189} 1224}
1190 1225
1191static int 1226static int partitions_ok(struct disk_desc *z)
1192partitions_ok(struct disk_desc *z) { 1227{
1193 struct part_desc *partitions = &(z->partitions[0]), *p, *q; 1228 struct part_desc *partitions = &(z->partitions[0]), *p, *q;
1194 int partno = z->partno; 1229 int partno = z->partno;
1195 1230
1196#define PNO(p) pnumber(p, z) 1231#define PNO(p) pnumber(p, z)
1197 1232
1198 /* Have at least 4 partitions been defined? */ 1233 /* Have at least 4 partitions been defined? */
1199 if (partno < 4) { 1234 if (partno < 4) {
1200 if (!partno) 1235 if (!partno)
1201 fatal("no partition table present.\n"); 1236 fatal("no partition table present.\n");
1202 else 1237 else
1203 fatal("strange, only %d partitions defined.\n"), partno; 1238 fatal("strange, only %d partitions defined.\n"), partno;
1204 return 0;
1205 }
1206
1207 /* Are the partitions of size 0 marked empty?
1208 And do they have start = 0? And bootable = 0? */
1209 for (p = partitions; p - partitions < partno; p++)
1210 if (p->size == 0) {
1211 if(p->p.sys_type != EMPTY_PARTITION)
1212 warn("Warning: partition %s has size 0 but is not marked Empty\n",
1213 PNO(p));
1214 else if(p->p.bootable != 0)
1215 warn("Warning: partition %s has size 0 and is bootable\n",
1216 PNO(p));
1217 else if(p->p.start_sect != 0)
1218 warn("Warning: partition %s has size 0 and nonzero start\n",
1219 PNO(p));
1220 /* all this is probably harmless, no error return */
1221 }
1222
1223 /* Are the logical partitions contained in their extended partitions? */
1224 for (p = partitions+4; p < partitions+partno; p++)
1225 if (p->ptype == DOS_TYPE)
1226 if (p->size && !is_extended(p->p.sys_type)) {
1227 q = p->ep;
1228 if (p->start < q->start || p->start + p->size > q->start + q->size) {
1229 warn("Warning: partition %s "), PNO(p);
1230 warn("is not contained in partition %s\n"), PNO(q);
1231 return 0;
1232 }
1233 }
1234
1235 /* Are the data partitions mutually disjoint? */
1236 for (p = partitions; p < partitions+partno; p++)
1237 if (p->size && !is_extended(p->p.sys_type))
1238 for (q = p+1; q < partitions+partno; q++)
1239 if (q->size && !is_extended(q->p.sys_type))
1240 if(!((p->start > q-> start) ? disj(q,p) : disj(p,q))) {
1241 warn("Warning: partitions %s "), PNO(p);
1242 warn("and %s overlap\n"), PNO(q);
1243 return 0;
1244 }
1245
1246 /* Are the data partitions and the extended partition
1247 table sectors disjoint? */
1248 for (p = partitions; p < partitions+partno; p++)
1249 if (p->size && !is_extended(p->p.sys_type))
1250 for (q = partitions; q < partitions+partno; q++)
1251 if (is_extended(q->p.sys_type))
1252 if (p->start <= q->start && p->start + p->size > q->start) {
1253 warn("Warning: partition %s contains part of ", PNO(p));
1254 warn("the partition table (sector %lu),\n", q->start);
1255 warn("and will destroy it when filled\n");
1256 return 0; 1239 return 0;
1257 } 1240 }
1258 1241
1259 /* Do they start past zero and end before end-of-disk? */ 1242 /* Are the partitions of size 0 marked empty?
1260 { unsigned long ds = get_disksize(F_SECTOR); 1243 And do they have start = 0? And bootable = 0? */
1261 for (p = partitions; p < partitions+partno; p++) 1244 for (p = partitions; p - partitions < partno; p++)
1262 if (p->size) { 1245 if (p->size == 0) {
1263 if(p->start == 0) { 1246 if (p->p.sys_type != EMPTY_PARTITION)
1264 warn("Warning: partition %s starts at sector 0\n", PNO(p)); 1247 warn
1265 return 0; 1248 ("Warning: partition %s has size 0 but is not marked Empty\n",
1266 } 1249 PNO(p));
1267 if (p->size && p->start + p->size > ds) { 1250 else if (p->p.bootable != 0)
1268 warn("Warning: partition %s extends past end of disk\n", PNO(p)); 1251 warn("Warning: partition %s has size 0 and is bootable\n",
1269 return 0; 1252 PNO(p));
1270 } 1253 else if (p->p.start_sect != 0)
1271 } 1254 warn
1272 } 1255 ("Warning: partition %s has size 0 and nonzero start\n",
1273 1256 PNO(p));
1274 /* At most one chain of DOS extended partitions ? */ 1257 /* all this is probably harmless, no error return */
1275 /* It seems that the OS/2 fdisk has the additional requirement 1258 }
1276 that the extended partition must be the fourth one */ 1259
1277 { int ect = 0; 1260 /* Are the logical partitions contained in their extended partitions? */
1278 for (p = partitions; p < partitions+4; p++) 1261 for (p = partitions + 4; p < partitions + partno; p++)
1279 if (p->p.sys_type == EXTENDED_PARTITION) 1262 if (p->ptype == DOS_TYPE)
1280 ect++; 1263 if (p->size && !is_extended(p->p.sys_type)) {
1281 if (ect > 1 && !Linux) { 1264 q = p->ep;
1282 warn("Among the primary partitions, at most one can be extended\n"); 1265 if (p->start < q->start
1283 warn(" (although this is not a problem under Linux)\n"); 1266 || p->start + p->size > q->start + q->size) {
1284 return 0; 1267 warn("Warning: partition %s "), PNO(p);
1285 } 1268 warn("is not contained in partition %s\n"), PNO(q);
1286 } 1269 return 0;
1287 1270 }
1288 /* 1271 }
1289 * Do all partitions start at a cylinder boundary ? 1272
1290 * (this is not required for Linux) 1273 /* Are the data partitions mutually disjoint? */
1291 * The first partition starts after MBR. 1274 for (p = partitions; p < partitions + partno; p++)
1292 * Logical partitions start slightly after the containing extended partn. 1275 if (p->size && !is_extended(p->p.sys_type))
1293 */ 1276 for (q = p + 1; q < partitions + partno; q++)
1294 if (B.cylindersize) { 1277 if (q->size && !is_extended(q->p.sys_type))
1295 for(p = partitions; p < partitions+partno; p++) 1278 if (!((p->start > q->start) ? disj(q, p) : disj(p, q))) {
1296 if (p->size) { 1279 warn("Warning: partitions %s "), PNO(p);
1297 if(p->start % B.cylindersize != 0 1280 warn("and %s overlap\n"), PNO(q);
1298 && (!p->ep || p->start / B.cylindersize != p->ep->start / B.cylindersize) 1281 return 0;
1299 && (p->p.start_sect >= B.cylindersize)) { 1282 }
1300 warn("Warning: partition %s does not start " 1283
1301 "at a cylinder boundary\n", PNO(p)); 1284 /* Are the data partitions and the extended partition
1302 if (!Linux) 1285 table sectors disjoint? */
1303 return 0; 1286 for (p = partitions; p < partitions + partno; p++)
1304 } 1287 if (p->size && !is_extended(p->p.sys_type))
1305 if((p->start + p->size) % B.cylindersize) { 1288 for (q = partitions; q < partitions + partno; q++)
1306 warn("Warning: partition %s does not end " 1289 if (is_extended(q->p.sys_type))
1307 "at a cylinder boundary\n", PNO(p)); 1290 if (p->start <= q->start
1308 if (!Linux) 1291 && p->start + p->size > q->start) {
1309 return 0; 1292 warn("Warning: partition %s contains part of ",
1310 } 1293 PNO(p));
1311 } 1294 warn("the partition table (sector %lu),\n",
1312 } 1295 q->start);
1313 1296 warn("and will destroy it when filled\n");
1314 /* Usually, one can boot only from primary partitions. */ 1297 return 0;
1315 /* In fact, from a unique one only. */ 1298 }
1316 /* do not warn about bootable extended partitions - 1299
1317 often LILO is there */ 1300 /* Do they start past zero and end before end-of-disk? */
1318 { int pno = -1; 1301 {
1319 for(p = partitions; p < partitions+partno; p++) 1302 unsigned long ds = get_disksize(F_SECTOR);
1320 if (p->p.bootable) { 1303
1321 if (pno == -1) 1304 for (p = partitions; p < partitions + partno; p++)
1322 pno = p - partitions; 1305 if (p->size) {
1323 else if (p - partitions < 4) { 1306 if (p->start == 0) {
1324 warn("Warning: more than one primary partition is marked " 1307 warn("Warning: partition %s starts at sector 0\n",
1325 "bootable (active)\n" 1308 PNO(p));
1326 "This does not matter for LILO, but the DOS MBR will " 1309 return 0;
1327 "not boot this disk.\n"); 1310 }
1328 break; 1311 if (p->size && p->start + p->size > ds) {
1329 } 1312 warn
1330 if (p - partitions >= 4) { 1313 ("Warning: partition %s extends past end of disk\n",
1331 warn("Warning: usually one can boot from primary partitions " 1314 PNO(p));
1332 "only\nLILO disregards the `bootable' flag.\n"); 1315 return 0;
1333 break; 1316 }
1334 } 1317 }
1335 } 1318 }
1336 if (pno == -1 || pno >= 4) 1319
1337 warn("Warning: no primary partition is marked bootable (active)\n" 1320 /* At most one chain of DOS extended partitions ? */
1338 "This does not matter for LILO, but the DOS MBR will " 1321 /* It seems that the OS/2 fdisk has the additional requirement
1339 "not boot this disk.\n"); 1322 that the extended partition must be the fourth one */
1340 } 1323 {
1341 1324 int ect = 0;
1342 /* Is chs as we expect? */ 1325
1343 for(p = partitions; p < partitions+partno; p++) 1326 for (p = partitions; p < partitions + 4; p++)
1344 if(p->ptype == DOS_TYPE) { 1327 if (p->p.sys_type == EXTENDED_PARTITION)
1345 chs a, b; 1328 ect++;
1346 longchs aa, bb; 1329 if (ect > 1 && !Linux) {
1347 a = p->size ? ulong_to_chs(p->start,B) : zero_chs; 1330 warn
1348 b = p->p.begin_chs; 1331 ("Among the primary partitions, at most one can be extended\n");
1349 aa = chs_to_longchs(a); 1332 warn(" (although this is not a problem under Linux)\n");
1350 bb = chs_to_longchs(b); 1333 return 0;
1351 if (!chs_ok(b, PNO(p), "start")) 1334 }
1352 return 0; 1335 }
1353 if(a.s && !is_equal_chs(a, b)) 1336
1354 warn("partition %s: start: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", 1337 /*
1355 PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); 1338 * Do all partitions start at a cylinder boundary ?
1356 a = p->size ? ulong_to_chs(p->start + p->size - 1, B) : zero_chs; 1339 * (this is not required for Linux)
1357 b = p->p.end_chs; 1340 * The first partition starts after MBR.
1358 aa = chs_to_longchs(a); 1341 * Logical partitions start slightly after the containing extended partn.
1359 bb = chs_to_longchs(b); 1342 */
1360 if (!chs_ok(b, PNO(p), "end")) 1343 if (B.cylindersize) {
1361 return 0; 1344 for (p = partitions; p < partitions + partno; p++)
1362 if(a.s && !is_equal_chs(a, b)) 1345 if (p->size) {
1363 warn("partition %s: end: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", 1346 if (p->start % B.cylindersize != 0
1364 PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); 1347 && (!p->ep
1365 if(B.cylinders && B.cylinders < 1024 && bb.c > B.cylinders) 1348 || p->start / B.cylindersize !=
1366 warn("partition %s ends on cylinder %ld, beyond the end of the disk\n", 1349 p->ep->start / B.cylindersize)
1367 PNO(p), bb.c); 1350 && (p->p.start_sect >= B.cylindersize)) {
1368 } 1351 warn("Warning: partition %s does not start "
1369 1352 "at a cylinder boundary\n", PNO(p));
1370 return 1; 1353 if (!Linux)
1354 return 0;
1355 }
1356 if ((p->start + p->size) % B.cylindersize) {
1357 warn("Warning: partition %s does not end "
1358 "at a cylinder boundary\n", PNO(p));
1359 if (!Linux)
1360 return 0;
1361 }
1362 }
1363 }
1364
1365 /* Usually, one can boot only from primary partitions. */
1366 /* In fact, from a unique one only. */
1367 /* do not warn about bootable extended partitions -
1368 often LILO is there */
1369 {
1370 int pno = -1;
1371
1372 for (p = partitions; p < partitions + partno; p++)
1373 if (p->p.bootable) {
1374 if (pno == -1)
1375 pno = p - partitions;
1376 else if (p - partitions < 4) {
1377 warn
1378 ("Warning: more than one primary partition is marked "
1379 "bootable (active)\n"
1380 "This does not matter for LILO, but the DOS MBR will "
1381 "not boot this disk.\n");
1382 break;
1383 }
1384 if (p - partitions >= 4) {
1385 warn
1386 ("Warning: usually one can boot from primary partitions "
1387 "only\nLILO disregards the `bootable' flag.\n");
1388 break;
1389 }
1390 }
1391 if (pno == -1 || pno >= 4)
1392 warn
1393 ("Warning: no primary partition is marked bootable (active)\n"
1394 "This does not matter for LILO, but the DOS MBR will "
1395 "not boot this disk.\n");
1396 }
1397
1398 /* Is chs as we expect? */
1399 for (p = partitions; p < partitions + partno; p++)
1400 if (p->ptype == DOS_TYPE) {
1401 chs a, b;
1402 longchs aa, bb;
1403
1404 a = p->size ? ulong_to_chs(p->start, B) : zero_chs;
1405 b = p->p.begin_chs;
1406 aa = chs_to_longchs(a);
1407 bb = chs_to_longchs(b);
1408 if (!chs_ok(b, PNO(p), "start"))
1409 return 0;
1410 if (a.s && !is_equal_chs(a, b))
1411 warn
1412 ("partition %s: start: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1413 PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1414 a =
1415 p->size ? ulong_to_chs(p->start + p->size - 1,
1416 B) : zero_chs;
1417 b = p->p.end_chs;
1418 aa = chs_to_longchs(a);
1419 bb = chs_to_longchs(b);
1420 if (!chs_ok(b, PNO(p), "end"))
1421 return 0;
1422 if (a.s && !is_equal_chs(a, b))
1423 warn
1424 ("partition %s: end: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n",
1425 PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s);
1426 if (B.cylinders && B.cylinders < 1024 && bb.c > B.cylinders)
1427 warn
1428 ("partition %s ends on cylinder %ld, beyond the end of the disk\n",
1429 PNO(p), bb.c);
1430 }
1431
1432 return 1;
1371 1433
1372#undef PNO 1434#undef PNO
1373} 1435}
1374 1436
1375static void 1437static void
1376extended_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) { 1438extended_partition(char *dev, int fd, struct part_desc *ep,
1377 char *cp; 1439 struct disk_desc *z)
1378 struct sector *s; 1440{
1379 unsigned long start, here, next; 1441 char *cp;
1380 int i, moretodo = 1; 1442 struct sector *s;
1381 struct partition p; 1443 unsigned long start, here, next;
1382 struct part_desc *partitions = &(z->partitions[0]); 1444 int i, moretodo = 1;
1383 int pno = z->partno; 1445 struct partition p;
1446 struct part_desc *partitions = &(z->partitions[0]);
1447 int pno = z->partno;
1384 1448
1385 here = start = ep->start; 1449 here = start = ep->start;
1386 1450
1387 while (moretodo) { 1451 while (moretodo) {
1388 moretodo = 0; 1452 moretodo = 0;
1389 1453
1390 if (!(s = get_sector(dev, fd, here))) 1454 if (!(s = get_sector(dev, fd, here)))
1391 break; 1455 break;
1392 1456
1393 if (!msdos_signature(s)) 1457 if (!msdos_signature(s))
1394 break; 1458 break;
1395 1459
1396 cp = s->data + 0x1be; 1460 cp = s->data + 0x1be;
1397 1461
1398 if (pno+4 >= SIZE(z->partitions)) { 1462 if (pno + 4 >= SIZE(z->partitions)) {
1399 printf("too many partitions - ignoring those past nr (%d)\n", 1463 printf("too many partitions - ignoring those past nr (%d)\n",
1400 pno-1); 1464 pno - 1);
1401 break; 1465 break;
1402 } 1466 }
1403 1467
1404 next = 0; 1468 next = 0;
1469
1470 for (i = 0; i < 4; i++, cp += sizeof(struct partition)) {
1471 partitions[pno].sector = here;
1472 partitions[pno].offset = cp - s->data;
1473 partitions[pno].ep = ep;
1474 copy_to_part(cp, &p);
1475 if (is_extended(p.sys_type)) {
1476 partitions[pno].start = start + p.start_sect;
1477 if (next)
1478 printf("tree of partitions?\n");
1479 else
1480 next = partitions[pno].start; /* follow `upper' branch */
1481 moretodo = 1;
1482 } else {
1483 partitions[pno].start = here + p.start_sect;
1484 }
1485 partitions[pno].size = p.nr_sects;
1486 partitions[pno].ptype = DOS_TYPE;
1487 partitions[pno].p = p;
1488 pno++;
1489 }
1490 here = next;
1491 }
1405 1492
1406 for (i=0; i<4; i++,cp += sizeof(struct partition)) { 1493 z->partno = pno;
1407 partitions[pno].sector = here;
1408 partitions[pno].offset = cp - s->data;
1409 partitions[pno].ep = ep;
1410 copy_to_part(cp,&p);
1411 if (is_extended(p.sys_type)) {
1412 partitions[pno].start = start + p.start_sect;
1413 if (next)
1414 printf("tree of partitions?\n");
1415 else
1416 next = partitions[pno].start; /* follow `upper' branch */
1417 moretodo = 1;
1418 } else {
1419 partitions[pno].start = here + p.start_sect;
1420 }
1421 partitions[pno].size = p.nr_sects;
1422 partitions[pno].ptype = DOS_TYPE;
1423 partitions[pno].p = p;
1424 pno++;
1425 }
1426 here = next;
1427 }
1428
1429 z->partno = pno;
1430} 1494}
1431 1495
1432#define BSD_DISKMAGIC (0x82564557UL) 1496#define BSD_DISKMAGIC (0x82564557UL)
@@ -1436,27 +1500,28 @@ typedef unsigned char u8;
1436typedef unsigned short u16; 1500typedef unsigned short u16;
1437typedef unsigned int u32; 1501typedef unsigned int u32;
1438struct bsd_disklabel { 1502struct bsd_disklabel {
1439 u32 d_magic; 1503 u32 d_magic;
1440 char d_junk1[4]; 1504 char d_junk1[4];
1441 char d_typename[16]; 1505 char d_typename[16];
1442 char d_packname[16]; 1506 char d_packname[16];
1443 char d_junk2[92]; 1507 char d_junk2[92];
1444 u32 d_magic2; 1508 u32 d_magic2;
1445 char d_junk3[2]; 1509 char d_junk3[2];
1446 u16 d_npartitions; /* number of partitions in following */ 1510 u16 d_npartitions; /* number of partitions in following */
1447 char d_junk4[8]; 1511 char d_junk4[8];
1448 struct bsd_partition { /* the partition table */ 1512 struct bsd_partition { /* the partition table */
1449 u32 p_size; /* number of sectors in partition */ 1513 u32 p_size; /* number of sectors in partition */
1450 u32 p_offset; /* starting sector */ 1514 u32 p_offset; /* starting sector */
1451 u32 p_fsize; /* filesystem basic fragment size */ 1515 u32 p_fsize; /* filesystem basic fragment size */
1452 u8 p_fstype; /* filesystem type, see below */ 1516 u8 p_fstype; /* filesystem type, see below */
1453 u8 p_frag; /* filesystem fragments per block */ 1517 u8 p_frag; /* filesystem fragments per block */
1454 u16 p_cpg; /* filesystem cylinders per group */ 1518 u16 p_cpg; /* filesystem cylinders per group */
1455 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */ 1519 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
1456}; 1520};
1457 1521
1458static void 1522static void
1459bsd_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) { 1523bsd_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z)
1524{
1460 struct bsd_disklabel *l; 1525 struct bsd_disklabel *l;
1461 struct bsd_partition *bp, *bp0; 1526 struct bsd_partition *bp, *bp0;
1462 unsigned long start = ep->start; 1527 unsigned long start = ep->start;
@@ -1464,7 +1529,7 @@ bsd_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) {
1464 struct part_desc *partitions = &(z->partitions[0]); 1529 struct part_desc *partitions = &(z->partitions[0]);
1465 int pno = z->partno; 1530 int pno = z->partno;
1466 1531
1467 if (!(s = get_sector(dev,fd,start+1))) 1532 if (!(s = get_sector(dev, fd, start + 1)))
1468 return; 1533 return;
1469 l = (struct bsd_disklabel *) (s->data); 1534 l = (struct bsd_disklabel *) (s->data);
1470 if (l->d_magic != BSD_DISKMAGIC) 1535 if (l->d_magic != BSD_DISKMAGIC)
@@ -1472,16 +1537,16 @@ bsd_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) {
1472 1537
1473 bp = bp0 = &l->d_partitions[0]; 1538 bp = bp0 = &l->d_partitions[0];
1474 while (bp - bp0 <= BSD_MAXPARTITIONS) { 1539 while (bp - bp0 <= BSD_MAXPARTITIONS) {
1475 if (pno+1 >= SIZE(z->partitions)) { 1540 if (pno + 1 >= SIZE(z->partitions)) {
1476 printf("too many partitions - ignoring those " 1541 printf("too many partitions - ignoring those "
1477 "past nr (%d)\n", pno-1); 1542 "past nr (%d)\n", pno - 1);
1478 break; 1543 break;
1479 } 1544 }
1480 if (bp->p_fstype != BSD_FS_UNUSED) { 1545 if (bp->p_fstype != BSD_FS_UNUSED) {
1481 partitions[pno].start = bp->p_offset; 1546 partitions[pno].start = bp->p_offset;
1482 partitions[pno].size = bp->p_size; 1547 partitions[pno].size = bp->p_size;
1483 partitions[pno].sector = start+1; 1548 partitions[pno].sector = start + 1;
1484 partitions[pno].offset = (char *)bp - (char *)bp0; 1549 partitions[pno].offset = (char *) bp - (char *) bp0;
1485 partitions[pno].ep = 0; 1550 partitions[pno].ep = 0;
1486 partitions[pno].ptype = BSD_TYPE; 1551 partitions[pno].ptype = BSD_TYPE;
1487 pno++; 1552 pno++;
@@ -1492,129 +1557,138 @@ bsd_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) {
1492} 1557}
1493 1558
1494static int 1559static int
1495msdos_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { 1560msdos_partition(char *dev, int fd, unsigned long start,
1496 int i; 1561 struct disk_desc *z)
1497 char *cp; 1562{
1498 struct partition pt; 1563 int i;
1499 struct sector *s; 1564 char *cp;
1500 struct part_desc *partitions = &(z->partitions[0]); 1565 struct partition pt;
1501 int pno = z->partno; 1566 struct sector *s;
1502 1567 struct part_desc *partitions = &(z->partitions[0]);
1503 if (!(s = get_sector(dev, fd, start))) 1568 int pno = z->partno;
1504 return 0;
1505 1569
1506 if (!msdos_signature(s)) 1570 if (!(s = get_sector(dev, fd, start)))
1507 return 0; 1571 return 0;
1508 1572
1509 cp = s->data + 0x1be; 1573 if (!msdos_signature(s))
1510 copy_to_part(cp,&pt); 1574 return 0;
1511 1575
1512 /* If I am not mistaken, recent kernels will hide this from us, 1576 cp = s->data + 0x1be;
1577 copy_to_part(cp, &pt);
1578
1579 /* If I am not mistaken, recent kernels will hide this from us,
1513 so we will never actually see traces of a Disk Manager */ 1580 so we will never actually see traces of a Disk Manager */
1514 if (pt.sys_type == DM6_PARTITION 1581 if (pt.sys_type == DM6_PARTITION
1515 || pt.sys_type == EZD_PARTITION 1582 || pt.sys_type == EZD_PARTITION
1516 || pt.sys_type == DM6_AUX1PARTITION 1583 || pt.sys_type == DM6_AUX1PARTITION
1517 || pt.sys_type == DM6_AUX3PARTITION) { 1584 || pt.sys_type == DM6_AUX3PARTITION) {
1518 printf("detected Disk Manager - unable to handle that\n"); 1585 printf("detected Disk Manager - unable to handle that\n");
1519 return 0; 1586 return 0;
1520 } 1587 }
1521 { unsigned int sig = *(unsigned short *)(s->data + 2); 1588 {
1522 if (sig <= 0x1ae 1589 unsigned int sig = *(unsigned short *) (s->data + 2);
1523 && *(unsigned short *)(s->data + sig) == 0x55aa 1590
1524 && (1 & *(unsigned char *)(s->data + sig + 2))) { 1591 if (sig <= 0x1ae
1525 printf("DM6 signature found - giving up\n"); 1592 && *(unsigned short *) (s->data + sig) == 0x55aa
1526 return 0; 1593 && (1 & *(unsigned char *) (s->data + sig + 2))) {
1527 } 1594 printf("DM6 signature found - giving up\n");
1528 } 1595 return 0;
1529 1596 }
1530 for (pno=0; pno<4; pno++,cp += sizeof(struct partition)) { 1597 }
1531 partitions[pno].sector = start; 1598
1532 partitions[pno].offset = cp - s->data; 1599 for (pno = 0; pno < 4; pno++, cp += sizeof(struct partition)) {
1533 copy_to_part(cp,&pt); 1600 partitions[pno].sector = start;
1534 partitions[pno].start = start + pt.start_sect; 1601 partitions[pno].offset = cp - s->data;
1535 partitions[pno].size = pt.nr_sects; 1602 copy_to_part(cp, &pt);
1536 partitions[pno].ep = 0; 1603 partitions[pno].start = start + pt.start_sect;
1537 partitions[pno].p = pt; 1604 partitions[pno].size = pt.nr_sects;
1538 } 1605 partitions[pno].ep = 0;
1539 1606 partitions[pno].p = pt;
1540 z->partno = pno; 1607 }
1541 1608
1542 for (i=0; i<4; i++) { 1609 z->partno = pno;
1543 if (is_extended(partitions[i].p.sys_type)) { 1610
1544 if (!partitions[i].size) { 1611 for (i = 0; i < 4; i++) {
1545 printf("strange..., an extended partition of size 0?\n"); 1612 if (is_extended(partitions[i].p.sys_type)) {
1546 continue; 1613 if (!partitions[i].size) {
1547 } 1614 printf("strange..., an extended partition of size 0?\n");
1548 extended_partition(dev, fd, &partitions[i], z); 1615 continue;
1549 } 1616 }
1550 if (is_bsd(partitions[i].p.sys_type)) { 1617 extended_partition(dev, fd, &partitions[i], z);
1551 if (!partitions[i].size) { 1618 }
1552 printf("strange..., a BSD partition of size 0?\n"); 1619 if (is_bsd(partitions[i].p.sys_type)) {
1553 continue; 1620 if (!partitions[i].size) {
1554 } 1621 printf("strange..., a BSD partition of size 0?\n");
1555 bsd_partition(dev, fd, &partitions[i], z); 1622 continue;
1556 } 1623 }
1557 } 1624 bsd_partition(dev, fd, &partitions[i], z);
1558 return 1; 1625 }
1626 }
1627 return 1;
1559} 1628}
1560 1629
1561static int 1630static int
1562osf_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { 1631osf_partition(char *dev, int fd, unsigned long start, struct disk_desc *z)
1632{
1563 return 0; 1633 return 0;
1564} 1634}
1565 1635
1566static int 1636static int
1567sun_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { 1637sun_partition(char *dev, int fd, unsigned long start, struct disk_desc *z)
1638{
1568 return 0; 1639 return 0;
1569} 1640}
1570 1641
1571static int 1642static int
1572amiga_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { 1643amiga_partition(char *dev, int fd, unsigned long start,
1644 struct disk_desc *z)
1645{
1573 return 0; 1646 return 0;
1574} 1647}
1575 1648
1576static void 1649static void get_partitions(char *dev, int fd, struct disk_desc *z)
1577get_partitions(char *dev, int fd, struct disk_desc *z) { 1650{
1578 z->partno = 0; 1651 z->partno = 0;
1579 1652
1580 if (!msdos_partition(dev, fd, 0, z) 1653 if (!msdos_partition(dev, fd, 0, z)
1581 && !osf_partition(dev, fd, 0, z) 1654 && !osf_partition(dev, fd, 0, z)
1582 && !sun_partition(dev, fd, 0, z) 1655 && !sun_partition(dev, fd, 0, z)
1583 && !amiga_partition(dev, fd, 0, z)) { 1656 && !amiga_partition(dev, fd, 0, z)) {
1584 printf(" %s: unrecognized partition\n", dev); 1657 printf(" %s: unrecognized partition\n", dev);
1585 return; 1658 return;
1586 } 1659 }
1587} 1660}
1588 1661
1589static int 1662static int write_partitions(char *dev, int fd, struct disk_desc *z)
1590write_partitions(char *dev, int fd, struct disk_desc *z) { 1663{
1591 struct sector *s; 1664 struct sector *s;
1592 struct part_desc *partitions = &(z->partitions[0]), *p; 1665 struct part_desc *partitions = &(z->partitions[0]), *p;
1593 int pno = z->partno; 1666 int pno = z->partno;
1594 1667
1595 if (no_write) { 1668 if (no_write) {
1596 printf("-n flag was given: Nothing changed\n"); 1669 printf("-n flag was given: Nothing changed\n");
1597 exit(0); 1670 exit(0);
1598 } 1671 }
1599 1672
1600 for (p = partitions; p < partitions+pno; p++) { 1673 for (p = partitions; p < partitions + pno; p++) {
1601 s = get_sector(dev, fd, p->sector); 1674 s = get_sector(dev, fd, p->sector);
1602 if (!s) return 0; 1675 if (!s)
1603 s->to_be_written = 1; 1676 return 0;
1604 copy_from_part(&(p->p), s->data + p->offset); 1677 s->to_be_written = 1;
1605 *(unsigned short *)(&(s->data[0x1fe])) = 0xaa55; 1678 copy_from_part(&(p->p), s->data + p->offset);
1606 } 1679 *(unsigned short *) (&(s->data[0x1fe])) = 0xaa55;
1607 if (save_sector_file) { 1680 }
1608 if (!save_sectors(dev, fd)) { 1681 if (save_sector_file) {
1609 fatal("Failed saving the old sectors - aborting\n"); 1682 if (!save_sectors(dev, fd)) {
1610 return 0; 1683 fatal("Failed saving the old sectors - aborting\n");
1611 } 1684 return 0;
1612 } 1685 }
1613 if (!write_sectors(dev, fd)) { 1686 }
1614 error("Failed writing the partition on %s\n"), dev; 1687 if (!write_sectors(dev, fd)) {
1615 return 0; 1688 error("Failed writing the partition on %s\n"), dev;
1616 } 1689 return 0;
1617 return 1; 1690 }
1691 return 1;
1618} 1692}
1619 1693
1620/* 1694/*
@@ -1644,20 +1718,21 @@ write_partitions(char *dev, int fd, struct disk_desc *z) {
1644static int eof, eob; 1718static int eof, eob;
1645 1719
1646struct dumpfld { 1720struct dumpfld {
1647 int fldno; 1721 int fldno;
1648 char *fldname; 1722 char *fldname;
1649 int is_bool; 1723 int is_bool;
1650} dumpflds[] = { 1724} dumpflds[] = {
1651 { 0, "start", 0 }, 1725 {
1652 { 1, "size", 0 }, 1726 0, "start", 0}, {
1653 { 2, "Id", 0 }, 1727 1, "size", 0}, {
1654 { 3, "bootable", 1 }, 1728 2, "Id", 0}, {
1655 { 4, "bh", 0 }, 1729 3, "bootable", 1}, {
1656 { 5, "bs", 0 }, 1730 4, "bh", 0}, {
1657 { 6, "bc", 0 }, 1731 5, "bs", 0}, {
1658 { 7, "eh", 0 }, 1732 6, "bc", 0}, {
1659 { 8, "es", 0 }, 1733 7, "eh", 0}, {
1660 { 9, "ec", 0 } 1734 8, "es", 0}, {
1735 9, "ec", 0}
1661}; 1736};
1662 1737
1663/* 1738/*
@@ -1670,115 +1745,117 @@ struct dumpfld {
1670#define RD_CMD (-2) 1745#define RD_CMD (-2)
1671 1746
1672static int 1747static int
1673read_stdin(unsigned char **fields, unsigned char *line, int fieldssize, int linesize) { 1748read_stdin(unsigned char **fields, unsigned char *line, int fieldssize,
1674 unsigned char *lp, *ip; 1749 int linesize)
1675 int c, fno; 1750{
1676 1751 unsigned char *lp, *ip;
1677 /* boolean true and empty string at start */ 1752 int c, fno;
1678 line[0] = '*'; 1753
1679 line[1] = 0; 1754 /* boolean true and empty string at start */
1680 for (fno=0; fno < fieldssize; fno++) 1755 line[0] = '*';
1681 fields[fno] = line + 1; 1756 line[1] = 0;
1682 fno = 0; 1757 for (fno = 0; fno < fieldssize; fno++)
1683 1758 fields[fno] = line + 1;
1684 /* read a line from stdin */ 1759 fno = 0;
1685 lp = fgets(line+2, linesize, stdin); 1760
1686 if (lp == NULL) { 1761 /* read a line from stdin */
1687 eof = 1; 1762 lp = fgets(line + 2, linesize, stdin);
1688 return RD_EOF; 1763 if (lp == NULL) {
1689 } 1764 eof = 1;
1690 if (!(lp = index(lp, '\n'))) 1765 return RD_EOF;
1691 fatal("long or incomplete input line - quitting\n"); 1766 }
1692 *lp = 0; 1767 if (!(lp = index(lp, '\n')))
1693 1768 fatal("long or incomplete input line - quitting\n");
1694 /* remove comments, if any */ 1769 *lp = 0;
1695 if ((lp = index(line+2, '#')) != 0) 1770
1696 *lp = 0; 1771 /* remove comments, if any */
1697 1772 if ((lp = index(line + 2, '#')) != 0)
1698 /* recognize a few commands - to be expanded */ 1773 *lp = 0;
1699 if (!strcmp(line+2, "unit: sectors")) { 1774
1700 specified_format = F_SECTOR; 1775 /* recognize a few commands - to be expanded */
1701 return RD_CMD; 1776 if (!strcmp(line + 2, "unit: sectors")) {
1702 } 1777 specified_format = F_SECTOR;
1703 1778 return RD_CMD;
1704 /* dump style? - then bad input is fatal */ 1779 }
1705 if ((ip = index(line+2, ':')) != 0) { 1780
1706 struct dumpfld *d; 1781 /* dump style? - then bad input is fatal */
1707 1782 if ((ip = index(line + 2, ':')) != 0) {
1708 nxtfld: 1783 struct dumpfld *d;
1709 ip++; 1784
1710 while(isspace(*ip)) 1785 nxtfld:
1711 ip++; 1786 ip++;
1712 if (*ip == 0) 1787 while (isspace(*ip))
1713 return fno; 1788 ip++;
1714 for(d = dumpflds; d-dumpflds < SIZE(dumpflds); d++) { 1789 if (*ip == 0)
1715 if(!strncmp(ip, d->fldname, strlen(d->fldname))) { 1790 return fno;
1716 ip += strlen(d->fldname); 1791 for (d = dumpflds; d - dumpflds < SIZE(dumpflds); d++) {
1717 while(isspace(*ip)) 1792 if (!strncmp(ip, d->fldname, strlen(d->fldname))) {
1718 ip++; 1793 ip += strlen(d->fldname);
1719 if (d->is_bool) 1794 while (isspace(*ip))
1720 fields[d->fldno] = line; 1795 ip++;
1721 else if (*ip == '=') { 1796 if (d->is_bool)
1722 while(isspace(*++ip)) ; 1797 fields[d->fldno] = line;
1723 fields[d->fldno] = ip; 1798 else if (*ip == '=') {
1724 while(isalnum(*ip)) /* 0x07FF */ 1799 while (isspace(*++ip));
1725 ip++; 1800 fields[d->fldno] = ip;
1726 } else 1801 while (isalnum(*ip)) /* 0x07FF */
1727 fatal("input error: `=' expected after %s field\n", 1802 ip++;
1728 d->fldname); 1803 } else
1729 if (fno <= d->fldno) 1804 fatal("input error: `=' expected after %s field\n",
1730 fno = d->fldno + 1; 1805 d->fldname);
1731 if(*ip == 0) 1806 if (fno <= d->fldno)
1732 return fno; 1807 fno = d->fldno + 1;
1733 if(*ip != ',' && *ip != ';') 1808 if (*ip == 0)
1734 fatal("input error: unexpected character %c after %s field\n", 1809 return fno;
1735 *ip, d->fldname); 1810 if (*ip != ',' && *ip != ';')
1736 *ip = 0; 1811 fatal
1737 goto nxtfld; 1812 ("input error: unexpected character %c after %s field\n",
1813 *ip, d->fldname);
1814 *ip = 0;
1815 goto nxtfld;
1816 }
1738 } 1817 }
1739 } 1818 fatal("unrecognized input: %s\n"), ip;
1740 fatal("unrecognized input: %s\n"), ip; 1819 }
1741 } 1820
1742 1821 /* split line into fields */
1743 /* split line into fields */ 1822 lp = ip = line + 2;
1744 lp = ip = line+2; 1823 fields[fno++] = lp;
1745 fields[fno++] = lp; 1824 while ((c = *ip++) != 0) {
1746 while((c = *ip++) != 0) { 1825 if (!lp[-1] && (c == '\t' || c == ' '));
1747 if (!lp[-1] && (c == '\t' || c == ' ')) 1826 else if (c == '\t' || c == ' ' || c == ',' || c == ';') {
1748 ; 1827 *lp++ = 0;
1749 else if (c == '\t' || c == ' ' || c == ',' || c == ';') { 1828 if (fno < fieldssize)
1750 *lp++ = 0; 1829 fields[fno++] = lp;
1751 if (fno < fieldssize) 1830 continue;
1752 fields[fno++] = lp; 1831 } else
1753 continue; 1832 *lp++ = c;
1754 } else 1833 }
1755 *lp++ = c;
1756 }
1757 1834
1758 if (lp == fields[fno-1]) 1835 if (lp == fields[fno - 1])
1759 fno--; 1836 fno--;
1760 return fno; 1837 return fno;
1761} 1838}
1762 1839
1763/* read a number, use default if absent */ 1840/* read a number, use default if absent */
1764static int 1841static int get_ul(char *u, unsigned long *up, unsigned long def, int base)
1765get_ul(char *u, unsigned long *up, unsigned long def, int base) { 1842{
1766 char *nu; 1843 char *nu;
1767 1844
1768 if (*u) { 1845 if (*u) {
1769 errno = 0; 1846 errno = 0;
1770 *up = strtoul(u, &nu, base); 1847 *up = strtoul(u, &nu, base);
1771 if (errno == ERANGE) { 1848 if (errno == ERANGE) {
1772 printf("number too big\n"); 1849 printf("number too big\n");
1773 return -1; 1850 return -1;
1774 } 1851 }
1775 if (*nu) { 1852 if (*nu) {
1776 printf("trailing junk after number\n"); 1853 printf("trailing junk after number\n");
1777 return -1; 1854 return -1;
1778 } 1855 }
1779 } else 1856 } else
1780 *up = def; 1857 *up = def;
1781 return 0; 1858 return 0;
1782} 1859}
1783 1860
1784/* There are two common ways to structure extended partitions: 1861/* There are two common ways to structure extended partitions:
@@ -1800,445 +1877,460 @@ static enum { NESTED, CHAINED, ONESECTOR } boxes = NESTED;
1800/* find the default value for <start> - assuming entire units */ 1877/* find the default value for <start> - assuming entire units */
1801static unsigned long 1878static unsigned long
1802first_free(int pno, int is_extended, struct part_desc *ep, int format, 1879first_free(int pno, int is_extended, struct part_desc *ep, int format,
1803 unsigned long mid, struct disk_desc *z) { 1880 unsigned long mid, struct disk_desc *z)
1804 unsigned long ff, fff; 1881{
1805 unsigned long unit = unitsize(format); 1882 unsigned long ff, fff;
1806 struct part_desc *partitions = &(z->partitions[0]), *pp = 0; 1883 unsigned long unit = unitsize(format);
1807 1884 struct part_desc *partitions = &(z->partitions[0]), *pp = 0;
1808 /* if containing ep undefined, look at its container */ 1885
1809 if (ep && ep->p.sys_type == EMPTY_PARTITION) 1886 /* if containing ep undefined, look at its container */
1810 ep = ep->ep; 1887 if (ep && ep->p.sys_type == EMPTY_PARTITION)
1811 1888 ep = ep->ep;
1812 if (ep) { 1889
1813 if (boxes == NESTED || (boxes == CHAINED && !is_extended)) 1890 if (ep) {
1814 pp = ep; 1891 if (boxes == NESTED || (boxes == CHAINED && !is_extended))
1815 else if (all_logicals_inside_outermost_extended) 1892 pp = ep;
1816 pp = outer_extended_partition(ep); 1893 else if (all_logicals_inside_outermost_extended)
1817 } 1894 pp = outer_extended_partition(ep);
1895 }
1818#if 0 1896#if 0
1819 ff = pp ? (pp->start + unit - 1) / unit : 0; 1897 ff = pp ? (pp->start + unit - 1) / unit : 0;
1820#else 1898#else
1821 /* rounding up wastes almost an entire cylinder - round down 1899 /* rounding up wastes almost an entire cylinder - round down
1822 and leave it to compute_start_sect() to fix the difference */ 1900 and leave it to compute_start_sect() to fix the difference */
1823 ff = pp ? pp->start / unit : 0; 1901 ff = pp ? pp->start / unit : 0;
1824#endif 1902#endif
1825 /* MBR and 1st sector of an extended partition are never free */ 1903 /* MBR and 1st sector of an extended partition are never free */
1826 if (unit == 1) 1904 if (unit == 1)
1827 ff++; 1905 ff++;
1828 1906
1829 again: 1907 again:
1830 for(pp = partitions; pp < partitions+pno; pp++) { 1908 for (pp = partitions; pp < partitions + pno; pp++) {
1831 if (!is_parent(pp, ep) && pp->size > 0) { 1909 if (!is_parent(pp, ep) && pp->size > 0) {
1832 if ((partitions_in_order || pp->start / unit <= ff 1910 if ((partitions_in_order || pp->start / unit <= ff
1833 || (mid && pp->start / unit <= mid)) 1911 || (mid && pp->start / unit <= mid))
1834 && (fff = (pp->start + pp->size + unit - 1) / unit) > ff) { 1912 && (fff = (pp->start + pp->size + unit - 1) / unit) > ff) {
1835 ff = fff; 1913 ff = fff;
1836 goto again; 1914 goto again;
1837 } 1915 }
1916 }
1838 } 1917 }
1839 }
1840 1918
1841 return ff; 1919 return ff;
1842} 1920}
1843 1921
1844/* find the default value for <size> - assuming entire units */ 1922/* find the default value for <size> - assuming entire units */
1845static unsigned long 1923static unsigned long
1846max_length(int pno, int is_extended, struct part_desc *ep, int format, 1924max_length(int pno, int is_extended, struct part_desc *ep, int format,
1847 unsigned long start, struct disk_desc *z) { 1925 unsigned long start, struct disk_desc *z)
1848 unsigned long fu; 1926{
1849 unsigned long unit = unitsize(format); 1927 unsigned long fu;
1850 struct part_desc *partitions = &(z->partitions[0]), *pp = 0; 1928 unsigned long unit = unitsize(format);
1851 1929 struct part_desc *partitions = &(z->partitions[0]), *pp = 0;
1852 /* if containing ep undefined, look at its container */ 1930
1853 if (ep && ep->p.sys_type == EMPTY_PARTITION) 1931 /* if containing ep undefined, look at its container */
1854 ep = ep->ep; 1932 if (ep && ep->p.sys_type == EMPTY_PARTITION)
1855 1933 ep = ep->ep;
1856 if (ep) { 1934
1857 if (boxes == NESTED || (boxes == CHAINED && !is_extended)) 1935 if (ep) {
1858 pp = ep; 1936 if (boxes == NESTED || (boxes == CHAINED && !is_extended))
1859 else if (all_logicals_inside_outermost_extended) 1937 pp = ep;
1860 pp = outer_extended_partition(ep); 1938 else if (all_logicals_inside_outermost_extended)
1861 } 1939 pp = outer_extended_partition(ep);
1862 fu = pp ? (pp->start + pp->size) / unit : get_disksize(format); 1940 }
1863 1941 fu = pp ? (pp->start + pp->size) / unit : get_disksize(format);
1864 for(pp = partitions; pp < partitions+pno; pp++) 1942
1865 if (!is_parent(pp, ep) && pp->size > 0 1943 for (pp = partitions; pp < partitions + pno; pp++)
1866 && pp->start / unit >= start && pp->start / unit < fu) 1944 if (!is_parent(pp, ep) && pp->size > 0
1867 fu = pp->start / unit; 1945 && pp->start / unit >= start && pp->start / unit < fu)
1868 1946 fu = pp->start / unit;
1869 return (fu > start) ? fu - start : 0; 1947
1948 return (fu > start) ? fu - start : 0;
1870} 1949}
1871 1950
1872/* compute starting sector of a partition inside an extended one */ 1951/* compute starting sector of a partition inside an extended one */
1873/* ep is 0 or points to surrounding extended partition */ 1952/* ep is 0 or points to surrounding extended partition */
1874static int 1953static int compute_start_sect(struct part_desc *p, struct part_desc *ep)
1875compute_start_sect(struct part_desc *p, struct part_desc *ep) { 1954{
1876 unsigned long base; 1955 unsigned long base;
1877 int inc = (DOS && B.sectors) ? B.sectors : 1; 1956 int inc = (DOS && B.sectors) ? B.sectors : 1;
1878 int delta; 1957 int delta;
1879 1958
1880 if (ep && p->start + p->size >= ep->start + 1) 1959 if (ep && p->start + p->size >= ep->start + 1)
1881 delta = p->start - ep->start - inc; 1960 delta = p->start - ep->start - inc;
1882 else if (p->start == 0 && p->size > 0) 1961 else if (p->start == 0 && p->size > 0)
1883 delta = -inc; 1962 delta = -inc;
1884 else 1963 else
1885 delta = 0; 1964 delta = 0;
1886 if (delta < 0) { 1965 if (delta < 0) {
1887 p->start -= delta; 1966 p->start -= delta;
1888 p->size += delta; 1967 p->size += delta;
1889 if (is_extended(p->p.sys_type) && boxes == ONESECTOR) 1968 if (is_extended(p->p.sys_type) && boxes == ONESECTOR)
1890 p->size = inc; 1969 p->size = inc;
1891 else if ((int)(p->size) <= 0) { 1970 else if ((int) (p->size) <= 0) {
1892 warn("no room for partition descriptor\n"); 1971 warn("no room for partition descriptor\n");
1893 return 0; 1972 return 0;
1894 } 1973 }
1895 } 1974 }
1896 base = (!ep ? 0 1975 base = (!ep ? 0
1897 : (is_extended(p->p.sys_type) ? 1976 : (is_extended(p->p.sys_type) ?
1898 outer_extended_partition(ep) : ep)->start); 1977 outer_extended_partition(ep) : ep)->start);
1899 p->ep = ep; 1978 p->ep = ep;
1900 if (p->p.sys_type == EMPTY_PARTITION && p->size == 0) { 1979 if (p->p.sys_type == EMPTY_PARTITION && p->size == 0) {
1901 p->p.start_sect = 0; 1980 p->p.start_sect = 0;
1902 p->p.begin_chs = zero_chs; 1981 p->p.begin_chs = zero_chs;
1903 p->p.end_chs = zero_chs; 1982 p->p.end_chs = zero_chs;
1904 } else { 1983 } else {
1905 p->p.start_sect = p->start - base; 1984 p->p.start_sect = p->start - base;
1906 p->p.begin_chs = ulong_to_chs(p->start,B); 1985 p->p.begin_chs = ulong_to_chs(p->start, B);
1907 p->p.end_chs = ulong_to_chs(p->start + p->size - 1,B); 1986 p->p.end_chs = ulong_to_chs(p->start + p->size - 1, B);
1908 } 1987 }
1909 p->p.nr_sects = p->size; 1988 p->p.nr_sects = p->size;
1910 return 1; 1989 return 1;
1911} 1990}
1912 1991
1913/* build the extended partition surrounding a given logical partition */ 1992/* build the extended partition surrounding a given logical partition */
1914static int 1993static int
1915build_surrounding_extended(struct part_desc *p, struct part_desc *ep, 1994build_surrounding_extended(struct part_desc *p, struct part_desc *ep,
1916 struct disk_desc *z) { 1995 struct disk_desc *z)
1917 int inc = (DOS && B.sectors) ? B.sectors : 1; 1996{
1918 int format = F_SECTOR; 1997 int inc = (DOS && B.sectors) ? B.sectors : 1;
1919 struct part_desc *p0 = &(z->partitions[0]), *eep = ep->ep; 1998 int format = F_SECTOR;
1920 1999 struct part_desc *p0 = &(z->partitions[0]), *eep = ep->ep;
1921 if (boxes == NESTED) { 2000
1922 ep->start = first_free(ep-p0, 1, eep, format, p->start, z); 2001 if (boxes == NESTED) {
1923 ep->size = max_length(ep-p0, 1, eep, format, ep->start, z); 2002 ep->start = first_free(ep - p0, 1, eep, format, p->start, z);
1924 if (ep->start > p->start || ep->start + ep->size < p->start + p->size) { 2003 ep->size = max_length(ep - p0, 1, eep, format, ep->start, z);
1925 warn("cannot build surrounding extended partition\n"); 2004 if (ep->start > p->start
1926 return 0; 2005 || ep->start + ep->size < p->start + p->size) {
1927 } 2006 warn("cannot build surrounding extended partition\n");
1928 } else { 2007 return 0;
1929 ep->start = p->start; 2008 }
1930 if(boxes == CHAINED) 2009 } else {
1931 ep->size = p->size; 2010 ep->start = p->start;
1932 else 2011 if (boxes == CHAINED)
1933 ep->size = inc; 2012 ep->size = p->size;
1934 } 2013 else
1935 2014 ep->size = inc;
1936 ep->p.nr_sects = ep->size; 2015 }
1937 ep->p.bootable = 0; 2016
1938 ep->p.sys_type = EXTENDED_PARTITION; 2017 ep->p.nr_sects = ep->size;
1939 if (!compute_start_sect(ep, eep) || !compute_start_sect(p, ep)) { 2018 ep->p.bootable = 0;
1940 ep->p.sys_type = EMPTY_PARTITION; 2019 ep->p.sys_type = EXTENDED_PARTITION;
1941 ep->size = 0; 2020 if (!compute_start_sect(ep, eep) || !compute_start_sect(p, ep)) {
1942 return 0; 2021 ep->p.sys_type = EMPTY_PARTITION;
1943 } 2022 ep->size = 0;
2023 return 0;
2024 }
1944 2025
1945 return 1; 2026 return 1;
1946} 2027}
1947 2028
1948static int 2029static int
1949read_line(int pno, struct part_desc *ep, char *dev, int interactive, 2030read_line(int pno, struct part_desc *ep, char *dev, int interactive,
1950 struct disk_desc *z) { 2031 struct disk_desc *z)
1951 unsigned char line[1000]; 2032{
1952 unsigned char *fields[11]; 2033 unsigned char line[1000];
1953 int fno, pct = pno%4; 2034 unsigned char *fields[11];
1954 struct part_desc p, *orig; 2035 int fno, pct = pno % 4;
1955 unsigned long ff, ff1, ul, ml, ml1, def; 2036 struct part_desc p, *orig;
1956 int format, lpno, is_extd; 2037 unsigned long ff, ff1, ul, ml, ml1, def;
1957 2038 int format, lpno, is_extd;
1958 if (eof || eob)
1959 return -1;
1960
1961 lpno = index_to_linux(pno, z);
1962
1963 if (interactive) {
1964 if (pct == 0 && (show_extended || pno == 0))
1965 warn("\n");
1966 warn("%8s%d: ", dev, lpno);
1967 }
1968
1969 /* read input line - skip blank lines when reading from a file */
1970 do {
1971 fno = read_stdin(fields, line, SIZE(fields), SIZE(line));
1972 } while(fno == RD_CMD || (fno == 0 && !interactive));
1973 if (fno == RD_EOF) {
1974 return -1;
1975 } else if (fno > 10 && *(fields[10]) != 0) {
1976 printf("too many input fields\n");
1977 return 0;
1978 }
1979 2039
1980 if (fno == 1 && !strcmp(fields[0], ".")) { 2040 if (eof || eob)
1981 eob = 1; 2041 return -1;
1982 return -1; 2042
1983 } 2043 lpno = index_to_linux(pno, z);
2044
2045 if (interactive) {
2046 if (pct == 0 && (show_extended || pno == 0))
2047 warn("\n");
2048 warn("%8s%d: ", dev, lpno);
2049 }
1984 2050
1985 /* use specified format, but round to cylinders if F_MEGABYTE specified */ 2051 /* read input line - skip blank lines when reading from a file */
1986 format = 0; 2052 do {
1987 if (B.cylindersize && specified_format == F_MEGABYTE) 2053 fno = read_stdin(fields, line, SIZE(fields), SIZE(line));
1988 format = F_CYLINDER; 2054 } while (fno == RD_CMD || (fno == 0 && !interactive));
2055 if (fno == RD_EOF) {
2056 return -1;
2057 } else if (fno > 10 && *(fields[10]) != 0) {
2058 printf("too many input fields\n");
2059 return 0;
2060 }
1989 2061
1990 orig = (one_only ? &(oldp.partitions[pno]) : 0); 2062 if (fno == 1 && !strcmp(fields[0], ".")) {
2063 eob = 1;
2064 return -1;
2065 }
1991 2066
1992 p = zero_part_desc; 2067 /* use specified format, but round to cylinders if F_MEGABYTE specified */
1993 p.ep = ep; 2068 format = 0;
2069 if (B.cylindersize && specified_format == F_MEGABYTE)
2070 format = F_CYLINDER;
2071
2072 orig = (one_only ? &(oldp.partitions[pno]) : 0);
2073
2074 p = zero_part_desc;
2075 p.ep = ep;
2076
2077 /* first read the type - we need to know whether it is extended */
2078 /* stop reading when input blank (defaults) and all is full */
2079 is_extd = 0;
2080 if (fno == 0) { /* empty line */
2081 if (orig && is_extended(orig->p.sys_type))
2082 is_extd = 1;
2083 ff = first_free(pno, is_extd, ep, format, 0, z);
2084 ml = max_length(pno, is_extd, ep, format, ff, z);
2085 if (ml == 0 && is_extd == 0) {
2086 is_extd = 1;
2087 ff = first_free(pno, is_extd, ep, format, 0, z);
2088 ml = max_length(pno, is_extd, ep, format, ff, z);
2089 }
2090 if (ml == 0 && pno >= 4) {
2091 /* no free blocks left - don't read any further */
2092 warn("No room for more\n");
2093 return -1;
2094 }
2095 }
2096 if (fno < 3 || !*(fields[2]))
2097 ul = orig ? orig->p.sys_type :
2098 (is_extd || (pno > 3 && pct == 1 && show_extended))
2099 ? EXTENDED_PARTITION : LINUX_NATIVE;
2100 else if (!strcmp(fields[2], "L"))
2101 ul = LINUX_NATIVE;
2102 else if (!strcmp(fields[2], "S"))
2103 ul = LINUX_SWAP;
2104 else if (!strcmp(fields[2], "E"))
2105 ul = EXTENDED_PARTITION;
2106 else if (!strcmp(fields[2], "X"))
2107 ul = LINUX_EXTENDED;
2108 else if (get_ul(fields[2], &ul, LINUX_NATIVE, 16))
2109 return 0;
2110 if (ul > 255) {
2111 warn("Illegal type\n");
2112 return 0;
2113 }
2114 p.p.sys_type = ul;
2115 is_extd = is_extended(ul);
1994 2116
1995 /* first read the type - we need to know whether it is extended */ 2117 /* find start */
1996 /* stop reading when input blank (defaults) and all is full */
1997 is_extd = 0;
1998 if (fno == 0) { /* empty line */
1999 if (orig && is_extended(orig->p.sys_type))
2000 is_extd = 1;
2001 ff = first_free(pno, is_extd, ep, format, 0, z); 2118 ff = first_free(pno, is_extd, ep, format, 0, z);
2002 ml = max_length(pno, is_extd, ep, format, ff, z); 2119 ff1 = ff * unitsize(format);
2003 if (ml == 0 && is_extd == 0) { 2120 def = orig ? orig->start : (pno > 4 && pct > 1) ? 0 : ff1;
2004 is_extd = 1; 2121 if (fno < 1 || !*(fields[0]))
2005 ff = first_free(pno, is_extd, ep, format, 0, z); 2122 p.start = def;
2006 ml = max_length(pno, is_extd, ep, format, ff, z); 2123 else {
2007 } 2124 if (get_ul(fields[0], &ul, def / unitsize(0), 0))
2008 if (ml == 0 && pno >= 4) { 2125 return 0;
2009 /* no free blocks left - don't read any further */ 2126 p.start = ul * unitsize(0);
2010 warn("No room for more\n"); 2127 p.start -= (p.start % unitsize(format));
2011 return -1; 2128 }
2012 }
2013 }
2014 if (fno < 3 || !*(fields[2]))
2015 ul = orig ? orig->p.sys_type :
2016 (is_extd || (pno > 3 && pct == 1 && show_extended))
2017 ? EXTENDED_PARTITION : LINUX_NATIVE;
2018 else if(!strcmp(fields[2], "L"))
2019 ul = LINUX_NATIVE;
2020 else if(!strcmp(fields[2], "S"))
2021 ul = LINUX_SWAP;
2022 else if(!strcmp(fields[2], "E"))
2023 ul = EXTENDED_PARTITION;
2024 else if(!strcmp(fields[2], "X"))
2025 ul = LINUX_EXTENDED;
2026 else if (get_ul(fields[2], &ul, LINUX_NATIVE, 16))
2027 return 0;
2028 if (ul > 255) {
2029 warn("Illegal type\n");
2030 return 0;
2031 }
2032 p.p.sys_type = ul;
2033 is_extd = is_extended(ul);
2034
2035 /* find start */
2036 ff = first_free(pno, is_extd, ep, format, 0, z);
2037 ff1 = ff * unitsize(format);
2038 def = orig ? orig->start : (pno > 4 && pct > 1) ? 0 : ff1;
2039 if (fno < 1 || !*(fields[0]))
2040 p.start = def;
2041 else {
2042 if (get_ul(fields[0], &ul, def / unitsize(0), 0))
2043 return 0;
2044 p.start = ul * unitsize(0);
2045 p.start -= (p.start % unitsize(format));
2046 }
2047
2048 /* find length */
2049 ml = max_length(pno, is_extd, ep, format, p.start / unitsize(format), z);
2050 ml1 = ml * unitsize(format);
2051 def = orig ? orig->size : (pno > 4 && pct > 1) ? 0 : ml1;
2052 if (fno < 2 || !*(fields[1]))
2053 p.size = def;
2054 else {
2055 if (get_ul(fields[1], &ul, def / unitsize(0), 0))
2056 return 0;
2057 p.size = ul * unitsize(0) + unitsize(format) - 1;
2058 p.size -= (p.size % unitsize(format));
2059 }
2060 if (p.size > ml1) {
2061 warn("Warning: exceeds max allowable size (%lu)\n", ml1 / unitsize(0));
2062 if (!force)
2063 return 0;
2064 }
2065 if (p.size == 0 && pno >= 4 && (fno < 2 || !*(fields[1]))) {
2066 warn("Warning: empty partition\n");
2067 if (!force)
2068 return 0;
2069 }
2070 p.p.nr_sects = p.size;
2071
2072 if (p.size == 0 && !orig) {
2073 if(fno < 1 || !*(fields[0]))
2074 p.start = 0;
2075 if(fno < 3 || !*(fields[2]))
2076 p.p.sys_type = EMPTY_PARTITION;
2077 }
2078
2079 if (p.start < ff1 && p.size > 0) {
2080 warn("Warning: bad partition start (earliest %lu)\n",
2081 (ff1 + unitsize(0) - 1) / unitsize(0));
2082 if (!force)
2083 return 0;
2084 }
2085
2086 if (fno < 4 || !*(fields[3]))
2087 ul = (orig ? orig->p.bootable : 0);
2088 else if (!strcmp(fields[3], "-"))
2089 ul = 0;
2090 else if (!strcmp(fields[3], "*") || !strcmp(fields[3], "+"))
2091 ul = 0x80;
2092 else {
2093 warn("unrecognized bootable flag - choose - or *\n");
2094 return 0;
2095 }
2096 p.p.bootable = ul;
2097
2098 if (ep && ep->p.sys_type == EMPTY_PARTITION) {
2099 if(!build_surrounding_extended(&p, ep, z))
2100 return 0;
2101 } else
2102 if(!compute_start_sect(&p, ep))
2103 return 0;
2104 2129
2105 { longchs aa = chs_to_longchs(p.p.begin_chs), bb; 2130 /* find length */
2131 ml =
2132 max_length(pno, is_extd, ep, format, p.start / unitsize(format),
2133 z);
2134 ml1 = ml * unitsize(format);
2135 def = orig ? orig->size : (pno > 4 && pct > 1) ? 0 : ml1;
2136 if (fno < 2 || !*(fields[1]))
2137 p.size = def;
2138 else {
2139 if (get_ul(fields[1], &ul, def / unitsize(0), 0))
2140 return 0;
2141 p.size = ul * unitsize(0) + unitsize(format) - 1;
2142 p.size -= (p.size % unitsize(format));
2143 }
2144 if (p.size > ml1) {
2145 warn("Warning: exceeds max allowable size (%lu)\n",
2146 ml1 / unitsize(0));
2147 if (!force)
2148 return 0;
2149 }
2150 if (p.size == 0 && pno >= 4 && (fno < 2 || !*(fields[1]))) {
2151 warn("Warning: empty partition\n");
2152 if (!force)
2153 return 0;
2154 }
2155 p.p.nr_sects = p.size;
2106 2156
2107 if (fno < 5) { 2157 if (p.size == 0 && !orig) {
2108 bb = aa; 2158 if (fno < 1 || !*(fields[0]))
2109 } else if (fno < 7) { 2159 p.start = 0;
2110 warn("partial c,h,s specification?\n"); 2160 if (fno < 3 || !*(fields[2]))
2111 return 0; 2161 p.p.sys_type = EMPTY_PARTITION;
2112 } else if(get_ul(fields[4], &bb.c, aa.c, 0) || 2162 }
2113 get_ul(fields[5], &bb.h, aa.h, 0) || 2163
2114 get_ul(fields[6], &bb.s, aa.s, 0)) 2164 if (p.start < ff1 && p.size > 0) {
2115 return 0; 2165 warn("Warning: bad partition start (earliest %lu)\n",
2116 p.p.begin_chs = longchs_to_chs(bb,B); 2166 (ff1 + unitsize(0) - 1) / unitsize(0));
2117 } 2167 if (!force)
2118 { longchs aa = chs_to_longchs(p.p.end_chs), bb; 2168 return 0;
2119 2169 }
2120 if (fno < 8) { 2170
2121 bb = aa; 2171 if (fno < 4 || !*(fields[3]))
2122 } else if (fno < 10) { 2172 ul = (orig ? orig->p.bootable : 0);
2123 warn("partial c,h,s specification?\n"); 2173 else if (!strcmp(fields[3], "-"))
2124 return 0; 2174 ul = 0;
2125 } else if(get_ul(fields[7], &bb.c, aa.c, 0) || 2175 else if (!strcmp(fields[3], "*") || !strcmp(fields[3], "+"))
2126 get_ul(fields[8], &bb.h, aa.h, 0) || 2176 ul = 0x80;
2127 get_ul(fields[9], &bb.s, aa.s, 0)) 2177 else {
2128 return 0; 2178 warn("unrecognized bootable flag - choose - or *\n");
2129 p.p.end_chs = longchs_to_chs(bb, B); 2179 return 0;
2130 } 2180 }
2181 p.p.bootable = ul;
2182
2183 if (ep && ep->p.sys_type == EMPTY_PARTITION) {
2184 if (!build_surrounding_extended(&p, ep, z))
2185 return 0;
2186 } else if (!compute_start_sect(&p, ep))
2187 return 0;
2131 2188
2132 if (pno > 3 && p.size && show_extended && p.p.sys_type != EMPTY_PARTITION 2189 {
2133 && (is_extended(p.p.sys_type) != (pct == 1))) { 2190 longchs aa = chs_to_longchs(p.p.begin_chs), bb;
2134 warn("Extended partition not where expected\n"); 2191
2135 if (!force) 2192 if (fno < 5) {
2136 return 0; 2193 bb = aa;
2137 } 2194 } else if (fno < 7) {
2195 warn("partial c,h,s specification?\n");
2196 return 0;
2197 } else if (get_ul(fields[4], &bb.c, aa.c, 0) ||
2198 get_ul(fields[5], &bb.h, aa.h, 0) ||
2199 get_ul(fields[6], &bb.s, aa.s, 0))
2200 return 0;
2201 p.p.begin_chs = longchs_to_chs(bb, B);
2202 }
2203 {
2204 longchs aa = chs_to_longchs(p.p.end_chs), bb;
2205
2206 if (fno < 8) {
2207 bb = aa;
2208 } else if (fno < 10) {
2209 warn("partial c,h,s specification?\n");
2210 return 0;
2211 } else if (get_ul(fields[7], &bb.c, aa.c, 0) ||
2212 get_ul(fields[8], &bb.h, aa.h, 0) ||
2213 get_ul(fields[9], &bb.s, aa.s, 0))
2214 return 0;
2215 p.p.end_chs = longchs_to_chs(bb, B);
2216 }
2217
2218 if (pno > 3 && p.size && show_extended
2219 && p.p.sys_type != EMPTY_PARTITION
2220 && (is_extended(p.p.sys_type) != (pct == 1))) {
2221 warn("Extended partition not where expected\n");
2222 if (!force)
2223 return 0;
2224 }
2138 2225
2139 z->partitions[pno] = p; 2226 z->partitions[pno] = p;
2140 if (pno >= z->partno) 2227 if (pno >= z->partno)
2141 z->partno += 4; /* reqd for out_partition() */ 2228 z->partno += 4; /* reqd for out_partition() */
2142 2229
2143 if (interactive) 2230 if (interactive)
2144 out_partition(dev, 0, &(z->partitions[pno]), z, B); 2231 out_partition(dev, 0, &(z->partitions[pno]), z, B);
2145 2232
2146 return 1; 2233 return 1;
2147} 2234}
2148 2235
2149/* ep either points to the extended partition to contain this one, 2236/* ep either points to the extended partition to contain this one,
2150 or to the empty partition that may become extended or is 0 */ 2237 or to the empty partition that may become extended or is 0 */
2151static int 2238static int
2152read_partition(char *dev, int interactive, int pno, struct part_desc *ep, 2239read_partition(char *dev, int interactive, int pno, struct part_desc *ep,
2153 struct disk_desc *z) { 2240 struct disk_desc *z)
2154 struct part_desc *p = &(z->partitions[pno]); 2241{
2155 int i; 2242 struct part_desc *p = &(z->partitions[pno]);
2156 2243 int i;
2157 if (one_only) { 2244
2158 *p = oldp.partitions[pno]; 2245 if (one_only) {
2159 if (one_only_pno != pno) 2246 *p = oldp.partitions[pno];
2160 goto ret; 2247 if (one_only_pno != pno)
2161 } else if (!show_extended && pno > 4 && pno%4) 2248 goto ret;
2162 goto ret; 2249 } else if (!show_extended && pno > 4 && pno % 4)
2163 2250 goto ret;
2164 while (!(i = read_line(pno, ep, dev, interactive, z))) 2251
2165 if (!interactive) 2252 while (!(i = read_line(pno, ep, dev, interactive, z)))
2166 fatal("bad input\n"); 2253 if (!interactive)
2167 if (i < 0) { 2254 fatal("bad input\n");
2168 p->ep = ep; 2255 if (i < 0) {
2169 return 0; 2256 p->ep = ep;
2170 } 2257 return 0;
2258 }
2171 2259
2172 ret: 2260 ret:
2173 p->ep = ep; 2261 p->ep = ep;
2174 if (pno >= z->partno) 2262 if (pno >= z->partno)
2175 z->partno += 4; 2263 z->partno += 4;
2176 return 1; 2264 return 1;
2177} 2265}
2178 2266
2179static void 2267static void
2180read_partition_chain(char *dev, int interactive, struct part_desc *ep, 2268read_partition_chain(char *dev, int interactive, struct part_desc *ep,
2181 struct disk_desc *z) { 2269 struct disk_desc *z)
2182 int i, base; 2270{
2183 2271 int i, base;
2184 eob = 0; 2272
2185 while (1) { 2273 eob = 0;
2186 base = z->partno; 2274 while (1) {
2187 if (base+4 > SIZE(z->partitions)) { 2275 base = z->partno;
2188 printf("too many partitions\n"); 2276 if (base + 4 > SIZE(z->partitions)) {
2189 break; 2277 printf("too many partitions\n");
2190 } 2278 break;
2191 for (i=0; i<4; i++) 2279 }
2192 if (!read_partition(dev, interactive, base+i, ep, z)) 2280 for (i = 0; i < 4; i++)
2193 return; 2281 if (!read_partition(dev, interactive, base + i, ep, z))
2194 for (i=0; i<4; i++) { 2282 return;
2195 ep = &(z->partitions[base+i]); 2283 for (i = 0; i < 4; i++) {
2196 if (is_extended(ep->p.sys_type) && ep->size) 2284 ep = &(z->partitions[base + i]);
2197 break; 2285 if (is_extended(ep->p.sys_type) && ep->size)
2198 } 2286 break;
2199 if (i == 4) { 2287 }
2200 /* nothing found - maybe an empty partition is going 2288 if (i == 4) {
2201 to be extended */ 2289 /* nothing found - maybe an empty partition is going
2202 if (one_only || show_extended) 2290 to be extended */
2203 break; 2291 if (one_only || show_extended)
2204 ep = &(z->partitions[base+1]); 2292 break;
2205 if (ep->size || ep->p.sys_type != EMPTY_PARTITION) 2293 ep = &(z->partitions[base + 1]);
2206 break; 2294 if (ep->size || ep->p.sys_type != EMPTY_PARTITION)
2207 } 2295 break;
2208 } 2296 }
2297 }
2209} 2298}
2210 2299
2211static void 2300static void read_input(char *dev, int interactive, struct disk_desc *z)
2212read_input(char *dev, int interactive, struct disk_desc *z) { 2301{
2213 int i; 2302 int i;
2214 struct part_desc *partitions = &(z->partitions[0]), *ep; 2303 struct part_desc *partitions = &(z->partitions[0]), *ep;
2215 2304
2216 for (i=0; i < SIZE(z->partitions); i++) 2305 for (i = 0; i < SIZE(z->partitions); i++)
2217 partitions[i] = zero_part_desc; 2306 partitions[i] = zero_part_desc;
2218 z->partno = 0; 2307 z->partno = 0;
2219 2308
2220 if (interactive) 2309 if (interactive)
2221 warn("Input in the following format; absent fields get a default value.\n" 2310 warn
2222 "<start> <size> <type [E,S,L,X,hex]> <bootable [-,*]> <c,h,s> <c,h,s>\n" 2311 ("Input in the following format; absent fields get a default value.\n"
2223 "Usually you only need to specify <start> and <size> (and perhaps <type>).\n"); 2312 "<start> <size> <type [E,S,L,X,hex]> <bootable [-,*]> <c,h,s> <c,h,s>\n"
2224 eof = 0; 2313 "Usually you only need to specify <start> and <size> (and perhaps <type>).\n");
2225 2314 eof = 0;
2226 for (i=0; i<4; i++) 2315
2227 read_partition(dev, interactive, i, 0, z); 2316 for (i = 0; i < 4; i++)
2228 for (i=0; i<4; i++) { 2317 read_partition(dev, interactive, i, 0, z);
2229 ep = partitions+i; 2318 for (i = 0; i < 4; i++) {
2230 if (is_extended(ep->p.sys_type) && ep->size) 2319 ep = partitions + i;
2231 read_partition_chain(dev, interactive, ep, z); 2320 if (is_extended(ep->p.sys_type) && ep->size)
2232 } 2321 read_partition_chain(dev, interactive, ep, z);
2233 add_sector_and_offset(z); 2322 }
2323 add_sector_and_offset(z);
2234} 2324}
2235 2325
2236/* 2326/*
2237 * G. The command line 2327 * G. The command line
2238 */ 2328 */
2239 2329
2240static void version(void) { 2330static void version(void)
2241 printf("%s %s %s (aeb@cwi.nl, %s)\n", PROGNAME, "version", VERSION, DATE); 2331{
2332 printf("%s %s %s (aeb@cwi.nl, %s)\n", PROGNAME, "version", VERSION,
2333 DATE);
2242} 2334}
2243 2335
2244static char short_opts[] = "cdfgilnqsu:vx?1A::C:DH:I:LN:O:RS:TU::V"; 2336static char short_opts[] = "cdfgilnqsu:vx?1A::C:DH:I:LN:O:RS:TU::V";
@@ -2247,77 +2339,78 @@ static char short_opts[] = "cdfgilnqsu:vx?1A::C:DH:I:LN:O:RS:TU::V";
2247#define CHANGE_ID 01000 2339#define CHANGE_ID 01000
2248 2340
2249static const struct option long_opts[] = { 2341static const struct option long_opts[] = {
2250 { "change-id", no_argument, NULL, 'c' + CHANGE_ID }, 2342 {"change-id", no_argument, NULL, 'c' + CHANGE_ID},
2251 { "print-id", no_argument, NULL, 'c' + PRINT_ID }, 2343 {"print-id", no_argument, NULL, 'c' + PRINT_ID},
2252 { "id", no_argument, NULL, 'c' }, 2344 {"id", no_argument, NULL, 'c'},
2253 { "dump", no_argument, NULL, 'd' }, 2345 {"dump", no_argument, NULL, 'd'},
2254 { "force", no_argument, NULL, 'f' }, 2346 {"force", no_argument, NULL, 'f'},
2255 { "show-geometry", no_argument, NULL, 'g' }, 2347 {"show-geometry", no_argument, NULL, 'g'},
2256 { "increment", no_argument, NULL, 'i' }, 2348 {"increment", no_argument, NULL, 'i'},
2257 { "list", no_argument, NULL, 'l' }, 2349 {"list", no_argument, NULL, 'l'},
2258 { "quiet", no_argument, NULL, 'q' }, 2350 {"quiet", no_argument, NULL, 'q'},
2259 { "show-size", no_argument, NULL, 's' }, 2351 {"show-size", no_argument, NULL, 's'},
2260 { "unit", required_argument, NULL, 'u' }, 2352 {"unit", required_argument, NULL, 'u'},
2261 { "version", no_argument, NULL, 'v' }, 2353 {"version", no_argument, NULL, 'v'},
2262 { "show-extended", no_argument, NULL, 'x' }, 2354 {"show-extended", no_argument, NULL, 'x'},
2263 { "help", no_argument, NULL, '?' }, 2355 {"help", no_argument, NULL, '?'},
2264 { "one-only", no_argument, NULL, '1' }, 2356 {"one-only", no_argument, NULL, '1'},
2265 { "cylinders", required_argument, NULL, 'C' }, 2357 {"cylinders", required_argument, NULL, 'C'},
2266 { "heads", required_argument, NULL, 'H' }, 2358 {"heads", required_argument, NULL, 'H'},
2267 { "sectors", required_argument, NULL, 'S' }, 2359 {"sectors", required_argument, NULL, 'S'},
2268 { "activate", optional_argument, NULL, 'A' }, 2360 {"activate", optional_argument, NULL, 'A'},
2269 { "DOS", no_argument, NULL, 'D' }, 2361 {"DOS", no_argument, NULL, 'D'},
2270 { "Linux", no_argument, NULL, 'L' }, 2362 {"Linux", no_argument, NULL, 'L'},
2271 { "re-read", no_argument, NULL, 'R' }, 2363 {"re-read", no_argument, NULL, 'R'},
2272 { "list-types", no_argument, NULL, 'T' }, 2364 {"list-types", no_argument, NULL, 'T'},
2273 { "unhide", optional_argument, NULL, 'U' }, 2365 {"unhide", optional_argument, NULL, 'U'},
2274 { "no-reread", no_argument, NULL, 160 }, 2366 {"no-reread", no_argument, NULL, 160},
2275 { "IBM", no_argument, NULL, 161 }, 2367 {"IBM", no_argument, NULL, 161},
2276 { "leave-last", no_argument, NULL, 161 }, 2368 {"leave-last", no_argument, NULL, 161},
2277/* undocumented flags - not all completely implemented */ 2369/* undocumented flags - not all completely implemented */
2278 { "in-order", no_argument, NULL, 128 }, 2370 {"in-order", no_argument, NULL, 128},
2279 { "not-in-order", no_argument, NULL, 129 }, 2371 {"not-in-order", no_argument, NULL, 129},
2280 { "inside-outer", no_argument, NULL, 130 }, 2372 {"inside-outer", no_argument, NULL, 130},
2281 { "not-inside-outer", no_argument, NULL, 131 }, 2373 {"not-inside-outer", no_argument, NULL, 131},
2282 { "nested", no_argument, NULL, 132 }, 2374 {"nested", no_argument, NULL, 132},
2283 { "chained", no_argument, NULL, 133 }, 2375 {"chained", no_argument, NULL, 133},
2284 { "onesector", no_argument, NULL, 134 }, 2376 {"onesector", no_argument, NULL, 134},
2285 { NULL, 0, NULL, 0 } 2377 {NULL, 0, NULL, 0}
2286}; 2378};
2287 2379
2288/* default devices to list */ 2380/* default devices to list */
2289static struct devd { 2381static struct devd {
2290 char *pref, *letters; 2382 char *pref, *letters;
2291} defdevs[] = { 2383} defdevs[] = {
2292 { "hd", "abcdefgh" }, 2384 {
2293 { "sd", "abcde" }, 2385 "hd", "abcdefgh"}, {
2294 { "xd", "ab" }, 2386 "sd", "abcde"}, {
2295 { "ed", "abcd" } 2387 "xd", "ab"}, {
2388 "ed", "abcd"}
2296}; 2389};
2297 2390
2298static int 2391static int is_ide_cdrom(char *device)
2299is_ide_cdrom(char *device) { 2392{
2300 /* No device was given explicitly, and we are trying some 2393 /* No device was given explicitly, and we are trying some
2301 likely things. But opening /dev/hdc may produce errors like 2394 likely things. But opening /dev/hdc may produce errors like
2302 "hdc: tray open or drive not ready" 2395 "hdc: tray open or drive not ready"
2303 if it happens to be a CD-ROM drive. So try to be careful. 2396 if it happens to be a CD-ROM drive. So try to be careful.
2304 This only works since 2.1.73. */ 2397 This only works since 2.1.73. */
2305 2398
2306 FILE *procf; 2399 FILE *procf;
2307 char buf[100]; 2400 char buf[100];
2308 struct stat statbuf; 2401 struct stat statbuf;
2309 2402
2310 sprintf(buf, "/proc/ide/%s/media", device+5); 2403 sprintf(buf, "/proc/ide/%s/media", device + 5);
2311 procf = fopen(buf, "r"); 2404 procf = fopen(buf, "r");
2312 if (procf != NULL && fgets(buf, sizeof(buf), procf)) 2405 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2313 return !strncmp(buf, "cdrom", 5); 2406 return !strncmp(buf, "cdrom", 5);
2314 2407
2315 /* Now when this proc file does not exist, skip the 2408 /* Now when this proc file does not exist, skip the
2316 device when it is read-only. */ 2409 device when it is read-only. */
2317 if (stat(device, &statbuf) == 0) 2410 if (stat(device, &statbuf) == 0)
2318 return (statbuf.st_mode & 0222) == 0; 2411 return (statbuf.st_mode & 0222) == 0;
2319 2412
2320 return 0; 2413 return 0;
2321} 2414}
2322 2415
2323static void do_list(char *dev, int silent); 2416static void do_list(char *dev, int silent);
@@ -2331,275 +2424,310 @@ static void do_activate(char **av, int ac, char *arg);
2331 2424
2332static int total_size; 2425static int total_size;
2333 2426
2334extern int 2427extern int sfdisk_main(int argc, char **argv)
2335sfdisk_main(int argc, char **argv) { 2428{
2336 int c; 2429 int c;
2337 char *dev; 2430 char *dev;
2338 int opt_size = 0; 2431 int opt_size = 0;
2339 int opt_out_geom = 0; 2432 int opt_out_geom = 0;
2340 int opt_reread = 0; 2433 int opt_reread = 0;
2341 int activate = 0; 2434 int activate = 0;
2342 int do_id = 0; 2435 int do_id = 0;
2343 int unhide = 0; 2436 int unhide = 0;
2344 char *activatearg = 0; 2437 char *activatearg = 0;
2345 char *unhidearg = 0; 2438 char *unhidearg = 0;
2346 2439
2347 if (argc < 1) 2440 if (argc < 1)
2348 usage(sfdisk_usage); 2441 usage(sfdisk_usage);
2349 2442
2350 while ((c = getopt_long (argc, argv, short_opts, long_opts, NULL)) != -1) { 2443 while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) !=
2351 switch (c) { 2444 -1) {
2352 case 'f': 2445 switch (c) {
2353 force = 1; break; /* does not imply quiet */ 2446 case 'f':
2354 case 'g': 2447 force = 1;
2355 opt_out_geom = 1; break; 2448 break; /* does not imply quiet */
2356 case 'i': 2449 case 'g':
2357 increment = 1; break; 2450 opt_out_geom = 1;
2358 case 'c': 2451 break;
2359 case 'c' + PRINT_ID: 2452 case 'i':
2360 case 'c' + CHANGE_ID: 2453 increment = 1;
2361 do_id = c; break; 2454 break;
2362 case 'd': 2455 case 'c':
2363 dump = 1; /* fall through */ 2456 case 'c' + PRINT_ID:
2364 case 'l': 2457 case 'c' + CHANGE_ID:
2365 opt_list = 1; break; 2458 do_id = c;
2366 case 'n': 2459 break;
2367 no_write = 1; break; 2460 case 'd':
2368 case 'q': 2461 dump = 1; /* fall through */
2369 quiet = 1; break; 2462 case 'l':
2370 case 's': 2463 opt_list = 1;
2371 opt_size = 1; break; 2464 break;
2372 case 'u': 2465 case 'n':
2373 set_format(*optarg); break; 2466 no_write = 1;
2374 case 'v': 2467 break;
2375 version(); 2468 case 'q':
2376 exit(0); 2469 quiet = 1;
2377 case 'x': 2470 break;
2378 show_extended = 1; break; 2471 case 's':
2379 case 'A': 2472 opt_size = 1;
2380 activatearg = optarg; 2473 break;
2381 activate = 1; break; 2474 case 'u':
2382 case 'C': 2475 set_format(*optarg);
2383 U.cylinders = atoi(optarg); break; 2476 break;
2384 case 'D': 2477 case 'v':
2385 DOS = 1; break; 2478 version();
2386 case 'H': 2479 exit(0);
2387 U.heads = atoi(optarg); break; 2480 case 'x':
2388 case 'L': 2481 show_extended = 1;
2389 Linux = 1; break; 2482 break;
2390 case 'N': 2483 case 'A':
2391 one_only = atoi(optarg); break; 2484 activatearg = optarg;
2392 case 'I': 2485 activate = 1;
2393 restore_sector_file = optarg; break; 2486 break;
2394 case 'O': 2487 case 'C':
2395 save_sector_file = optarg; break; 2488 U.cylinders = atoi(optarg);
2396 case 'R': 2489 break;
2397 opt_reread = 1; break; 2490 case 'D':
2398 case 'S': 2491 DOS = 1;
2399 U.sectors = atoi(optarg); break; 2492 break;
2400 case 'T': 2493 case 'H':
2401 list_types(); 2494 U.heads = atoi(optarg);
2402 exit(0); 2495 break;
2403 case 'U': 2496 case 'L':
2404 unhidearg = optarg; 2497 Linux = 1;
2405 unhide = 1; break; 2498 break;
2406 case 'V': 2499 case 'N':
2407 verify = 1; break; 2500 one_only = atoi(optarg);
2408 case '?': 2501 break;
2409 default: 2502 case 'I':
2410 usage(sfdisk_usage); 2503 restore_sector_file = optarg;
2411 2504 break;
2412 /* undocumented flags */ 2505 case 'O':
2413 case 128: 2506 save_sector_file = optarg;
2414 partitions_in_order = 1; break; 2507 break;
2415 case 129: 2508 case 'R':
2416 partitions_in_order = 0; break; 2509 opt_reread = 1;
2417 case 130: 2510 break;
2418 all_logicals_inside_outermost_extended = 1; break; 2511 case 'S':
2419 case 131: 2512 U.sectors = atoi(optarg);
2420 all_logicals_inside_outermost_extended = 0; break; 2513 break;
2421 case 132: 2514 case 'T':
2422 boxes = NESTED; break; 2515 list_types();
2423 case 133: 2516 exit(0);
2424 boxes = CHAINED; break; 2517 case 'U':
2425 case 134: 2518 unhidearg = optarg;
2426 boxes = ONESECTOR; break; 2519 unhide = 1;
2427 2520 break;
2428 /* more flags */ 2521 case 'V':
2429 case 160: 2522 verify = 1;
2430 no_reread = 1; break; 2523 break;
2431 case 161: 2524 case '?':
2432 leave_last = 1; break; 2525 default:
2433 } 2526 usage(sfdisk_usage);
2434 } 2527
2435 2528 /* undocumented flags */
2436 if (optind == argc && (opt_list || opt_out_geom || opt_size || verify)) { 2529 case 128:
2437 struct devd *dp; 2530 partitions_in_order = 1;
2438 char *lp; 2531 break;
2439 char device[10]; 2532 case 129:
2440 2533 partitions_in_order = 0;
2441 total_size = 0; 2534 break;
2442 2535 case 130:
2443 for(dp = defdevs; dp-defdevs < SIZE(defdevs); dp++) { 2536 all_logicals_inside_outermost_extended = 1;
2444 lp = dp->letters; 2537 break;
2445 while(*lp) { 2538 case 131:
2446 sprintf(device, "/dev/%s%c", dp->pref, *lp++); 2539 all_logicals_inside_outermost_extended = 0;
2447 if (!strcmp(dp->pref, "hd") && is_ide_cdrom(device)) 2540 break;
2448 continue; 2541 case 132:
2449 if (opt_out_geom) 2542 boxes = NESTED;
2450 do_geom(device, 1); 2543 break;
2451 if (opt_size) 2544 case 133:
2452 do_size(device, 1); 2545 boxes = CHAINED;
2453 if (opt_list || verify) 2546 break;
2454 do_list(device, 1); 2547 case 134:
2455 } 2548 boxes = ONESECTOR;
2549 break;
2550
2551 /* more flags */
2552 case 160:
2553 no_reread = 1;
2554 break;
2555 case 161:
2556 leave_last = 1;
2557 break;
2558 }
2456 } 2559 }
2457 2560
2458 if (opt_size) 2561 if (optind == argc && (opt_list || opt_out_geom || opt_size || verify)) {
2459 printf("total: %d blocks\n", total_size); 2562 struct devd *dp;
2563 char *lp;
2564 char device[10];
2565
2566 total_size = 0;
2567
2568 for (dp = defdevs; dp - defdevs < SIZE(defdevs); dp++) {
2569 lp = dp->letters;
2570 while (*lp) {
2571 sprintf(device, "/dev/%s%c", dp->pref, *lp++);
2572 if (!strcmp(dp->pref, "hd") && is_ide_cdrom(device))
2573 continue;
2574 if (opt_out_geom)
2575 do_geom(device, 1);
2576 if (opt_size)
2577 do_size(device, 1);
2578 if (opt_list || verify)
2579 do_list(device, 1);
2580 }
2581 }
2582
2583 if (opt_size)
2584 printf("total: %d blocks\n", total_size);
2460 2585
2461 exit(exit_status); 2586 exit(exit_status);
2462 } 2587 }
2463 2588
2464 if (optind == argc) usage(sfdisk_usage); 2589 if (optind == argc)
2590 usage(sfdisk_usage);
2591
2592 if (opt_list || opt_out_geom || opt_size || verify) {
2593 while (optind < argc) {
2594 if (opt_out_geom)
2595 do_geom(argv[optind], 0);
2596 if (opt_size)
2597 do_size(argv[optind], 0);
2598 if (opt_list || verify)
2599 do_list(argv[optind], 0);
2600 optind++;
2601 }
2602 exit(exit_status);
2603 }
2465 2604
2466 if (opt_list || opt_out_geom || opt_size || verify) { 2605 if (activate) {
2467 while (optind < argc) { 2606 do_activate(argv + optind, argc - optind, activatearg);
2468 if (opt_out_geom) 2607 exit(exit_status);
2469 do_geom(argv[optind], 0); 2608 }
2470 if (opt_size) 2609 if (unhide) {
2471 do_size(argv[optind], 0); 2610 do_unhide(argv + optind, argc - optind, unhidearg);
2472 if (opt_list || verify) 2611 exit(exit_status);
2473 do_list(argv[optind], 0); 2612 }
2474 optind++; 2613 if (do_id) {
2614 if ((do_id & PRINT_ID) != 0 && optind != argc - 2)
2615 fatal("usage: sfdisk --print-id device partition-number\n");
2616 else if ((do_id & CHANGE_ID) != 0 && optind != argc - 3)
2617 fatal
2618 ("usage: sfdisk --change-id device partition-number Id\n");
2619 else if (optind != argc - 3 && optind != argc - 2)
2620 fatal("usage: sfdisk --id device partition-number [Id]\n");
2621 do_change_id(argv[optind], argv[optind + 1],
2622 (optind == argc - 2) ? 0 : argv[optind + 2]);
2623 exit(exit_status);
2475 } 2624 }
2476 exit(exit_status);
2477 }
2478 2625
2479 if (activate) { 2626 if (optind != argc - 1)
2480 do_activate(argv+optind, argc-optind, activatearg); 2627 fatal("can specify only one device (except with -l or -s)\n");
2481 exit(exit_status); 2628 dev = argv[optind];
2482 }
2483 if (unhide) {
2484 do_unhide(argv+optind, argc-optind, unhidearg);
2485 exit(exit_status);
2486 }
2487 if (do_id) {
2488 if ((do_id & PRINT_ID) != 0 && optind != argc-2)
2489 fatal("usage: sfdisk --print-id device partition-number\n");
2490 else if ((do_id & CHANGE_ID) != 0 && optind != argc-3)
2491 fatal("usage: sfdisk --change-id device partition-number Id\n");
2492 else if (optind != argc-3 && optind != argc-2)
2493 fatal("usage: sfdisk --id device partition-number [Id]\n");
2494 do_change_id(argv[optind], argv[optind+1],
2495 (optind == argc-2) ? 0 : argv[optind+2]);
2496 exit(exit_status);
2497 }
2498
2499 if (optind != argc-1)
2500 fatal("can specify only one device (except with -l or -s)\n");
2501 dev = argv[optind];
2502 2629
2503 if (opt_reread) 2630 if (opt_reread)
2504 do_reread(dev); 2631 do_reread(dev);
2505 else if (restore_sector_file) 2632 else if (restore_sector_file)
2506 restore_sectors(dev); 2633 restore_sectors(dev);
2507 else 2634 else
2508 do_fdisk(dev); 2635 do_fdisk(dev);
2509 2636
2510 return ( TRUE); 2637 return (TRUE);
2511} 2638}
2512 2639
2513/* 2640/*
2514 * H. Listing the current situation 2641 * H. Listing the current situation
2515 */ 2642 */
2516 2643
2517static int 2644static int my_open(char *dev, int rw, int silent)
2518my_open (char *dev, int rw, int silent) { 2645{
2519 int fd, mode; 2646 int fd, mode;
2520 2647
2521 mode = (rw ? O_RDWR : O_RDONLY); 2648 mode = (rw ? O_RDWR : O_RDONLY);
2522 fd = open(dev, mode); 2649 fd = open(dev, mode);
2523 if (fd < 0 && !silent) { 2650 if (fd < 0 && !silent) {
2524 perror(dev); 2651 perror(dev);
2525 fatal("cannot open %s %s\n", dev, rw ? "read-write" : "for reading"); 2652 fatal("cannot open %s %s\n", dev,
2526 } 2653 rw ? "read-write" : "for reading");
2527 return fd; 2654 }
2655 return fd;
2528} 2656}
2529 2657
2530static void 2658static void do_list(char *dev, int silent)
2531do_list (char *dev, int silent) { 2659{
2532 int fd; 2660 int fd;
2533 struct disk_desc *z; 2661 struct disk_desc *z;
2534 2662
2535 fd = my_open(dev, 0, silent); 2663 fd = my_open(dev, 0, silent);
2536 if (fd < 0) 2664 if (fd < 0)
2537 return; 2665 return;
2538 2666
2539 z = &oldp; 2667 z = &oldp;
2540 2668
2541 free_sectors(); 2669 free_sectors();
2542 get_cylindersize(dev, fd, dump ? 1 : opt_list ? 0 : 1); 2670 get_cylindersize(dev, fd, dump ? 1 : opt_list ? 0 : 1);
2543 get_partitions(dev, fd, z); 2671 get_partitions(dev, fd, z);
2544 2672
2545 if (opt_list) 2673 if (opt_list)
2546 out_partitions(dev, z); 2674 out_partitions(dev, z);
2547 2675
2548 if (verify) { 2676 if (verify) {
2549 if (partitions_ok(z)) 2677 if (partitions_ok(z))
2550 warn("%s: OK\n"), dev; 2678 warn("%s: OK\n"), dev;
2551 else 2679 else
2552 exit_status = 1; 2680 exit_status = 1;
2553 } 2681 }
2554} 2682}
2555 2683
2556static void 2684static void do_geom(char *dev, int silent)
2557do_geom (char *dev, int silent) { 2685{
2558 int fd; 2686 int fd;
2559 struct hd_geometry g; 2687 struct hd_geometry g;
2560 2688
2561 fd = my_open(dev, 0, silent); 2689 fd = my_open(dev, 0, silent);
2562 if (fd < 0) 2690 if (fd < 0)
2563 return; 2691 return;
2564 2692
2565 /* get_cylindersize(dev, fd, silent); */ 2693 /* get_cylindersize(dev, fd, silent); */
2566 if (!ioctl(fd, HDIO_GETGEO, &g)) 2694 if (!ioctl(fd, HDIO_GETGEO, &g))
2567 printf("%s: %d cylinders, %d heads, %d sectors/track\n", 2695 printf("%s: %d cylinders, %d heads, %d sectors/track\n",
2568 dev, g.cylinders, g.heads, g.sectors); 2696 dev, g.cylinders, g.heads, g.sectors);
2569 else 2697 else
2570 printf("%s: unknown geometry\n", dev); 2698 printf("%s: unknown geometry\n", dev);
2571} 2699}
2572 2700
2573/* for compatibility with earlier fdisk: provide option -s */ 2701/* for compatibility with earlier fdisk: provide option -s */
2574static void 2702static void do_size(char *dev, int silent)
2575do_size (char *dev, int silent) { 2703{
2576 int fd; 2704 int fd;
2577 long size; 2705 long size;
2578 2706
2579 fd = my_open(dev, 0, silent); 2707 fd = my_open(dev, 0, silent);
2580 if (fd < 0) 2708 if (fd < 0)
2581 return; 2709 return;
2582 2710
2583 if(ioctl(fd, BLKGETSIZE, &size)) { 2711 if (ioctl(fd, BLKGETSIZE, &size)) {
2584 if(!silent) { 2712 if (!silent) {
2585 perror(dev); 2713 perror(dev);
2586 fatal("BLKGETSIZE ioctl failed for %s\n"), dev; 2714 fatal("BLKGETSIZE ioctl failed for %s\n"), dev;
2715 }
2716 return;
2587 } 2717 }
2588 return;
2589 }
2590 2718
2591 size /= 2; /* convert sectors to blocks */ 2719 size /= 2; /* convert sectors to blocks */
2592 2720
2593 /* a CDROM drive without mounted CD yields MAXINT */ 2721 /* a CDROM drive without mounted CD yields MAXINT */
2594 if (silent && size == ((1<<30)-1)) 2722 if (silent && size == ((1 << 30) - 1))
2595 return; 2723 return;
2596 2724
2597 if (silent) 2725 if (silent)
2598 printf("%s: %9ld\n", dev, size); 2726 printf("%s: %9ld\n", dev, size);
2599 else 2727 else
2600 printf("%ld\n", size); 2728 printf("%ld\n", size);
2601 2729
2602 total_size += size; 2730 total_size += size;
2603} 2731}
2604 2732
2605/* 2733/*
@@ -2626,255 +2754,263 @@ do_size (char *dev, int silent) {
2626 * The present syntax was chosen to be (somewhat) compatible with the 2754 * The present syntax was chosen to be (somewhat) compatible with the
2627 * activate from the LILO package. 2755 * activate from the LILO package.
2628 */ 2756 */
2629static void 2757static void set_active(struct disk_desc *z, char *pnam)
2630set_active (struct disk_desc *z, char *pnam) { 2758{
2631 int pno; 2759 int pno;
2632 2760
2633 pno = asc_to_index(pnam, z); 2761 pno = asc_to_index(pnam, z);
2634 z->partitions[pno].p.bootable = 0x80; 2762 z->partitions[pno].p.bootable = 0x80;
2635} 2763}
2636 2764
2637static void 2765static void do_activate(char **av, int ac, char *arg)
2638do_activate (char **av, int ac, char *arg) { 2766{
2639 char *dev = av[0]; 2767 char *dev = av[0];
2640 int fd; 2768 int fd;
2641 int rw, i, pno, lpno; 2769 int rw, i, pno, lpno;
2642 struct disk_desc *z; 2770 struct disk_desc *z;
2643 2771
2644 z = &oldp; 2772 z = &oldp;
2645 2773
2646 rw = (!no_write && (arg || ac > 1)); 2774 rw = (!no_write && (arg || ac > 1));
2647 fd = my_open(dev, rw, 0); 2775 fd = my_open(dev, rw, 0);
2648 2776
2649 free_sectors(); 2777 free_sectors();
2650 get_cylindersize(dev, fd, 1); 2778 get_cylindersize(dev, fd, 1);
2651 get_partitions(dev, fd, z); 2779 get_partitions(dev, fd, z);
2652 2780
2653 if (!arg && ac == 1) { 2781 if (!arg && ac == 1) {
2654 /* list active partitions */ 2782 /* list active partitions */
2655 for (pno=0; pno < z->partno; pno++) { 2783 for (pno = 0; pno < z->partno; pno++) {
2656 if (z->partitions[pno].p.bootable) { 2784 if (z->partitions[pno].p.bootable) {
2657 lpno = index_to_linux(pno, z); 2785 lpno = index_to_linux(pno, z);
2658 if (pno == linux_to_index(lpno, z)) 2786 if (pno == linux_to_index(lpno, z))
2659 printf("%s%d\n", dev, lpno); 2787 printf("%s%d\n", dev, lpno);
2788 else
2789 printf("%s#%d\n", dev, pno);
2790 if (z->partitions[pno].p.bootable != 0x80)
2791 warn("bad active byte: 0x%x instead of 0x80\n",
2792 z->partitions[pno].p.bootable);
2793 }
2794 }
2795 } else {
2796 /* clear `active byte' everywhere */
2797 for (pno = 0; pno < z->partno; pno++)
2798 z->partitions[pno].p.bootable = 0;
2799
2800 /* then set where desired */
2801 if (ac == 1)
2802 set_active(z, arg);
2660 else 2803 else
2661 printf("%s#%d\n", dev, pno); 2804 for (i = 1; i < ac; i++)
2662 if (z->partitions[pno].p.bootable != 0x80) 2805 set_active(z, av[i]);
2663 warn("bad active byte: 0x%x instead of 0x80\n",
2664 z->partitions[pno].p.bootable);
2665 }
2666 }
2667 } else {
2668 /* clear `active byte' everywhere */
2669 for (pno=0; pno < z->partno; pno++)
2670 z->partitions[pno].p.bootable = 0;
2671
2672 /* then set where desired */
2673 if (ac == 1)
2674 set_active(z, arg);
2675 else for(i=1; i<ac; i++)
2676 set_active(z, av[i]);
2677 2806
2678 /* then write to disk */ 2807 /* then write to disk */
2679 if(write_partitions(dev, fd, z)) 2808 if (write_partitions(dev, fd, z))
2680 warn("Done\n\n"); 2809 warn("Done\n\n");
2810 else
2811 exit_status = 1;
2812 }
2813 i = 0;
2814 for (pno = 0; pno < z->partno && pno < 4; pno++)
2815 if (z->partitions[pno].p.bootable)
2816 i++;
2817 if (i != 1)
2818 warn
2819 ("You have %d active primary partitions. This does not matter for LILO,\n"
2820 "but the DOS MBR will only boot a disk with 1 active partition.\n",
2821 i);
2822}
2823
2824static void set_unhidden(struct disk_desc *z, char *pnam)
2825{
2826 int pno;
2827 unsigned char id;
2828
2829 pno = asc_to_index(pnam, z);
2830 id = z->partitions[pno].p.sys_type;
2831 if (id == 0x11 || id == 0x14 || id == 0x16 || id == 0x17)
2832 id -= 0x10;
2681 else 2833 else
2682 exit_status = 1; 2834 fatal("partition %s has id %x and is not hidden\n", pnam, id);
2683 } 2835 z->partitions[pno].p.sys_type = id;
2684 i = 0;
2685 for (pno=0; pno < z->partno && pno < 4; pno++)
2686 if (z->partitions[pno].p.bootable)
2687 i++;
2688 if (i != 1)
2689 warn("You have %d active primary partitions. This does not matter for LILO,\n"
2690 "but the DOS MBR will only boot a disk with 1 active partition.\n", i);
2691}
2692
2693static void
2694set_unhidden (struct disk_desc *z, char *pnam) {
2695 int pno;
2696 unsigned char id;
2697
2698 pno = asc_to_index(pnam, z);
2699 id = z->partitions[pno].p.sys_type;
2700 if (id == 0x11 || id == 0x14 || id == 0x16 || id == 0x17)
2701 id -= 0x10;
2702 else
2703 fatal("partition %s has id %x and is not hidden\n", pnam, id);
2704 z->partitions[pno].p.sys_type = id;
2705} 2836}
2706 2837
2707/* 2838/*
2708 * maybe remove and make part of --change-id 2839 * maybe remove and make part of --change-id
2709 */ 2840 */
2710static void 2841static void do_unhide(char **av, int ac, char *arg)
2711do_unhide (char **av, int ac, char *arg) { 2842{
2712 char *dev = av[0]; 2843 char *dev = av[0];
2713 int fd, rw, i; 2844 int fd, rw, i;
2714 struct disk_desc *z; 2845 struct disk_desc *z;
2715 2846
2716 z = &oldp; 2847 z = &oldp;
2717 2848
2718 rw = !no_write; 2849 rw = !no_write;
2719 fd = my_open(dev, rw, 0); 2850 fd = my_open(dev, rw, 0);
2720 2851
2721 free_sectors(); 2852 free_sectors();
2722 get_cylindersize(dev, fd, 1); 2853 get_cylindersize(dev, fd, 1);
2723 get_partitions(dev, fd, z); 2854 get_partitions(dev, fd, z);
2724 2855
2725 /* unhide where desired */ 2856 /* unhide where desired */
2726 if (ac == 1) 2857 if (ac == 1)
2727 set_unhidden(z, arg); 2858 set_unhidden(z, arg);
2728 else for(i=1; i<ac; i++) 2859 else
2729 set_unhidden(z, av[i]); 2860 for (i = 1; i < ac; i++)
2861 set_unhidden(z, av[i]);
2730 2862
2731 /* then write to disk */ 2863 /* then write to disk */
2732 if(write_partitions(dev, fd, z)) 2864 if (write_partitions(dev, fd, z))
2733 warn("Done\n\n"); 2865 warn("Done\n\n");
2734 else 2866 else
2735 exit_status = 1; 2867 exit_status = 1;
2736} 2868}
2737 2869
2738static void do_change_id(char *dev, char *pnam, char *id) { 2870static void do_change_id(char *dev, char *pnam, char *id)
2739 int fd, rw, pno; 2871{
2740 struct disk_desc *z; 2872 int fd, rw, pno;
2741 unsigned long i; 2873 struct disk_desc *z;
2874 unsigned long i;
2742 2875
2743 z = &oldp; 2876 z = &oldp;
2744 2877
2745 rw = !no_write; 2878 rw = !no_write;
2746 fd = my_open(dev, rw, 0); 2879 fd = my_open(dev, rw, 0);
2747 2880
2748 free_sectors(); 2881 free_sectors();
2749 get_cylindersize(dev, fd, 1); 2882 get_cylindersize(dev, fd, 1);
2750 get_partitions(dev, fd, z); 2883 get_partitions(dev, fd, z);
2751 2884
2752 pno = asc_to_index(pnam, z); 2885 pno = asc_to_index(pnam, z);
2753 if (id == 0) { 2886 if (id == 0) {
2754 printf("%x\n", z->partitions[pno].p.sys_type); 2887 printf("%x\n", z->partitions[pno].p.sys_type);
2755 return; 2888 return;
2756 } 2889 }
2757 i = strtoul(id, NULL, 16); 2890 i = strtoul(id, NULL, 16);
2758 if (i > 255) 2891 if (i > 255)
2759 fatal("Bad Id %x\n"), i; 2892 fatal("Bad Id %x\n"), i;
2760 z->partitions[pno].p.sys_type = i; 2893 z->partitions[pno].p.sys_type = i;
2761 2894
2762 if(write_partitions(dev, fd, z)) 2895 if (write_partitions(dev, fd, z))
2763 warn("Done\n\n"); 2896 warn("Done\n\n");
2764 else 2897 else
2765 exit_status = 1; 2898 exit_status = 1;
2766} 2899}
2767 2900
2768static void 2901static void do_reread(char *dev)
2769do_reread(char *dev) { 2902{
2770 int fd; 2903 int fd;
2771 2904
2772 fd = my_open(dev, 0, 0); 2905 fd = my_open(dev, 0, 0);
2773 if(reread_ioctl(fd)) 2906 if (reread_ioctl(fd))
2774 printf("This disk is currently in use.\n"); 2907 printf("This disk is currently in use.\n");
2775} 2908}
2776 2909
2777/* 2910/*
2778 * I. Writing the new situation 2911 * I. Writing the new situation
2779 */ 2912 */
2780 2913
2781static void 2914static void do_fdisk(char *dev)
2782do_fdisk(char *dev){ 2915{
2783 int fd; 2916 int fd;
2784 int c, answer; 2917 int c, answer;
2785 struct stat statbuf; 2918 struct stat statbuf;
2786 int interactive = isatty(0); 2919 int interactive = isatty(0);
2787 struct disk_desc *z; 2920 struct disk_desc *z;
2788 2921
2789 if (stat(dev, &statbuf) < 0) { 2922 if (stat(dev, &statbuf) < 0) {
2790 perror(dev); 2923 perror(dev);
2791 fatal("Fatal error: cannot find %s\n"), dev; 2924 fatal("Fatal error: cannot find %s\n"), dev;
2792 } 2925 }
2793 if (!S_ISBLK(statbuf.st_mode)) { 2926 if (!S_ISBLK(statbuf.st_mode)) {
2794 warn("Warning: %s is not a block device\n"), dev; 2927 warn("Warning: %s is not a block device\n"), dev;
2795 no_reread = 1; 2928 no_reread = 1;
2796 } 2929 }
2797 fd = my_open(dev, !no_write, 0); 2930 fd = my_open(dev, !no_write, 0);
2798 2931
2799 if(!no_write && !no_reread) { 2932 if (!no_write && !no_reread) {
2800 warn("Checking that no-one is using this disk right now ...\n"); 2933 warn("Checking that no-one is using this disk right now ...\n");
2801 if(reread_ioctl(fd)) { 2934 if (reread_ioctl(fd)) {
2802 printf("\nThis disk is currently in use - repartitioning is probably a bad idea." 2935 printf
2803 "Umount all file systems, and swapoff all swap partitions on this disk." 2936 ("\nThis disk is currently in use - repartitioning is probably a bad idea."
2804 "Use the --no-reread flag to suppress this check.\n"); 2937 "Umount all file systems, and swapoff all swap partitions on this disk."
2805 if (!force) { 2938 "Use the --no-reread flag to suppress this check.\n");
2806 printf("Use the --force flag to overrule all checks.\n"); 2939 if (!force) {
2807 exit(1); 2940 printf("Use the --force flag to overrule all checks.\n");
2808 } 2941 exit(1);
2809 } else 2942 }
2810 warn("OK"); 2943 } else
2811 } 2944 warn("OK");
2945 }
2812 2946
2813 z = &oldp; 2947 z = &oldp;
2814 2948
2815 free_sectors(); 2949 free_sectors();
2816 get_cylindersize(dev, fd, 0); 2950 get_cylindersize(dev, fd, 0);
2817 get_partitions(dev, fd, z); 2951 get_partitions(dev, fd, z);
2818 2952
2819 printf("Old situation:\n"); 2953 printf("Old situation:\n");
2820 out_partitions(dev, z); 2954 out_partitions(dev, z);
2821 2955
2822 if (one_only && (one_only_pno = linux_to_index(one_only, z)) < 0) 2956 if (one_only && (one_only_pno = linux_to_index(one_only, z)) < 0)
2823 fatal("Partition %d does not exist, cannot change it\n"), one_only; 2957 fatal("Partition %d does not exist, cannot change it\n"), one_only;
2824 2958
2825 z = &newp; 2959 z = &newp;
2826 2960
2827 while(1) { 2961 while (1) {
2828 2962
2829 read_input(dev, interactive, z); 2963 read_input(dev, interactive, z);
2830 2964
2831 printf("New situation:\n"); 2965 printf("New situation:\n");
2832 out_partitions(dev, z); 2966 out_partitions(dev, z);
2833 2967
2834 if (!partitions_ok(z) && !force) { 2968 if (!partitions_ok(z) && !force) {
2835 if(!interactive) 2969 if (!interactive)
2836 fatal("I don't like these partitions - nothing changed.\n" 2970 fatal("I don't like these partitions - nothing changed.\n"
2837 "(If you really want this, use the --force option.)\n"); 2971 "(If you really want this, use the --force option.)\n");
2838 else 2972 else
2839 printf("I don't like this - probably you should answer No\n"); 2973 printf
2974 ("I don't like this - probably you should answer No\n");
2975 }
2976 ask:
2977 if (interactive) {
2978 if (no_write)
2979 printf("Are you satisfied with this? [ynq] ");
2980 else
2981 printf("Do you want to write this to disk? [ynq] ");
2982 answer = c = getchar();
2983 while (c != '\n' && c != EOF)
2984 c = getchar();
2985 if (c == EOF)
2986 printf("\nsfdisk: premature end of input\n");
2987 if (c == EOF || answer == 'q' || answer == 'Q') {
2988 fatal("Quitting - nothing changed\n");
2989 } else if (answer == 'n' || answer == 'N') {
2990 continue;
2991 } else if (answer == 'y' || answer == 'Y') {
2992 break;
2993 } else {
2994 printf("Please answer one of y,n,q\n");
2995 goto ask;
2996 }
2997 } else
2998 break;
2840 } 2999 }
2841 ask: 3000
2842 if (interactive) { 3001 if (write_partitions(dev, fd, z))
2843 if (no_write) 3002 printf("Successfully wrote the new partition table\n\n");
2844 printf("Are you satisfied with this? [ynq] "); 3003 else
2845 else 3004 exit_status = 1;
2846 printf("Do you want to write this to disk? [ynq] "); 3005
2847 answer = c = getchar(); 3006 reread_disk_partition(dev, fd);
2848 while (c != '\n' && c != EOF) 3007
2849 c = getchar(); 3008 warn
2850 if (c == EOF) 3009 ("If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)\n"
2851 printf("\nsfdisk: premature end of input\n"); 3010 "to zero the first 512 bytes: dd if=/dev/zero of=/dev/foo7 bs=512 count=1\n"
2852 if (c == EOF || answer == 'q' || answer == 'Q') { 3011 "(See fdisk(8).)\n");
2853 fatal("Quitting - nothing changed\n"); 3012
2854 } else if (answer == 'n' || answer == 'N') { 3013 sync(); /* superstition */
2855 continue; 3014 sleep(3);
2856 } else if (answer == 'y' || answer == 'Y') { 3015 exit(exit_status);
2857 break;
2858 } else {
2859 printf("Please answer one of y,n,q\n");
2860 goto ask;
2861 }
2862 } else
2863 break;
2864 }
2865
2866 if(write_partitions(dev, fd, z))
2867 printf("Successfully wrote the new partition table\n\n");
2868 else
2869 exit_status = 1;
2870
2871 reread_disk_partition(dev, fd);
2872
2873 warn("If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)\n"
2874 "to zero the first 512 bytes: dd if=/dev/zero of=/dev/foo7 bs=512 count=1\n"
2875 "(See fdisk(8).)\n");
2876
2877 sync(); /* superstition */
2878 sleep(3);
2879 exit(exit_status);
2880} 3016}