aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-10-12 19:30:44 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-10-12 19:30:44 +0000
commit98ae2160b62b99424e5793e97d5abd4e3c2e576b (patch)
tree58f4e56d32330ea4abe200f3b2b0e21392d944e1
parenta6dbb08a48903cb8f31fad2cf2d1cffa92bd4808 (diff)
downloadbusybox-w32-98ae2160b62b99424e5793e97d5abd4e3c2e576b.tar.gz
busybox-w32-98ae2160b62b99424e5793e97d5abd4e3c2e576b.tar.bz2
busybox-w32-98ae2160b62b99424e5793e97d5abd4e3c2e576b.zip
fdisk: separate sun/aix/etc code into #included files
-rw-r--r--util-linux/fdisk.c3408
-rw-r--r--util-linux/fdisk_aix.c76
-rw-r--r--util-linux/fdisk_osf.c1046
-rw-r--r--util-linux/fdisk_sgi.c887
-rw-r--r--util-linux/fdisk_sun.c731
5 files changed, 3004 insertions, 3144 deletions
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c
index 3bf78ee04..ab8946744 100644
--- a/util-linux/fdisk.c
+++ b/util-linux/fdisk.c
@@ -7,50 +7,13 @@
7 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. 7 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
8 */ 8 */
9 9
10/* Current changes have not compatibility with this version */
11#define UTIL_LINUX_VERSION "2.12"
12
13
14#define _(x) x
15
16#define PROC_PARTITIONS "/proc/partitions"
17
18#include <features.h>
19#include <sys/types.h>
20#include <sys/stat.h> /* stat */
21#include <ctype.h>
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include <errno.h>
26#include <unistd.h>
27#include <fcntl.h>
28#include <setjmp.h>
29#include <assert.h> /* assert */ 10#include <assert.h> /* assert */
30#include <getopt.h>
31#include <endian.h>
32#include <sys/ioctl.h>
33#include <sys/param.h>
34#include <sys/sysmacros.h> /* major */
35
36#include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
37
38/* Copied from linux/major.h */
39#define FLOPPY_MAJOR 2
40
41#include <sys/utsname.h>
42
43#include "busybox.h" 11#include "busybox.h"
44 12#define _(x) x
45#define DKTYPENAMES
46
47/*
48 fdisk.h
49*/
50 13
51#define DEFAULT_SECTOR_SIZE 512 14#define DEFAULT_SECTOR_SIZE 512
52#define MAX_SECTOR_SIZE 2048 15#define MAX_SECTOR_SIZE 2048
53#define SECTOR_SIZE 512 /* still used in BSD code */ 16#define SECTOR_SIZE 512 /* still used in osf/sgi/sun code */
54#define MAXIMUM_PARTS 60 17#define MAXIMUM_PARTS 60
55 18
56#define ACTIVE_FLAG 0x80 19#define ACTIVE_FLAG 0x80
@@ -64,9 +27,6 @@
64#define LINUX_LVM 0x8e 27#define LINUX_LVM 0x8e
65#define LINUX_RAID 0xfd 28#define LINUX_RAID 0xfd
66 29
67#define SUNOS_SWAP 3
68#define WHOLE_DISK 5
69
70#define IS_EXTENDED(i) \ 30#define IS_EXTENDED(i) \
71 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED) 31 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
72 32
@@ -75,12 +35,6 @@
75#define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n)) 35#define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
76#define scround(x) (((x)+units_per_sector-1)/units_per_sector) 36#define scround(x) (((x)+units_per_sector-1)/units_per_sector)
77 37
78#ifdef CONFIG_FEATURE_SUN_LABEL
79#define SCSI_IOCTL_GET_IDLUN 0x5382
80#endif
81
82
83/* including <linux/hdreg.h> also fails */
84struct hd_geometry { 38struct hd_geometry {
85 unsigned char heads; 39 unsigned char heads;
86 unsigned char sectors; 40 unsigned char sectors;
@@ -88,8 +42,7 @@ struct hd_geometry {
88 unsigned long start; 42 unsigned long start;
89}; 43};
90 44
91#define HDIO_GETGEO 0x0301 /* get device geometry */ 45#define HDIO_GETGEO 0x0301 /* get device geometry */
92
93 46
94struct systypes { 47struct systypes {
95 const char *name; 48 const char *name;
@@ -174,9 +127,30 @@ enum failure {
174 unable_to_write 127 unable_to_write
175}; 128};
176 129
177enum label_type{ 130enum label_type {
178 label_dos, label_sun, label_sgi, label_aix, label_osf 131 label_dos, label_sun, label_sgi, label_aix, label_osf
179}; 132};
133#define LABEL_IS_DOS (label_dos == current_label_type)
134#ifdef CONFIG_FEATURE_SUN_LABEL
135#define LABEL_IS_SUN (label_sun == current_label_type)
136#else
137#define LABEL_IS_SUN 0
138#endif
139#ifdef CONFIG_FEATURE_SGI_LABEL
140#define LABEL_IS_SGI (label_sgi == current_label_type)
141#else
142#define LABEL_IS_SGI 0
143#endif
144#ifdef CONFIG_FEATURE_AIX_LABEL
145#define LABEL_IS_AIX (label_aix == current_label_type)
146#else
147#define LABEL_IS_AIX 0
148#endif
149#ifdef CONFIG_FEATURE_OSF_LABEL
150#define LABEL_IS_OSF (label_osf == current_label_type)
151#else
152#define LABEL_IS_OSF 0
153#endif
180 154
181enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun }; 155enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
182 156
@@ -188,7 +162,6 @@ static int partitions = 4; /* maximum partition + 1 */
188static uint display_in_cyl_units = 1; 162static uint display_in_cyl_units = 1;
189static uint units_per_sector = 1; 163static uint units_per_sector = 1;
190#ifdef CONFIG_FEATURE_FDISK_WRITABLE 164#ifdef CONFIG_FEATURE_FDISK_WRITABLE
191static char *line_ptr;
192static void change_units(void); 165static void change_units(void);
193static void reread_partition_table(int leave); 166static void reread_partition_table(int leave);
194static void delete_partition(int i); 167static void delete_partition(int i);
@@ -268,13 +241,11 @@ set_changed(int i)
268} 241}
269#endif /* CONFIG_FEATURE_FDISK_WRITABLE */ 242#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
270 243
271#if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL) 244static inline struct partition *
272static struct partition *
273get_part_table(int i) 245get_part_table(int i)
274{ 246{
275 return ptes[i].part_table; 247 return ptes[i].part_table;
276} 248}
277#endif
278 249
279static const char * 250static const char *
280str_units(int n) 251str_units(int n)
@@ -286,30 +257,25 @@ str_units(int n)
286} 257}
287 258
288static int 259static int
289valid_part_table_flag(const char *mbuffer) { 260valid_part_table_flag(const char *mbuffer)
261{
290 const unsigned char *b = (const unsigned char *)mbuffer; 262 const unsigned char *b = (const unsigned char *)mbuffer;
291 return (b[510] == 0x55 && b[511] == 0xaa); 263 return (b[510] == 0x55 && b[511] == 0xaa);
292} 264}
293 265
294#ifdef CONFIG_FEATURE_FDISK_WRITABLE 266#ifdef CONFIG_FEATURE_FDISK_WRITABLE
295static char line_buffer[LINE_LENGTH]; 267static char line_buffer[LINE_LENGTH];
268static char *line_ptr;
296 269
297/* read line; return 0 or first char */ 270/* read line; return 0 or first char */
298static int 271static int
299read_line(void) 272read_line(void)
300{ 273{
301 static int got_eof = 0; 274 fflush(stdout); /* requested by niles@scyld.com */
302
303 fflush (stdout); /* requested by niles@scyld.com */
304 line_ptr = line_buffer; 275 line_ptr = line_buffer;
305 if (!fgets(line_buffer, LINE_LENGTH, stdin)) { 276 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
306 if (feof(stdin)) 277 /* error or eof */
307 got_eof++; /* user typed ^D ? */ 278 bb_error_msg_and_die("\ngot EOF - exiting...");
308 if (got_eof >= 3) {
309 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
310 exit(1);
311 }
312 return 0;
313 } 279 }
314 while (*line_ptr && !isgraph(*line_ptr)) 280 while (*line_ptr && !isgraph(*line_ptr))
315 line_ptr++; 281 line_ptr++;
@@ -317,7 +283,7 @@ read_line(void)
317} 283}
318 284
319static char 285static char
320read_char(const char *mesg) 286read_nonempty(const char *mesg)
321{ 287{
322 do { 288 do {
323 fputs(mesg, stdout); 289 fputs(mesg, stdout);
@@ -326,10 +292,11 @@ read_char(const char *mesg)
326} 292}
327 293
328static char 294static char
329read_chars(const char *mesg) 295read_maybe_empty(const char *mesg)
330{ 296{
331 fputs(mesg, stdout); 297 fputs(mesg, stdout);
332 if (!read_line()) { 298 if (!read_line()) {
299 line_ptr = line_buffer;
333 *line_ptr = '\n'; 300 *line_ptr = '\n';
334 line_ptr[1] = 0; 301 line_ptr[1] = 0;
335 } 302 }
@@ -339,440 +306,33 @@ read_chars(const char *mesg)
339static int 306static int
340read_hex(const struct systypes *sys) 307read_hex(const struct systypes *sys)
341{ 308{
342 int hex;
343
344 while (1) { 309 while (1) {
345 read_char(_("Hex code (type L to list codes): ")); 310 read_nonempty(_("Hex code (type L to list codes): "));
346 if (*line_ptr == 'l' || *line_ptr == 'L') 311 if (*line_ptr == 'l' || *line_ptr == 'L')
347 list_types(sys); 312 list_types(sys);
348 else if (isxdigit (*line_ptr)) { 313 else if (isxdigit(*line_ptr)) {
349 hex = 0; 314 return strtoul(line_ptr, NULL, 16);
350 do
351 hex = hex << 4 | hex_val(*line_ptr++);
352 while (isxdigit(*line_ptr));
353 return hex;
354 } 315 }
355 } 316 }
356} 317}
357#endif /* CONFIG_FEATURE_FDISK_WRITABLE */ 318#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
358 319
359#ifdef CONFIG_FEATURE_AIX_LABEL 320static const struct systypes sgi_sys_types[];
360/* 321static unsigned int sgi_get_num_sectors(int i);
361 * Copyright (C) Andreas Neuper, Sep 1998. 322static int sgi_get_sysid(int i);
362 * This file may be redistributed under 323static void sgi_delete_partition(int i);
363 * the terms of the GNU Public License. 324static void sgi_change_sysid(int i, int sys);
364 */ 325static void sgi_list_table(int xtra);
365 326static void sgi_set_xcyl(void);
366typedef struct { 327static int verify_sgi(int verbose);
367 unsigned int magic; /* expect AIX_LABEL_MAGIC */ 328static void sgi_add_partition(int n, int sys);
368 unsigned int fillbytes1[124]; 329static void sgi_set_swappartition(int i);
369 unsigned int physical_volume_id; 330static const char *sgi_get_bootfile(void);
370 unsigned int fillbytes2[124]; 331static void sgi_set_bootfile(const char* aFile);
371} aix_partition; 332static void create_sgiinfo(void);
372 333static void sgi_write_table(void);
373#define AIX_LABEL_MAGIC 0xc9c2d4c1 334static void sgi_set_bootpartition(int i);
374#define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9 335#include "fdisk_aix.c"
375#define AIX_INFO_MAGIC 0x00072959
376#define AIX_INFO_MAGIC_SWAPPED 0x59290700
377
378#define aixlabel ((aix_partition *)MBRbuffer)
379
380
381/*
382 Changes:
383 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
384 * Internationalization
385 *
386 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
387 * Some fixes
388*/
389
390static int aix_other_endian;
391static short aix_volumes = 1;
392
393/*
394 * only dealing with free blocks here
395 */
396
397static void
398aix_info(void)
399{
400 puts(
401 _("\n\tThere is a valid AIX label on this disk.\n"
402 "\tUnfortunately Linux cannot handle these\n"
403 "\tdisks at the moment. Nevertheless some\n"
404 "\tadvice:\n"
405 "\t1. fdisk will destroy its contents on write.\n"
406 "\t2. Be sure that this disk is NOT a still vital\n"
407 "\t part of a volume group. (Otherwise you may\n"
408 "\t erase the other disks as well, if unmirrored.)\n"
409 "\t3. Before deleting this physical volume be sure\n"
410 "\t to remove the disk logically from your AIX\n"
411 "\t machine. (Otherwise you become an AIXpert).")
412 );
413}
414
415static int
416check_aix_label(void)
417{
418 if (aixlabel->magic != AIX_LABEL_MAGIC &&
419 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
420 current_label_type = 0;
421 aix_other_endian = 0;
422 return 0;
423 }
424 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
425 update_units();
426 current_label_type = label_aix;
427 partitions = 1016;
428 aix_volumes = 15;
429 aix_info();
430 /*aix_nolabel();*/ /* %% */
431 /*aix_label = 1;*/ /* %% */
432 return 1;
433}
434#endif /* AIX_LABEL */
435
436#ifdef CONFIG_FEATURE_OSF_LABEL
437/*
438 * Copyright (c) 1987, 1988 Regents of the University of California.
439 * All rights reserved.
440 *
441 * Redistribution and use in source and binary forms, with or without
442 * modification, are permitted provided that the following conditions
443 * are met:
444 * 1. Redistributions of source code must retain the above copyright
445 * notice, this list of conditions and the following disclaimer.
446 * 2. Redistributions in binary form must reproduce the above copyright
447 * notice, this list of conditions and the following disclaimer in the
448 * documentation and/or other materials provided with the distribution.
449 * 3. All advertising materials mentioning features or use of this software
450 * must display the following acknowledgment:
451 * This product includes software developed by the University of
452 * California, Berkeley and its contributors.
453 * 4. Neither the name of the University nor the names of its contributors
454 * may be used to endorse or promote products derived from this software
455 * without specific prior written permission.
456 *
457 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
458 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
459 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
460 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
461 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
462 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
463 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
464 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
465 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
466 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
467 * SUCH DAMAGE.
468 */
469
470
471#ifndef BSD_DISKMAGIC
472#define BSD_DISKMAGIC ((uint32_t) 0x82564557)
473#endif
474
475#ifndef BSD_MAXPARTITIONS
476#define BSD_MAXPARTITIONS 16
477#endif
478
479#define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
480
481#if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__m68k__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
482#define BSD_LABELSECTOR 1
483#define BSD_LABELOFFSET 0
484#elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
485#define BSD_LABELSECTOR 0
486#define BSD_LABELOFFSET 64
487#elif defined (__s390__) || defined (__s390x__)
488#define BSD_LABELSECTOR 1
489#define BSD_LABELOFFSET 0
490#else
491#error unknown architecture
492#endif
493
494#define BSD_BBSIZE 8192 /* size of boot area, with label */
495#define BSD_SBSIZE 8192 /* max size of fs superblock */
496
497struct xbsd_disklabel {
498 uint32_t d_magic; /* the magic number */
499 int16_t d_type; /* drive type */
500 int16_t d_subtype; /* controller/d_type specific */
501 char d_typename[16]; /* type name, e.g. "eagle" */
502 char d_packname[16]; /* pack identifier */
503 /* disk geometry: */
504 uint32_t d_secsize; /* # of bytes per sector */
505 uint32_t d_nsectors; /* # of data sectors per track */
506 uint32_t d_ntracks; /* # of tracks per cylinder */
507 uint32_t d_ncylinders; /* # of data cylinders per unit */
508 uint32_t d_secpercyl; /* # of data sectors per cylinder */
509 uint32_t d_secperunit; /* # of data sectors per unit */
510 /*
511 * Spares (bad sector replacements) below
512 * are not counted in d_nsectors or d_secpercyl.
513 * Spare sectors are assumed to be physical sectors
514 * which occupy space at the end of each track and/or cylinder.
515 */
516 uint16_t d_sparespertrack; /* # of spare sectors per track */
517 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
518 /*
519 * Alternate cylinders include maintenance, replacement,
520 * configuration description areas, etc.
521 */
522 uint32_t d_acylinders; /* # of alt. cylinders per unit */
523
524 /* hardware characteristics: */
525 /*
526 * d_interleave, d_trackskew and d_cylskew describe perturbations
527 * in the media format used to compensate for a slow controller.
528 * Interleave is physical sector interleave, set up by the formatter
529 * or controller when formatting. When interleaving is in use,
530 * logically adjacent sectors are not physically contiguous,
531 * but instead are separated by some number of sectors.
532 * It is specified as the ratio of physical sectors traversed
533 * per logical sector. Thus an interleave of 1:1 implies contiguous
534 * layout, while 2:1 implies that logical sector 0 is separated
535 * by one sector from logical sector 1.
536 * d_trackskew is the offset of sector 0 on track N
537 * relative to sector 0 on track N-1 on the same cylinder.
538 * Finally, d_cylskew is the offset of sector 0 on cylinder N
539 * relative to sector 0 on cylinder N-1.
540 */
541 uint16_t d_rpm; /* rotational speed */
542 uint16_t d_interleave; /* hardware sector interleave */
543 uint16_t d_trackskew; /* sector 0 skew, per track */
544 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
545 uint32_t d_headswitch; /* head switch time, usec */
546 uint32_t d_trkseek; /* track-to-track seek, usec */
547 uint32_t d_flags; /* generic flags */
548#define NDDATA 5
549 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
550#define NSPARE 5
551 uint32_t d_spare[NSPARE]; /* reserved for future use */
552 uint32_t d_magic2; /* the magic number (again) */
553 uint16_t d_checksum; /* xor of data incl. partitions */
554 /* filesystem and partition information: */
555 uint16_t d_npartitions; /* number of partitions in following */
556 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
557 uint32_t d_sbsize; /* max size of fs superblock, bytes */
558 struct xbsd_partition { /* the partition table */
559 uint32_t p_size; /* number of sectors in partition */
560 uint32_t p_offset; /* starting sector */
561 uint32_t p_fsize; /* filesystem basic fragment size */
562 uint8_t p_fstype; /* filesystem type, see below */
563 uint8_t p_frag; /* filesystem fragments per block */
564 uint16_t p_cpg; /* filesystem cylinders per group */
565 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
566};
567
568/* d_type values: */
569#define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
570#define BSD_DTYPE_MSCP 2 /* MSCP */
571#define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
572#define BSD_DTYPE_SCSI 4 /* SCSI */
573#define BSD_DTYPE_ESDI 5 /* ESDI interface */
574#define BSD_DTYPE_ST506 6 /* ST506 etc. */
575#define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
576#define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
577#define BSD_DTYPE_FLOPPY 10 /* floppy */
578
579/* d_subtype values: */
580#define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
581#define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
582#define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
583
584#ifdef DKTYPENAMES
585static const char * const xbsd_dktypenames[] = {
586 "unknown",
587 "SMD",
588 "MSCP",
589 "old DEC",
590 "SCSI",
591 "ESDI",
592 "ST506",
593 "HP-IB",
594 "HP-FL",
595 "type 9",
596 "floppy",
597 0
598};
599#define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
600#endif
601
602/*
603 * Filesystem type and version.
604 * Used to interpret other filesystem-specific
605 * per-partition information.
606 */
607#define BSD_FS_UNUSED 0 /* unused */
608#define BSD_FS_SWAP 1 /* swap */
609#define BSD_FS_V6 2 /* Sixth Edition */
610#define BSD_FS_V7 3 /* Seventh Edition */
611#define BSD_FS_SYSV 4 /* System V */
612#define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
613#define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
614#define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
615#define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
616#define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
617#define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
618#define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
619#define BSD_FS_ISOFS BSD_FS_ISO9660
620#define BSD_FS_BOOT 13 /* partition contains bootstrap */
621#define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
622#define BSD_FS_HFS 15 /* Macintosh HFS */
623#define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
624
625/* this is annoying, but it's also the way it is :-( */
626#ifdef __alpha__
627#define BSD_FS_EXT2 8 /* ext2 file system */
628#else
629#define BSD_FS_MSDOS 8 /* MS-DOS file system */
630#endif
631
632#ifdef DKTYPENAMES
633static const struct systypes xbsd_fstypes[] = {
634 { "\x00" "unused" }, /* BSD_FS_UNUSED */
635 { "\x01" "swap" }, /* BSD_FS_SWAP */
636 { "\x02" "Version 6" }, /* BSD_FS_V6 */
637 { "\x03" "Version 7" }, /* BSD_FS_V7 */
638 { "\x04" "System V" }, /* BSD_FS_SYSV */
639 { "\x05" "4.1BSD" }, /* BSD_FS_V71K */
640 { "\x06" "Eighth Edition" }, /* BSD_FS_V8 */
641 { "\x07" "4.2BSD" }, /* BSD_FS_BSDFFS */
642#ifdef __alpha__
643 { "\x08" "ext2" }, /* BSD_FS_EXT2 */
644#else
645 { "\x08" "MS-DOS" }, /* BSD_FS_MSDOS */
646#endif
647 { "\x09" "4.4LFS" }, /* BSD_FS_BSDLFS */
648 { "\x0a" "unknown" }, /* BSD_FS_OTHER */
649 { "\x0b" "HPFS" }, /* BSD_FS_HPFS */
650 { "\x0c" "ISO-9660" }, /* BSD_FS_ISO9660 */
651 { "\x0d" "boot" }, /* BSD_FS_BOOT */
652 { "\x0e" "ADOS" }, /* BSD_FS_ADOS */
653 { "\x0f" "HFS" }, /* BSD_FS_HFS */
654 { "\x10" "AdvFS" }, /* BSD_FS_ADVFS */
655 { NULL }
656};
657#define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
658
659#endif
660
661/*
662 * flags shared by various drives:
663 */
664#define BSD_D_REMOVABLE 0x01 /* removable media */
665#define BSD_D_ECC 0x02 /* supports ECC */
666#define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
667#define BSD_D_RAMDISK 0x08 /* disk emulator */
668#define BSD_D_CHAIN 0x10 /* can do back-back transfers */
669#define BSD_D_DOSPART 0x20 /* within MSDOS partition */
670
671#endif /* OSF_LABEL */
672
673/*
674 * Copyright (C) Andreas Neuper, Sep 1998.
675 * This file may be modified and redistributed under
676 * the terms of the GNU Public License.
677 */
678
679struct device_parameter { /* 48 bytes */
680 unsigned char skew;
681 unsigned char gap1;
682 unsigned char gap2;
683 unsigned char sparecyl;
684 unsigned short pcylcount;
685 unsigned short head_vol0;
686 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
687 unsigned char cmd_tag_queue_depth;
688 unsigned char unused0;
689 unsigned short unused1;
690 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
691 unsigned short bytes;
692 unsigned short ilfact;
693 unsigned int flags; /* controller flags */
694 unsigned int datarate;
695 unsigned int retries_on_error;
696 unsigned int ms_per_word;
697 unsigned short xylogics_gap1;
698 unsigned short xylogics_syncdelay;
699 unsigned short xylogics_readdelay;
700 unsigned short xylogics_gap2;
701 unsigned short xylogics_readgate;
702 unsigned short xylogics_writecont;
703};
704
705#define SGI_VOLHDR 0x00
706/* 1 and 2 were used for drive types no longer supported by SGI */
707#define SGI_SWAP 0x03
708/* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
709#define SGI_VOLUME 0x06
710#define SGI_EFS 0x07
711#define SGI_LVOL 0x08
712#define SGI_RLVOL 0x09
713#define SGI_XFS 0x0a
714#define SGI_XFSLOG 0x0b
715#define SGI_XLV 0x0c
716#define SGI_XVM 0x0d
717#define ENTIRE_DISK SGI_VOLUME
718/*
719 * controller flags
720 */
721#define SECTOR_SLIP 0x01
722#define SECTOR_FWD 0x02
723#define TRACK_FWD 0x04
724#define TRACK_MULTIVOL 0x08
725#define IGNORE_ERRORS 0x10
726#define RESEEK 0x20
727#define ENABLE_CMDTAGQ 0x40
728
729typedef struct {
730 unsigned int magic; /* expect SGI_LABEL_MAGIC */
731 unsigned short boot_part; /* active boot partition */
732 unsigned short swap_part; /* active swap partition */
733 unsigned char boot_file[16]; /* name of the bootfile */
734 struct device_parameter devparam; /* 1 * 48 bytes */
735 struct volume_directory { /* 15 * 16 bytes */
736 unsigned char vol_file_name[8]; /* a character array */
737 unsigned int vol_file_start; /* number of logical block */
738 unsigned int vol_file_size; /* number of bytes */
739 } directory[15];
740 struct sgi_partition { /* 16 * 12 bytes */
741 unsigned int num_sectors; /* number of blocks */
742 unsigned int start_sector; /* must be cylinder aligned */
743 unsigned int id;
744 } partitions[16];
745 unsigned int csum;
746 unsigned int fillbytes;
747} sgi_partition;
748
749typedef struct {
750 unsigned int magic; /* looks like a magic number */
751 unsigned int a2;
752 unsigned int a3;
753 unsigned int a4;
754 unsigned int b1;
755 unsigned short b2;
756 unsigned short b3;
757 unsigned int c[16];
758 unsigned short d[3];
759 unsigned char scsi_string[50];
760 unsigned char serial[137];
761 unsigned short check1816;
762 unsigned char installer[225];
763} sgiinfo;
764
765#define SGI_LABEL_MAGIC 0x0be5a941
766#define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
767#define SGI_INFO_MAGIC 0x00072959
768#define SGI_INFO_MAGIC_SWAPPED 0x59290700
769#define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
770 : (uint16_t)(x))
771#define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
772 : (uint32_t)(x))
773
774#define sgilabel ((sgi_partition *)MBRbuffer)
775#define sgiparam (sgilabel->devparam)
776 336
777typedef struct { 337typedef struct {
778 unsigned char info[128]; /* Informative text string */ 338 unsigned char info[128]; /* Informative text string */
@@ -794,841 +354,33 @@ typedef struct {
794 unsigned short ntrks; /* Tracks per cylinder */ 354 unsigned short ntrks; /* Tracks per cylinder */
795 unsigned short nsect; /* Sectors per track */ 355 unsigned short nsect; /* Sectors per track */
796 unsigned char spare3[4]; /* Even more magic... */ 356 unsigned char spare3[4]; /* Even more magic... */
797 struct sun_partition { 357 struct sun_partinfo {
798 uint32_t start_cylinder; 358 uint32_t start_cylinder;
799 uint32_t num_sectors; 359 uint32_t num_sectors;
800 } partitions[8]; 360 } partitions[8];
801 unsigned short magic; /* Magic number */ 361 unsigned short magic; /* Magic number */
802 unsigned short csum; /* Label xor'd checksum */ 362 unsigned short csum; /* Label xor'd checksum */
803} sun_partition; 363} sun_partition;
804
805
806#define SUN_LABEL_MAGIC 0xDABE
807#define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
808#define sunlabel ((sun_partition *)MBRbuffer) 364#define sunlabel ((sun_partition *)MBRbuffer)
809#define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \ 365#define SUNOS_SWAP 3
810 : (uint16_t)(x)) 366#define SUN_WHOLE_DISK 5
811#define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \ 367static void bselect(void);
812 : (uint32_t)(x))
813
814
815#ifdef CONFIG_FEATURE_OSF_LABEL
816/*
817 Changes:
818 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
819
820 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
821 support for OSF/1 disklabels on Alpha.
822 Also fixed unaligned accesses in alpha_bootblock_checksum()
823*/
824
825#define FREEBSD_PARTITION 0xa5
826#define NETBSD_PARTITION 0xa9
827
828static void xbsd_delete_part(void);
829static void xbsd_new_part(void);
830static void xbsd_write_disklabel(void);
831static int xbsd_create_disklabel(void);
832static void xbsd_edit_disklabel(void);
833static void xbsd_write_bootstrap(void);
834static void xbsd_change_fstype(void);
835static int xbsd_get_part_index(int max);
836static int xbsd_check_new_partition(int *i);
837static void xbsd_list_types(void);
838static u_short xbsd_dkcksum(struct xbsd_disklabel *lp);
839static int xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d);
840static int xbsd_readlabel(struct partition *p, struct xbsd_disklabel *d);
841static int xbsd_writelabel(struct partition *p, struct xbsd_disklabel *d);
842
843#if defined (__alpha__)
844static void alpha_bootblock_checksum(char *boot);
845#endif
846
847#if !defined (__alpha__)
848static int xbsd_translate_fstype(int linux_type);
849static void xbsd_link_part(void);
850static struct partition *xbsd_part;
851static int xbsd_part_index;
852#endif
853
854#if defined (__alpha__)
855/* We access this through a uint64_t * when checksumming */
856static char disklabelbuffer[BSD_BBSIZE] ATTRIBUTE_ALIGNED(8);
857#else
858static char disklabelbuffer[BSD_BBSIZE];
859#endif
860
861static struct xbsd_disklabel xbsd_dlabel;
862
863#define bsd_cround(n) \
864 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
865
866/*
867 * Test whether the whole disk has BSD disk label magic.
868 *
869 * Note: often reformatting with DOS-type label leaves the BSD magic,
870 * so this does not mean that there is a BSD disk label.
871 */
872static int
873check_osf_label(void)
874{
875 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
876 return 0;
877 return 1;
878}
879
880static void xbsd_print_disklabel(int); 368static void xbsd_print_disklabel(int);
369#include "fdisk_osf.c"
881 370
882static int 371#define SGI_VOLHDR 0x00
883btrydev(const char * dev) 372/* 1 and 2 were used for drive types no longer supported by SGI */
884{ 373#define SGI_SWAP 0x03
885 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0) 374/* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
886 return -1; 375#define SGI_VOLUME 0x06
887 printf(_("\nBSD label for device: %s\n"), dev); 376#define SGI_EFS 0x07
888 xbsd_print_disklabel (0); 377#define SGI_LVOL 0x08
889 return 0; 378#define SGI_RLVOL 0x09
890} 379#define SGI_XFS 0x0a
891 380#define SGI_XFSLOG 0x0b
892static void 381#define SGI_XLV 0x0c
893bmenu(void) 382#define SGI_XVM 0x0d
894{ 383#define SGI_ENTIRE_DISK SGI_VOLUME
895 puts (_("Command action"));
896 puts (_("\td\tdelete a BSD partition"));
897 puts (_("\te\tedit drive data"));
898 puts (_("\ti\tinstall bootstrap"));
899 puts (_("\tl\tlist known filesystem types"));
900 puts (_("\tm\tprint this menu"));
901 puts (_("\tn\tadd a new BSD partition"));
902 puts (_("\tp\tprint BSD partition table"));
903 puts (_("\tq\tquit without saving changes"));
904 puts (_("\tr\treturn to main menu"));
905 puts (_("\ts\tshow complete disklabel"));
906 puts (_("\tt\tchange a partition's filesystem id"));
907 puts (_("\tu\tchange units (cylinders/sectors)"));
908 puts (_("\tw\twrite disklabel to disk"));
909#if !defined (__alpha__)
910 puts (_("\tx\tlink BSD partition to non-BSD partition"));
911#endif
912}
913
914#if !defined (__alpha__)
915static int
916hidden(int type)
917{
918 return type ^ 0x10;
919}
920
921static int
922is_bsd_partition_type(int type)
923{
924 return (type == FREEBSD_PARTITION ||
925 type == hidden(FREEBSD_PARTITION) ||
926 type == NETBSD_PARTITION ||
927 type == hidden(NETBSD_PARTITION));
928}
929#endif
930
931static void
932bselect(void)
933{
934#if !defined (__alpha__)
935 int t, ss;
936 struct partition *p;
937
938 for (t = 0; t < 4; t++) {
939 p = get_part_table(t);
940 if (p && is_bsd_partition_type(p->sys_ind)) {
941 xbsd_part = p;
942 xbsd_part_index = t;
943 ss = get_start_sect(xbsd_part);
944 if (ss == 0) {
945 fprintf(stderr, _("Partition %s has invalid starting sector 0.\n"),
946 partname(disk_device, t+1, 0));
947 return;
948 }
949 printf(_("Reading disklabel of %s at sector %d.\n"),
950 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
951 if (xbsd_readlabel(xbsd_part, &xbsd_dlabel) == 0)
952 if (xbsd_create_disklabel() == 0)
953 return;
954 break;
955 }
956 }
957
958 if (t == 4) {
959 printf(_("There is no *BSD partition on %s.\n"), disk_device);
960 return;
961 }
962
963#elif defined (__alpha__)
964
965 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
966 if (xbsd_create_disklabel() == 0)
967 exit (EXIT_SUCCESS);
968
969#endif
970
971 while (1) {
972 putchar('\n');
973 switch (tolower(read_char(_("BSD disklabel command (m for help): ")))) {
974 case 'd':
975 xbsd_delete_part();
976 break;
977 case 'e':
978 xbsd_edit_disklabel();
979 break;
980 case 'i':
981 xbsd_write_bootstrap();
982 break;
983 case 'l':
984 xbsd_list_types();
985 break;
986 case 'n':
987 xbsd_new_part();
988 break;
989 case 'p':
990 xbsd_print_disklabel(0);
991 break;
992 case 'q':
993 close(fd);
994 exit(EXIT_SUCCESS);
995 case 'r':
996 return;
997 case 's':
998 xbsd_print_disklabel(1);
999 break;
1000 case 't':
1001 xbsd_change_fstype();
1002 break;
1003 case 'u':
1004 change_units();
1005 break;
1006 case 'w':
1007 xbsd_write_disklabel();
1008 break;
1009#if !defined (__alpha__)
1010 case 'x':
1011 xbsd_link_part();
1012 break;
1013#endif
1014 default:
1015 bmenu();
1016 break;
1017 }
1018 }
1019}
1020
1021static void
1022xbsd_delete_part(void)
1023{
1024 int i;
1025
1026 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1027 xbsd_dlabel.d_partitions[i].p_size = 0;
1028 xbsd_dlabel.d_partitions[i].p_offset = 0;
1029 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1030 if (xbsd_dlabel.d_npartitions == i + 1)
1031 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1032 xbsd_dlabel.d_npartitions--;
1033}
1034
1035static void
1036xbsd_new_part(void)
1037{
1038 off_t begin, end;
1039 char mesg[256];
1040 int i;
1041
1042 if (!xbsd_check_new_partition(&i))
1043 return;
1044
1045#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1046 begin = get_start_sect(xbsd_part);
1047 end = begin + get_nr_sects(xbsd_part) - 1;
1048#else
1049 begin = 0;
1050 end = xbsd_dlabel.d_secperunit - 1;
1051#endif
1052
1053 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1054 begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end),
1055 0, mesg);
1056
1057 if (display_in_cyl_units)
1058 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1059
1060 snprintf(mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1061 str_units(SINGULAR));
1062 end = read_int(bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1063 bsd_cround (begin), mesg);
1064
1065 if (display_in_cyl_units)
1066 end = end * xbsd_dlabel.d_secpercyl - 1;
1067
1068 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1069 xbsd_dlabel.d_partitions[i].p_offset = begin;
1070 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1071}
1072
1073static void
1074xbsd_print_disklabel(int show_all)
1075{
1076 struct xbsd_disklabel *lp = &xbsd_dlabel;
1077 struct xbsd_partition *pp;
1078 int i, j;
1079
1080 if (show_all) {
1081#if defined (__alpha__)
1082 printf("# %s:\n", disk_device);
1083#else
1084 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1085#endif
1086 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1087 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1088 else
1089 printf(_("type: %d\n"), lp->d_type);
1090 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1091 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1092 printf(_("flags:"));
1093 if (lp->d_flags & BSD_D_REMOVABLE)
1094 printf(_(" removable"));
1095 if (lp->d_flags & BSD_D_ECC)
1096 printf(_(" ecc"));
1097 if (lp->d_flags & BSD_D_BADSECT)
1098 printf(_(" badsect"));
1099 printf("\n");
1100 /* On various machines the fields of *lp are short/int/long */
1101 /* In order to avoid problems, we cast them all to long. */
1102 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1103 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1104 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1105 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1106 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1107 printf(_("rpm: %d\n"), lp->d_rpm);
1108 printf(_("interleave: %d\n"), lp->d_interleave);
1109 printf(_("trackskew: %d\n"), lp->d_trackskew);
1110 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1111 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1112 (long) lp->d_headswitch);
1113 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1114 (long) lp->d_trkseek);
1115 printf(_("drivedata: "));
1116 for (i = NDDATA - 1; i >= 0; i--)
1117 if (lp->d_drivedata[i])
1118 break;
1119 if (i < 0)
1120 i = 0;
1121 for (j = 0; j <= i; j++)
1122 printf("%ld ", (long) lp->d_drivedata[j]);
1123 }
1124 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1125 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1126 pp = lp->d_partitions;
1127 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1128 if (pp->p_size) {
1129 if (display_in_cyl_units && lp->d_secpercyl) {
1130 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1131 'a' + i,
1132 (long) pp->p_offset / lp->d_secpercyl + 1,
1133 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1134 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl,
1135 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1136 (long) pp->p_size / lp->d_secpercyl,
1137 (pp->p_size % lp->d_secpercyl) ? '*' : ' '
1138 );
1139 } else {
1140 printf(" %c: %8ld %8ld %8ld ",
1141 'a' + i,
1142 (long) pp->p_offset,
1143 (long) pp->p_offset + pp->p_size - 1,
1144 (long) pp->p_size
1145 );
1146 }
1147
1148 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1149 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1150 else
1151 printf("%8x", pp->p_fstype);
1152
1153 switch (pp->p_fstype) {
1154 case BSD_FS_UNUSED:
1155 printf(" %5ld %5ld %5.5s ",
1156 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1157 break;
1158 case BSD_FS_BSDFFS:
1159 printf(" %5ld %5ld %5d ",
1160 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg);
1161 break;
1162 default:
1163 printf("%22.22s", "");
1164 break;
1165 }
1166 printf("\n");
1167 }
1168 }
1169}
1170
1171static void
1172xbsd_write_disklabel(void)
1173{
1174#if defined (__alpha__)
1175 printf(_("Writing disklabel to %s.\n"), disk_device);
1176 xbsd_writelabel(NULL, &xbsd_dlabel);
1177#else
1178 printf(_("Writing disklabel to %s.\n"),
1179 partname(disk_device, xbsd_part_index + 1, 0));
1180 xbsd_writelabel(xbsd_part, &xbsd_dlabel);
1181#endif
1182 reread_partition_table(0); /* no exit yet */
1183}
1184
1185static int
1186xbsd_create_disklabel(void)
1187{
1188 char c;
1189
1190#if defined (__alpha__)
1191 fprintf(stderr, _("%s contains no disklabel.\n"), disk_device);
1192#else
1193 fprintf(stderr, _("%s contains no disklabel.\n"),
1194 partname(disk_device, xbsd_part_index + 1, 0));
1195#endif
1196
1197 while (1) {
1198 c = read_char(_("Do you want to create a disklabel? (y/n) "));
1199 if (c == 'y' || c == 'Y') {
1200 if (xbsd_initlabel(
1201#if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1202 defined (__s390__) || defined (__s390x__)
1203 NULL, &xbsd_dlabel
1204#else
1205 xbsd_part, &xbsd_dlabel/* not used, xbsd_part_index*/
1206#endif
1207 ) == 1) {
1208 xbsd_print_disklabel (1);
1209 return 1;
1210 } else
1211 return 0;
1212 } else if (c == 'n')
1213 return 0;
1214 }
1215}
1216
1217static int
1218edit_int(int def, char *mesg)
1219{
1220 do {
1221 fputs(mesg, stdout);
1222 printf(" (%d): ", def);
1223 if (!read_line())
1224 return def;
1225 } while (!isdigit(*line_ptr));
1226 return atoi(line_ptr);
1227}
1228
1229static void
1230xbsd_edit_disklabel(void)
1231{
1232 struct xbsd_disklabel *d;
1233
1234 d = &xbsd_dlabel;
1235
1236#if defined (__alpha__) || defined (__ia64__)
1237 d->d_secsize = (u_long) edit_int((u_long) d->d_secsize ,_("bytes/sector"));
1238 d->d_nsectors = (u_long) edit_int((u_long) d->d_nsectors ,_("sectors/track"));
1239 d->d_ntracks = (u_long) edit_int((u_long) d->d_ntracks ,_("tracks/cylinder"));
1240 d->d_ncylinders = (u_long) edit_int((u_long) d->d_ncylinders ,_("cylinders"));
1241#endif
1242
1243 /* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */
1244 while (1) {
1245 d->d_secpercyl = (u_long) edit_int((u_long) d->d_nsectors * d->d_ntracks,
1246 _("sectors/cylinder"));
1247 if (d->d_secpercyl <= d->d_nsectors * d->d_ntracks)
1248 break;
1249
1250 printf(_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1251 }
1252 d->d_rpm = (u_short) edit_int((u_short) d->d_rpm ,_("rpm"));
1253 d->d_interleave = (u_short) edit_int((u_short) d->d_interleave,_("interleave"));
1254 d->d_trackskew = (u_short) edit_int((u_short) d->d_trackskew ,_("trackskew"));
1255 d->d_cylskew = (u_short) edit_int((u_short) d->d_cylskew ,_("cylinderskew"));
1256 d->d_headswitch = (u_long) edit_int((u_long) d->d_headswitch ,_("headswitch"));
1257 d->d_trkseek = (u_long) edit_int((u_long) d->d_trkseek ,_("track-to-track seek"));
1258
1259 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1260}
1261
1262static int
1263xbsd_get_bootstrap (char *path, void *ptr, int size)
1264{
1265 int fdb;
1266
1267 if ((fdb = open (path, O_RDONLY)) < 0) {
1268 perror(path);
1269 return 0;
1270 }
1271 if (read(fdb, ptr, size) < 0) {
1272 perror(path);
1273 close(fdb);
1274 return 0;
1275 }
1276 printf(" ... %s\n", path);
1277 close(fdb);
1278 return 1;
1279}
1280
1281static void
1282sync_disks(void)
1283{
1284 printf(_("\nSyncing disks.\n"));
1285 sync();
1286 sleep(4); /* What? */
1287}
1288
1289static void
1290xbsd_write_bootstrap(void)
1291{
1292 char *bootdir = BSD_LINUX_BOOTDIR;
1293 char path[MAXPATHLEN];
1294 char *dkbasename;
1295 struct xbsd_disklabel dl;
1296 char *d, *p, *e;
1297 int sector;
1298
1299 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1300 dkbasename = "sd";
1301 else
1302 dkbasename = "wd";
1303
1304 printf(_("Bootstrap: %sboot -> boot%s (%s): "),
1305 dkbasename, dkbasename, dkbasename);
1306 if (read_line()) {
1307 line_ptr[strlen(line_ptr)-1] = '\0';
1308 dkbasename = line_ptr;
1309 }
1310 snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1311 if (!xbsd_get_bootstrap(path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1312 return;
1313
1314/* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1315 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1316 memmove(&dl, d, sizeof(struct xbsd_disklabel));
1317
1318/* The disklabel will be overwritten by 0's from bootxx anyway */
1319 memset(d, 0, sizeof(struct xbsd_disklabel));
1320
1321 snprintf(path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1322 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1323 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1324 return;
1325
1326 e = d + sizeof(struct xbsd_disklabel);
1327 for (p = d; p < e; p++)
1328 if (*p) {
1329 fprintf(stderr, _("Bootstrap overlaps with disk label!\n"));
1330 exit(EXIT_FAILURE);
1331 }
1332
1333 memmove(d, &dl, sizeof(struct xbsd_disklabel));
1334
1335#if defined (__powerpc__) || defined (__hppa__)
1336 sector = 0;
1337#elif defined (__alpha__)
1338 sector = 0;
1339 alpha_bootblock_checksum(disklabelbuffer);
1340#else
1341 sector = get_start_sect(xbsd_part);
1342#endif
1343
1344 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1345 fdisk_fatal(unable_to_seek);
1346 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1347 fdisk_fatal(unable_to_write);
1348
1349#if defined (__alpha__)
1350 printf(_("Bootstrap installed on %s.\n"), disk_device);
1351#else
1352 printf(_("Bootstrap installed on %s.\n"),
1353 partname (disk_device, xbsd_part_index+1, 0));
1354#endif
1355
1356 sync_disks();
1357}
1358
1359static void
1360xbsd_change_fstype(void)
1361{
1362 int i;
1363
1364 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1365 xbsd_dlabel.d_partitions[i].p_fstype = read_hex(xbsd_fstypes);
1366}
1367
1368static int
1369xbsd_get_part_index(int max)
1370{
1371 char prompt[256];
1372 char l;
1373
1374 snprintf(prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1375 do
1376 l = tolower(read_char(prompt));
1377 while (l < 'a' || l > 'a' + max - 1);
1378 return l - 'a';
1379}
1380
1381static int
1382xbsd_check_new_partition(int *i)
1383{
1384 /* room for more? various BSD flavours have different maxima */
1385 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1386 int t;
1387
1388 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1389 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1390 break;
1391
1392 if (t == BSD_MAXPARTITIONS) {
1393 fprintf(stderr, _("The maximum number of partitions "
1394 "has been created\n"));
1395 return 0;
1396 }
1397 }
1398
1399 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1400
1401 if (*i >= xbsd_dlabel.d_npartitions)
1402 xbsd_dlabel.d_npartitions = (*i) + 1;
1403
1404 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1405 fprintf(stderr, _("This partition already exists.\n"));
1406 return 0;
1407 }
1408
1409 return 1;
1410}
1411
1412static void
1413xbsd_list_types(void)
1414{
1415 list_types(xbsd_fstypes);
1416}
1417
1418static u_short
1419xbsd_dkcksum(struct xbsd_disklabel *lp)
1420{
1421 u_short *start, *end;
1422 u_short sum = 0;
1423
1424 start = (u_short *) lp;
1425 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1426 while (start < end)
1427 sum ^= *start++;
1428 return sum;
1429}
1430
1431static int
1432xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d)
1433{
1434 struct xbsd_partition *pp;
1435
1436 get_geometry();
1437 memset(d, 0, sizeof(struct xbsd_disklabel));
1438
1439 d->d_magic = BSD_DISKMAGIC;
1440
1441 if (strncmp(disk_device, "/dev/sd", 7) == 0)
1442 d->d_type = BSD_DTYPE_SCSI;
1443 else
1444 d->d_type = BSD_DTYPE_ST506;
1445
1446#if !defined (__alpha__)
1447 d->d_flags = BSD_D_DOSPART;
1448#else
1449 d->d_flags = 0;
1450#endif
1451 d->d_secsize = SECTOR_SIZE; /* bytes/sector */
1452 d->d_nsectors = sectors; /* sectors/track */
1453 d->d_ntracks = heads; /* tracks/cylinder (heads) */
1454 d->d_ncylinders = cylinders;
1455 d->d_secpercyl = sectors * heads;/* sectors/cylinder */
1456 if (d->d_secpercyl == 0)
1457 d->d_secpercyl = 1; /* avoid segfaults */
1458 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1459
1460 d->d_rpm = 3600;
1461 d->d_interleave = 1;
1462 d->d_trackskew = 0;
1463 d->d_cylskew = 0;
1464 d->d_headswitch = 0;
1465 d->d_trkseek = 0;
1466
1467 d->d_magic2 = BSD_DISKMAGIC;
1468 d->d_bbsize = BSD_BBSIZE;
1469 d->d_sbsize = BSD_SBSIZE;
1470
1471#if !defined (__alpha__)
1472 d->d_npartitions = 4;
1473 pp = &d->d_partitions[2]; /* Partition C should be
1474 the NetBSD partition */
1475 pp->p_offset = get_start_sect(p);
1476 pp->p_size = get_nr_sects(p);
1477 pp->p_fstype = BSD_FS_UNUSED;
1478 pp = &d->d_partitions[3]; /* Partition D should be
1479 the whole disk */
1480 pp->p_offset = 0;
1481 pp->p_size = d->d_secperunit;
1482 pp->p_fstype = BSD_FS_UNUSED;
1483#elif defined (__alpha__)
1484 d->d_npartitions = 3;
1485 pp = &d->d_partitions[2]; /* Partition C should be
1486 the whole disk */
1487 pp->p_offset = 0;
1488 pp->p_size = d->d_secperunit;
1489 pp->p_fstype = BSD_FS_UNUSED;
1490#endif
1491
1492 return 1;
1493}
1494
1495/*
1496 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1497 * If it has the right magic, return 1.
1498 */
1499static int
1500xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1501{
1502 int t, sector;
1503
1504 /* p is used only to get the starting sector */
1505#if !defined (__alpha__)
1506 sector = (p ? get_start_sect(p) : 0);
1507#elif defined (__alpha__)
1508 sector = 0;
1509#endif
1510
1511 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1512 fdisk_fatal(unable_to_seek);
1513 if (BSD_BBSIZE != read(fd, disklabelbuffer, BSD_BBSIZE))
1514 fdisk_fatal(unable_to_read);
1515
1516 memmove(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1517 sizeof(struct xbsd_disklabel));
1518
1519 if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC)
1520 return 0;
1521
1522 for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1523 d->d_partitions[t].p_size = 0;
1524 d->d_partitions[t].p_offset = 0;
1525 d->d_partitions[t].p_fstype = BSD_FS_UNUSED;
1526 }
1527
1528 if (d->d_npartitions > BSD_MAXPARTITIONS)
1529 fprintf(stderr, _("Warning: too many partitions "
1530 "(%d, maximum is %d).\n"),
1531 d->d_npartitions, BSD_MAXPARTITIONS);
1532 return 1;
1533}
1534
1535static int
1536xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1537{
1538 unsigned int sector;
1539
1540#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1541 sector = get_start_sect(p) + BSD_LABELSECTOR;
1542#else
1543 sector = BSD_LABELSECTOR;
1544#endif
1545
1546 d->d_checksum = 0;
1547 d->d_checksum = xbsd_dkcksum (d);
1548
1549 /* This is necessary if we want to write the bootstrap later,
1550 otherwise we'd write the old disklabel with the bootstrap.
1551 */
1552 memmove(&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1553 d, sizeof(struct xbsd_disklabel));
1554
1555#if defined (__alpha__) && BSD_LABELSECTOR == 0
1556 alpha_bootblock_checksum (disklabelbuffer);
1557 if (lseek(fd, 0, SEEK_SET) == -1)
1558 fdisk_fatal(unable_to_seek);
1559 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1560 fdisk_fatal(unable_to_write);
1561#else
1562 if (lseek(fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1)
1563 fdisk_fatal(unable_to_seek);
1564 if (sizeof(struct xbsd_disklabel) != write(fd, d, sizeof(struct xbsd_disklabel)))
1565 fdisk_fatal(unable_to_write);
1566#endif
1567 sync_disks();
1568 return 1;
1569}
1570
1571
1572#if !defined (__alpha__)
1573static int
1574xbsd_translate_fstype(int linux_type)
1575{
1576 switch (linux_type) {
1577 case 0x01: /* DOS 12-bit FAT */
1578 case 0x04: /* DOS 16-bit <32M */
1579 case 0x06: /* DOS 16-bit >=32M */
1580 case 0xe1: /* DOS access */
1581 case 0xe3: /* DOS R/O */
1582 case 0xf2: /* DOS secondary */
1583 return BSD_FS_MSDOS;
1584 case 0x07: /* OS/2 HPFS */
1585 return BSD_FS_HPFS;
1586 default:
1587 return BSD_FS_OTHER;
1588 }
1589}
1590
1591static void
1592xbsd_link_part(void)
1593{
1594 int k, i;
1595 struct partition *p;
1596
1597 k = get_partition(1, partitions);
1598
1599 if (!xbsd_check_new_partition(&i))
1600 return;
1601
1602 p = get_part_table(k);
1603
1604 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1605 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1606 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1607}
1608#endif
1609
1610#if defined (__alpha__)
1611
1612#if !defined(__GLIBC__)
1613typedef unsigned long long uint64_t;
1614#endif
1615
1616static void
1617alpha_bootblock_checksum(char *boot)
1618{
1619 uint64_t *dp, sum;
1620 int i;
1621
1622 dp = (uint64_t *)boot;
1623 sum = 0;
1624 for (i = 0; i < 63; i++)
1625 sum += dp[i];
1626 dp[63] = sum;
1627}
1628#endif /* __alpha__ */
1629
1630#endif /* OSF_LABEL */
1631
1632#if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL) 384#if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1633static unsigned short 385static unsigned short
1634__swap16(unsigned short x) 386__swap16(unsigned short x)
@@ -1646,1515 +398,24 @@ __swap32(uint32_t x)
1646} 398}
1647#endif 399#endif
1648 400
1649#ifdef CONFIG_FEATURE_SGI_LABEL 401#include "fdisk_sgi.c"
1650/*
1651 *
1652 * fdisksgilabel.c
1653 *
1654 * Copyright (C) Andreas Neuper, Sep 1998.
1655 * This file may be modified and redistributed under
1656 * the terms of the GNU Public License.
1657 *
1658 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1659 * Internationalization
1660 */
1661
1662
1663static int sgi_other_endian;
1664static int debug;
1665static short sgi_volumes = 1;
1666
1667/*
1668 * only dealing with free blocks here
1669 */
1670
1671typedef struct {
1672 unsigned int first;
1673 unsigned int last;
1674} freeblocks;
1675static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1676
1677static void
1678setfreelist(int i, unsigned int f, unsigned int l)
1679{
1680 freelist[i].first = f;
1681 freelist[i].last = l;
1682}
1683
1684static void
1685add2freelist(unsigned int f, unsigned int l)
1686{
1687 int i;
1688 for (i = 0; i < 17 ; i++)
1689 if (freelist[i].last == 0)
1690 break;
1691 setfreelist(i, f, l);
1692}
1693
1694static void
1695clearfreelist(void)
1696{
1697 int i;
1698
1699 for (i = 0; i < 17 ; i++)
1700 setfreelist(i, 0, 0);
1701}
1702
1703static unsigned int
1704isinfreelist(unsigned int b)
1705{
1706 int i;
1707
1708 for (i = 0; i < 17 ; i++)
1709 if (freelist[i].first <= b && freelist[i].last >= b)
1710 return freelist[i].last;
1711 return 0;
1712}
1713 /* return last vacant block of this stride (never 0). */
1714 /* the '>=' is not quite correct, but simplifies the code */
1715/*
1716 * end of free blocks section
1717 */
1718
1719static const struct systypes sgi_sys_types[] = {
1720/* SGI_VOLHDR */ { "\x00" "SGI volhdr" },
1721/* 0x01 */ { "\x01" "SGI trkrepl" },
1722/* 0x02 */ { "\x02" "SGI secrepl" },
1723/* SGI_SWAP */ { "\x03" "SGI raw" },
1724/* 0x04 */ { "\x04" "SGI bsd" },
1725/* 0x05 */ { "\x05" "SGI sysv" },
1726/* ENTIRE_DISK */ { "\x06" "SGI volume" },
1727/* SGI_EFS */ { "\x07" "SGI efs" },
1728/* 0x08 */ { "\x08" "SGI lvol" },
1729/* 0x09 */ { "\x09" "SGI rlvol" },
1730/* SGI_XFS */ { "\x0a" "SGI xfs" },
1731/* SGI_XFSLOG */ { "\x0b" "SGI xfslog" },
1732/* SGI_XLV */ { "\x0c" "SGI xlv" },
1733/* SGI_XVM */ { "\x0d" "SGI xvm" },
1734/* LINUX_SWAP */ { "\x82" "Linux swap" },
1735/* LINUX_NATIVE */ { "\x83" "Linux native" },
1736/* LINUX_LVM */ { "\x8d" "Linux LVM" },
1737/* LINUX_RAID */ { "\xfd" "Linux RAID" },
1738 { NULL }
1739};
1740
1741
1742static int
1743sgi_get_nsect(void)
1744{
1745 return SGI_SSWAP16(sgilabel->devparam.nsect);
1746}
1747
1748static int
1749sgi_get_ntrks(void)
1750{
1751 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1752}
1753
1754static unsigned int
1755two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */)
1756{
1757 int i = 0;
1758 unsigned int sum = 0;
1759
1760 size /= sizeof(unsigned int);
1761 for (i = 0; i < size; i++)
1762 sum -= SGI_SSWAP32(base[i]);
1763 return sum;
1764}
1765
1766static int
1767check_sgi_label(void)
1768{
1769 if (sizeof(sgilabel) > 512) {
1770 fprintf(stderr,
1771 _("According to MIPS Computer Systems, Inc the "
1772 "Label must not contain more than 512 bytes\n"));
1773 exit(1);
1774 }
1775
1776 if (sgilabel->magic != SGI_LABEL_MAGIC
1777 && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1778 current_label_type = label_dos;
1779 return 0;
1780 }
1781
1782 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1783 /*
1784 * test for correct checksum
1785 */
1786 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1787 sizeof(*sgilabel))) {
1788 fprintf(stderr,
1789 _("Detected sgi disklabel with wrong checksum.\n"));
1790 }
1791 update_units();
1792 current_label_type = label_sgi;
1793 partitions = 16;
1794 sgi_volumes = 15;
1795 return 1;
1796}
1797
1798static unsigned int
1799sgi_get_start_sector(int i)
1800{
1801 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1802}
1803
1804static unsigned int
1805sgi_get_num_sectors(int i)
1806{
1807 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1808}
1809
1810static int
1811sgi_get_sysid(int i)
1812{
1813 return SGI_SSWAP32(sgilabel->partitions[i].id);
1814}
1815
1816static int
1817sgi_get_bootpartition(void)
1818{
1819 return SGI_SSWAP16(sgilabel->boot_part);
1820}
1821
1822static int
1823sgi_get_swappartition(void)
1824{
1825 return SGI_SSWAP16(sgilabel->swap_part);
1826}
1827
1828static void
1829sgi_list_table(int xtra)
1830{
1831 int i, w, wd;
1832 int kpi = 0; /* kernel partition ID */
1833
1834 if(xtra) {
1835 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1836 "%d cylinders, %d physical cylinders\n"
1837 "%d extra sects/cyl, interleave %d:1\n"
1838 "%s\n"
1839 "Units = %s of %d * 512 bytes\n\n"),
1840 disk_device, heads, sectors, cylinders,
1841 SGI_SSWAP16(sgiparam.pcylcount),
1842 SGI_SSWAP16(sgiparam.sparecyl),
1843 SGI_SSWAP16(sgiparam.ilfact),
1844 (char *)sgilabel,
1845 str_units(PLURAL), units_per_sector);
1846 } else {
1847 printf( _("\nDisk %s (SGI disk label): "
1848 "%d heads, %d sectors, %d cylinders\n"
1849 "Units = %s of %d * 512 bytes\n\n"),
1850 disk_device, heads, sectors, cylinders,
1851 str_units(PLURAL), units_per_sector );
1852 }
1853
1854 w = strlen(disk_device);
1855 wd = strlen(_("Device"));
1856 if (w < wd)
1857 w = wd;
1858
1859 printf(_("----- partitions -----\n"
1860 "Pt# %*s Info Start End Sectors Id System\n"),
1861 w + 2, _("Device"));
1862 for (i = 0 ; i < partitions; i++) {
1863 if( sgi_get_num_sectors(i) || debug ) {
1864 uint32_t start = sgi_get_start_sector(i);
1865 uint32_t len = sgi_get_num_sectors(i);
1866 kpi++; /* only count nonempty partitions */
1867 printf(
1868 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1869/* fdisk part number */ i+1,
1870/* device */ partname(disk_device, kpi, w+3),
1871/* flags */ (sgi_get_swappartition() == i) ? "swap" :
1872/* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1873/* start */ (long) scround(start),
1874/* end */ (long) scround(start+len)-1,
1875/* no odd flag on end */(long) len,
1876/* type id */ sgi_get_sysid(i),
1877/* type name */ partition_type(sgi_get_sysid(i)));
1878 }
1879 }
1880 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1881 "----- Directory Entries -----\n"),
1882 sgilabel->boot_file);
1883 for (i = 0 ; i < sgi_volumes; i++) {
1884 if (sgilabel->directory[i].vol_file_size) {
1885 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1886 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1887 unsigned char *name = sgilabel->directory[i].vol_file_name;
1888
1889 printf(_("%2d: %-10s sector%5u size%8u\n"),
1890 i, (char*)name, (unsigned int) start, (unsigned int) len);
1891 }
1892 }
1893}
1894
1895static void
1896sgi_set_bootpartition(int i)
1897{
1898 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1899}
1900
1901static unsigned int
1902sgi_get_lastblock(void)
1903{
1904 return heads * sectors * cylinders;
1905}
1906
1907static void
1908sgi_set_swappartition(int i)
1909{
1910 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1911}
1912
1913static int
1914sgi_check_bootfile(const char* aFile)
1915{
1916 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1917 printf(_("\nInvalid Bootfile!\n"
1918 "\tThe bootfile must be an absolute non-zero pathname,\n"
1919 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1920 return 0;
1921 } else {
1922 if (strlen(aFile) > 16) {
1923 printf(_("\n\tName of Bootfile too long: "
1924 "16 bytes maximum.\n"));
1925 return 0;
1926 } else {
1927 if (aFile[0] != '/') {
1928 printf(_("\n\tBootfile must have a "
1929 "fully qualified pathname.\n"));
1930 return 0;
1931 }
1932 }
1933 }
1934 if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
1935 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1936 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1937 /* filename is correct and did change */
1938 return 1;
1939 }
1940 return 0; /* filename did not change */
1941}
1942
1943static const char *
1944sgi_get_bootfile(void)
1945{
1946 return (char*)sgilabel->boot_file;
1947}
1948
1949static void
1950sgi_set_bootfile(const char* aFile)
1951{
1952 int i = 0;
1953
1954 if (sgi_check_bootfile(aFile)) {
1955 while (i < 16) {
1956 if ((aFile[i] != '\n') /* in principle caught again by next line */
1957 && (strlen(aFile) > i))
1958 sgilabel->boot_file[i] = aFile[i];
1959 else
1960 sgilabel->boot_file[i] = 0;
1961 i++;
1962 }
1963 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
1964 }
1965}
1966
1967static void
1968create_sgiinfo(void)
1969{
1970 /* I keep SGI's habit to write the sgilabel to the second block */
1971 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
1972 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
1973 strcpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel");
1974}
1975
1976static sgiinfo *fill_sgiinfo(void);
1977
1978static void
1979sgi_write_table(void)
1980{
1981 sgilabel->csum = 0;
1982 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
1983 (unsigned int*)sgilabel, sizeof(*sgilabel)));
1984 assert(two_s_complement_32bit_sum(
1985 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
1986
1987 if (lseek(fd, 0, SEEK_SET) < 0)
1988 fdisk_fatal(unable_to_seek);
1989 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
1990 fdisk_fatal(unable_to_write);
1991 if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
1992 /*
1993 * keep this habit of first writing the "sgilabel".
1994 * I never tested whether it works without (AN 981002).
1995 */
1996 sgiinfo *info = fill_sgiinfo();
1997 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
1998 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
1999 fdisk_fatal(unable_to_seek);
2000 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2001 fdisk_fatal(unable_to_write);
2002 free(info);
2003 }
2004}
2005
2006static int
2007compare_start(int *x, int *y)
2008{
2009 /*
2010 * sort according to start sectors
2011 * and prefers largest partition:
2012 * entry zero is entire disk entry
2013 */
2014 unsigned int i = *x;
2015 unsigned int j = *y;
2016 unsigned int a = sgi_get_start_sector(i);
2017 unsigned int b = sgi_get_start_sector(j);
2018 unsigned int c = sgi_get_num_sectors(i);
2019 unsigned int d = sgi_get_num_sectors(j);
2020
2021 if (a == b)
2022 return (d > c) ? 1 : (d == c) ? 0 : -1;
2023 return (a > b) ? 1 : -1;
2024}
2025
2026
2027static int
2028verify_sgi(int verbose)
2029{
2030 int Index[16]; /* list of valid partitions */
2031 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2032 int entire = 0, i = 0;
2033 unsigned int start = 0;
2034 long long gap = 0; /* count unused blocks */
2035 unsigned int lastblock = sgi_get_lastblock();
2036
2037 clearfreelist();
2038 for (i = 0; i < 16; i++) {
2039 if (sgi_get_num_sectors(i) != 0) {
2040 Index[sortcount++] = i;
2041 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2042 if (entire++ == 1) {
2043 if (verbose)
2044 printf(_("More than one entire disk entry present.\n"));
2045 }
2046 }
2047 }
2048 }
2049 if (sortcount == 0) {
2050 if (verbose)
2051 printf(_("No partitions defined\n"));
2052 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2053 }
2054 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2055 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2056 if ((Index[0] != 10) && verbose)
2057 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2058 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2059 printf(_("The entire disk partition should start "
2060 "at block 0,\n"
2061 "not at diskblock %d.\n"),
2062 sgi_get_start_sector(Index[0]));
2063 if (debug) /* I do not understand how some disks fulfil it */
2064 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2065 printf(_("The entire disk partition is only %d diskblock large,\n"
2066 "but the disk is %d diskblocks long.\n"),
2067 sgi_get_num_sectors(Index[0]), lastblock);
2068 lastblock = sgi_get_num_sectors(Index[0]);
2069 } else {
2070 if (verbose)
2071 printf(_("One Partition (#11) should cover the entire disk.\n"));
2072 if (debug > 2)
2073 printf("sysid=%d\tpartition=%d\n",
2074 sgi_get_sysid(Index[0]), Index[0]+1);
2075 }
2076 for (i = 1, start = 0; i < sortcount; i++) {
2077 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2078
2079 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2080 if (debug) /* I do not understand how some disks fulfil it */
2081 if (verbose)
2082 printf(_("Partition %d does not start on cylinder boundary.\n"),
2083 Index[i]+1);
2084 }
2085 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2086 if (debug) /* I do not understand how some disks fulfil it */
2087 if (verbose)
2088 printf(_("Partition %d does not end on cylinder boundary.\n"),
2089 Index[i]+1);
2090 }
2091 /* We cannot handle several "entire disk" entries. */
2092 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2093 if (start > sgi_get_start_sector(Index[i])) {
2094 if (verbose)
2095 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2096 Index[i-1]+1, Index[i]+1,
2097 start - sgi_get_start_sector(Index[i]));
2098 if (gap > 0) gap = -gap;
2099 if (gap == 0) gap = -1;
2100 }
2101 if (start < sgi_get_start_sector(Index[i])) {
2102 if (verbose)
2103 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2104 sgi_get_start_sector(Index[i]) - start,
2105 start, sgi_get_start_sector(Index[i])-1);
2106 gap += sgi_get_start_sector(Index[i]) - start;
2107 add2freelist(start, sgi_get_start_sector(Index[i]));
2108 }
2109 start = sgi_get_start_sector(Index[i])
2110 + sgi_get_num_sectors(Index[i]);
2111 if (debug > 1) {
2112 if (verbose)
2113 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2114 sgi_get_start_sector(Index[i]),
2115 sgi_get_num_sectors(Index[i]),
2116 sgi_get_sysid(Index[i]));
2117 }
2118 }
2119 if (start < lastblock) {
2120 if (verbose)
2121 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2122 lastblock - start, start, lastblock-1);
2123 gap += lastblock - start;
2124 add2freelist(start, lastblock);
2125 }
2126 /*
2127 * Done with arithmetics
2128 * Go for details now
2129 */
2130 if (verbose) {
2131 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2132 printf(_("\nThe boot partition does not exist.\n"));
2133 }
2134 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2135 printf(_("\nThe swap partition does not exist.\n"));
2136 } else {
2137 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2138 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2139 printf(_("\nThe swap partition has no swap type.\n"));
2140 }
2141 if (sgi_check_bootfile("/unix"))
2142 printf(_("\tYou have chosen an unusual boot file name.\n"));
2143 }
2144 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2145}
2146
2147static int
2148sgi_gaps(void)
2149{
2150 /*
2151 * returned value is:
2152 * = 0 : disk is properly filled to the rim
2153 * < 0 : there is an overlap
2154 * > 0 : there is still some vacant space
2155 */
2156 return verify_sgi(0);
2157}
2158
2159static void
2160sgi_change_sysid(int i, int sys)
2161{
2162 if( sgi_get_num_sectors(i) == 0 ) { /* caught already before, ... */
2163 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2164 return;
2165 }
2166 if (((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2167 && (sgi_get_start_sector(i) < 1) ) {
2168 read_chars(
2169 _("It is highly recommended that the partition at offset 0\n"
2170 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2171 "retrieve from its directory standalone tools like sash and fx.\n"
2172 "Only the \"SGI volume\" entire disk section may violate this.\n"
2173 "Type YES if you are sure about tagging this partition differently.\n"));
2174 if (strcmp(line_ptr, _("YES\n")))
2175 return;
2176 }
2177 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2178}
2179
2180/* returns partition index of first entry marked as entire disk */
2181static int
2182sgi_entire(void)
2183{
2184 int i;
2185
2186 for (i = 0; i < 16; i++)
2187 if (sgi_get_sysid(i) == SGI_VOLUME)
2188 return i;
2189 return -1;
2190}
2191
2192static void
2193sgi_set_partition(int i, unsigned int start, unsigned int length, int sys)
2194{
2195 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2196 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2197 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2198 set_changed(i);
2199 if (sgi_gaps() < 0) /* rebuild freelist */
2200 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2201}
2202
2203static void
2204sgi_set_entire(void)
2205{
2206 int n;
2207
2208 for (n = 10; n < partitions; n++) {
2209 if(!sgi_get_num_sectors(n) ) {
2210 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2211 break;
2212 }
2213 }
2214}
2215
2216static void
2217sgi_set_volhdr(void)
2218{
2219 int n;
2220
2221 for (n = 8; n < partitions; n++) {
2222 if (!sgi_get_num_sectors(n)) {
2223 /*
2224 * 5 cylinders is an arbitrary value I like
2225 * IRIX 5.3 stored files in the volume header
2226 * (like sash, symmon, fx, ide) with ca. 3200
2227 * sectors.
2228 */
2229 if (heads * sectors * 5 < sgi_get_lastblock())
2230 sgi_set_partition(n, 0, heads * sectors * 5, SGI_VOLHDR);
2231 break;
2232 }
2233 }
2234}
2235
2236static void
2237sgi_delete_partition(int i)
2238{
2239 sgi_set_partition(i, 0, 0, 0);
2240}
2241
2242static void
2243sgi_add_partition(int n, int sys)
2244{
2245 char mesg[256];
2246 unsigned int first = 0, last = 0;
2247
2248 if (n == 10) {
2249 sys = SGI_VOLUME;
2250 } else if (n == 8) {
2251 sys = 0;
2252 }
2253 if(sgi_get_num_sectors(n)) {
2254 printf(_("Partition %d is already defined. Delete "
2255 "it before re-adding it.\n"), n + 1);
2256 return;
2257 }
2258 if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) {
2259 printf(_("Attempting to generate entire disk entry automatically.\n"));
2260 sgi_set_entire();
2261 sgi_set_volhdr();
2262 }
2263 if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
2264 printf(_("The entire disk is already covered with partitions.\n"));
2265 return;
2266 }
2267 if (sgi_gaps() < 0) {
2268 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2269 return;
2270 }
2271 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2272 while (1) {
2273 if(sys == SGI_VOLUME) {
2274 last = sgi_get_lastblock();
2275 first = read_int(0, 0, last-1, 0, mesg);
2276 if (first != 0) {
2277 printf(_("It is highly recommended that eleventh partition\n"
2278 "covers the entire disk and is of type `SGI volume'\n"));
2279 }
2280 } else {
2281 first = freelist[0].first;
2282 last = freelist[0].last;
2283 first = read_int(scround(first), scround(first), scround(last)-1,
2284 0, mesg);
2285 }
2286 if (display_in_cyl_units)
2287 first *= units_per_sector;
2288 else
2289 first = first; /* align to cylinder if you know how ... */
2290 if(!last )
2291 last = isinfreelist(first);
2292 if(last == 0) {
2293 printf(_("You will get a partition overlap on the disk. "
2294 "Fix it first!\n"));
2295 } else
2296 break;
2297 }
2298 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2299 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2300 scround(first), mesg)+1;
2301 if (display_in_cyl_units)
2302 last *= units_per_sector;
2303 else
2304 last = last; /* align to cylinder if You know how ... */
2305 if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
2306 printf(_("It is highly recommended that eleventh partition\n"
2307 "covers the entire disk and is of type `SGI volume'\n"));
2308 sgi_set_partition(n, first, last-first, sys);
2309}
2310
2311#ifdef CONFIG_FEATURE_FDISK_ADVANCED
2312static void
2313create_sgilabel(void)
2314{
2315 struct hd_geometry geometry;
2316 struct {
2317 unsigned int start;
2318 unsigned int nsect;
2319 int sysid;
2320 } old[4];
2321 int i = 0;
2322 long longsectors; /* the number of sectors on the device */
2323 int res; /* the result from the ioctl */
2324 int sec_fac; /* the sector factor */
2325
2326 sec_fac = sector_size / 512; /* determine the sector factor */
2327
2328 fprintf( stderr,
2329 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2330 "until you decide to write them. After that, of course, the previous\n"
2331 "content will be unrecoverably lost.\n\n"));
2332
2333 sgi_other_endian = (BB_LITTLE_ENDIAN);
2334 res = ioctl(fd, BLKGETSIZE, &longsectors);
2335 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2336 heads = geometry.heads;
2337 sectors = geometry.sectors;
2338 if (res == 0) {
2339 /* the get device size ioctl was successful */
2340 cylinders = longsectors / (heads * sectors);
2341 cylinders /= sec_fac;
2342 } else {
2343 /* otherwise print error and use truncated version */
2344 cylinders = geometry.cylinders;
2345 fprintf(stderr,
2346 _("Warning: BLKGETSIZE ioctl failed on %s. "
2347 "Using geometry cylinder value of %d.\n"
2348 "This value may be truncated for devices"
2349 " > 33.8 GB.\n"), disk_device, cylinders);
2350 }
2351 }
2352 for (i = 0; i < 4; i++) {
2353 old[i].sysid = 0;
2354 if (valid_part_table_flag(MBRbuffer)) {
2355 if(get_part_table(i)->sys_ind) {
2356 old[i].sysid = get_part_table(i)->sys_ind;
2357 old[i].start = get_start_sect(get_part_table(i));
2358 old[i].nsect = get_nr_sects(get_part_table(i));
2359 printf(_("Trying to keep parameters of partition %d.\n"), i);
2360 if (debug)
2361 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2362 old[i].sysid, old[i].start, old[i].nsect);
2363 }
2364 }
2365 }
2366
2367 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2368 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2369 sgilabel->boot_part = SGI_SSWAP16(0);
2370 sgilabel->swap_part = SGI_SSWAP16(1);
2371
2372 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2373 memset(sgilabel->boot_file, 0, 16);
2374 strcpy((char*)sgilabel->boot_file, "/unix");
2375
2376 sgilabel->devparam.skew = (0);
2377 sgilabel->devparam.gap1 = (0);
2378 sgilabel->devparam.gap2 = (0);
2379 sgilabel->devparam.sparecyl = (0);
2380 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2381 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2382 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2383 /* tracks/cylinder (heads) */
2384 sgilabel->devparam.cmd_tag_queue_depth = (0);
2385 sgilabel->devparam.unused0 = (0);
2386 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2387 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2388 /* sectors/track */
2389 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2390 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2391 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2392 IGNORE_ERRORS|RESEEK);
2393 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2394 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2395 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2396 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2397 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2398 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2399 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2400 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2401 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2402 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2403 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2404 current_label_type = label_sgi;
2405 partitions = 16;
2406 sgi_volumes = 15;
2407 sgi_set_entire();
2408 sgi_set_volhdr();
2409 for (i = 0; i < 4; i++) {
2410 if(old[i].sysid) {
2411 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2412 }
2413 }
2414}
2415
2416static void
2417sgi_set_xcyl(void)
2418{
2419 /* do nothing in the beginning */
2420}
2421#endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2422
2423/* _____________________________________________________________
2424 */
2425
2426static sgiinfo *
2427fill_sgiinfo(void)
2428{
2429 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2430
2431 info->magic = SGI_SSWAP32(SGI_INFO_MAGIC);
2432 info->b1 = SGI_SSWAP32(-1);
2433 info->b2 = SGI_SSWAP16(-1);
2434 info->b3 = SGI_SSWAP16(1);
2435 /* You may want to replace this string !!!!!!! */
2436 strcpy( (char*)info->scsi_string, "IBM OEM 0662S12 3 30" );
2437 strcpy( (char*)info->serial, "0000" );
2438 info->check1816 = SGI_SSWAP16(18*256 +16 );
2439 strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" );
2440 return info;
2441}
2442#endif /* SGI_LABEL */
2443
2444
2445#ifdef CONFIG_FEATURE_SUN_LABEL
2446/*
2447 * fdisksunlabel.c
2448 *
2449 * I think this is mostly, or entirely, due to
2450 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2451 *
2452 * Merged with fdisk for other architectures, aeb, June 1998.
2453 *
2454 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2455 * Internationalization
2456 */
2457
2458
2459static int sun_other_endian;
2460static int scsi_disk;
2461static int floppy;
2462
2463#ifndef IDE0_MAJOR
2464#define IDE0_MAJOR 3
2465#endif
2466#ifndef IDE1_MAJOR
2467#define IDE1_MAJOR 22
2468#endif
2469
2470static void
2471guess_device_type(void)
2472{
2473 struct stat bootstat;
2474
2475 if (fstat(fd, &bootstat) < 0) {
2476 scsi_disk = 0;
2477 floppy = 0;
2478 } else if (S_ISBLK(bootstat.st_mode)
2479 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2480 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2481 scsi_disk = 0;
2482 floppy = 0;
2483 } else if (S_ISBLK(bootstat.st_mode)
2484 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2485 scsi_disk = 0;
2486 floppy = 1;
2487 } else {
2488 scsi_disk = 1;
2489 floppy = 0;
2490 }
2491}
2492
2493static const struct systypes sun_sys_types[] = {
2494 { "\x00" "Empty" }, /* 0 */
2495 { "\x01" "Boot" }, /* 1 */
2496 { "\x02" "SunOS root" }, /* 2 */
2497 { "\x03" "SunOS swap" }, /* SUNOS_SWAP */
2498 { "\x04" "SunOS usr" }, /* 4 */
2499 { "\x05" "Whole disk" }, /* WHOLE_DISK */
2500 { "\x06" "SunOS stand" }, /* 6 */
2501 { "\x07" "SunOS var" }, /* 7 */
2502 { "\x08" "SunOS home" }, /* 8 */
2503 { "\x82" "Linux swap" }, /* LINUX_SWAP */
2504 { "\x83" "Linux native" }, /* LINUX_NATIVE */
2505 { "\x8e" "Linux LVM" }, /* 0x8e */
2506/* New (2.2.x) raid partition with autodetect using persistent superblock */
2507 { "\xfd" "Linux raid autodetect" }, /* 0xfd */
2508 { NULL }
2509};
2510
2511
2512static void
2513set_sun_partition(int i, uint start, uint stop, int sysid)
2514{
2515 sunlabel->infos[i].id = sysid;
2516 sunlabel->partitions[i].start_cylinder =
2517 SUN_SSWAP32(start / (heads * sectors));
2518 sunlabel->partitions[i].num_sectors =
2519 SUN_SSWAP32(stop - start);
2520 set_changed(i);
2521}
2522
2523static int
2524check_sun_label(void)
2525{
2526 unsigned short *ush;
2527 int csum;
2528
2529 if (sunlabel->magic != SUN_LABEL_MAGIC
2530 && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2531 current_label_type = label_dos;
2532 sun_other_endian = 0;
2533 return 0;
2534 }
2535 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2536 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2537 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2538 if (csum) {
2539 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2540 "Probably you'll have to set all the values,\n"
2541 "e.g. heads, sectors, cylinders and partitions\n"
2542 "or force a fresh label (s command in main menu)\n"));
2543 } else {
2544 heads = SUN_SSWAP16(sunlabel->ntrks);
2545 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2546 sectors = SUN_SSWAP16(sunlabel->nsect);
2547 }
2548 update_units();
2549 current_label_type = label_sun;
2550 partitions = 8;
2551 return 1;
2552}
2553
2554static const struct sun_predefined_drives {
2555 const char *vendor;
2556 const char *model;
2557 unsigned short sparecyl;
2558 unsigned short ncyl;
2559 unsigned short nacyl;
2560 unsigned short pcylcount;
2561 unsigned short ntrks;
2562 unsigned short nsect;
2563 unsigned short rspeed;
2564} sun_drives[] = {
2565 { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2566 { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2567 { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2568 { "IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2569 { "IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2570 { "IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2571 { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2572 { "","SUN0104",1,974,2,1019,6,35,3662},
2573 { "","SUN0207",4,1254,2,1272,9,36,3600},
2574 { "","SUN0327",3,1545,2,1549,9,46,3600},
2575 { "","SUN0340",0,1538,2,1544,6,72,4200},
2576 { "","SUN0424",2,1151,2,2500,9,80,4400},
2577 { "","SUN0535",0,1866,2,2500,7,80,5400},
2578 { "","SUN0669",5,1614,2,1632,15,54,3600},
2579 { "","SUN1.0G",5,1703,2,1931,15,80,3597},
2580 { "","SUN1.05",0,2036,2,2038,14,72,5400},
2581 { "","SUN1.3G",6,1965,2,3500,17,80,5400},
2582 { "","SUN2.1G",0,2733,2,3500,19,80,5400},
2583 { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2584};
2585
2586static const struct sun_predefined_drives *
2587sun_autoconfigure_scsi(void)
2588{
2589 const struct sun_predefined_drives *p = NULL;
2590
2591#ifdef SCSI_IOCTL_GET_IDLUN
2592 unsigned int id[2];
2593 char buffer[2048];
2594 char buffer2[2048];
2595 FILE *pfd;
2596 char *vendor;
2597 char *model;
2598 char *q;
2599 int i;
2600
2601 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2602 sprintf(buffer,
2603 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2604 /* This is very wrong (works only if you have one HBA),
2605 but I haven't found a way how to get hostno
2606 from the current kernel */
2607 0,
2608 (id[0]>>16) & 0xff,
2609 id[0] & 0xff,
2610 (id[0]>>8) & 0xff
2611 );
2612 pfd = fopen("/proc/scsi/scsi","r");
2613 if (pfd) {
2614 while (fgets(buffer2, 2048, pfd)) {
2615 if (!strcmp(buffer, buffer2)) {
2616 if (fgets(buffer2,2048,pfd)) {
2617 q = strstr(buffer2,"Vendor: ");
2618 if (q) {
2619 q += 8;
2620 vendor = q;
2621 q = strstr(q," ");
2622 *q++ = 0; /* truncate vendor name */
2623 q = strstr(q,"Model: ");
2624 if (q) {
2625 *q = 0;
2626 q += 7;
2627 model = q;
2628 q = strstr(q," Rev: ");
2629 if (q) {
2630 *q = 0;
2631 for (i = 0; i < SIZE(sun_drives); i++) {
2632 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2633 continue;
2634 if (!strstr(model, sun_drives[i].model))
2635 continue;
2636 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2637 p = sun_drives + i;
2638 break;
2639 }
2640 }
2641 }
2642 }
2643 }
2644 break;
2645 }
2646 }
2647 fclose(pfd);
2648 }
2649 }
2650#endif
2651 return p;
2652}
2653
2654static void
2655create_sunlabel(void)
2656{
2657 struct hd_geometry geometry;
2658 unsigned int ndiv;
2659 int i;
2660 unsigned char c;
2661 const struct sun_predefined_drives *p = NULL;
2662
2663 fprintf(stderr,
2664 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2665 "until you decide to write them. After that, of course, the previous\n"
2666 "content won't be recoverable.\n\n"));
2667 sun_other_endian = BB_LITTLE_ENDIAN;
2668 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2669 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2670 if (!floppy) {
2671 puts(_("Drive type\n"
2672 " ? auto configure\n"
2673 " 0 custom (with hardware detected defaults)"));
2674 for (i = 0; i < SIZE(sun_drives); i++) {
2675 printf(" %c %s%s%s\n",
2676 i + 'a', sun_drives[i].vendor,
2677 (*sun_drives[i].vendor) ? " " : "",
2678 sun_drives[i].model);
2679 }
2680 while (1) {
2681 c = read_char(_("Select type (? for auto, 0 for custom): "));
2682 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2683 p = sun_drives + c - 'a';
2684 break;
2685 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2686 p = sun_drives + c - 'A';
2687 break;
2688 } else if (c == '0') {
2689 break;
2690 } else if (c == '?' && scsi_disk) {
2691 p = sun_autoconfigure_scsi();
2692 if (!p)
2693 printf(_("Autoconfigure failed.\n"));
2694 else
2695 break;
2696 }
2697 }
2698 }
2699 if (!p || floppy) {
2700 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2701 heads = geometry.heads;
2702 sectors = geometry.sectors;
2703 cylinders = geometry.cylinders;
2704 } else {
2705 heads = 0;
2706 sectors = 0;
2707 cylinders = 0;
2708 }
2709 if (floppy) {
2710 sunlabel->nacyl = 0;
2711 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2712 sunlabel->rspeed = SUN_SSWAP16(300);
2713 sunlabel->ilfact = SUN_SSWAP16(1);
2714 sunlabel->sparecyl = 0;
2715 } else {
2716 heads = read_int(1,heads,1024,0,_("Heads"));
2717 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2718 if (cylinders)
2719 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2720 else
2721 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2722 sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders")));
2723 sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders")));
2724 sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)")));
2725 sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor")));
2726 sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder")));
2727 }
2728 } else {
2729 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2730 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2731 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2732 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2733 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2734 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2735 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2736 sunlabel->ilfact = SUN_SSWAP16(1);
2737 cylinders = p->ncyl;
2738 heads = p->ntrks;
2739 sectors = p->nsect;
2740 puts(_("You may change all the disk params from the x menu"));
2741 }
2742
2743 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
2744 "%s%s%s cyl %d alt %d hd %d sec %d",
2745 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2746 p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2747 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2748
2749 sunlabel->ntrks = SUN_SSWAP16(heads);
2750 sunlabel->nsect = SUN_SSWAP16(sectors);
2751 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2752 if (floppy)
2753 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2754 else {
2755 if (cylinders * heads * sectors >= 150 * 2048) {
2756 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2757 } else
2758 ndiv = cylinders * 2 / 3;
2759 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2760 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2761 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2762 }
2763 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2764 {
2765 unsigned short *ush = (unsigned short *)sunlabel;
2766 unsigned short csum = 0;
2767 while (ush < (unsigned short *)(&sunlabel->csum))
2768 csum ^= *ush++;
2769 sunlabel->csum = csum;
2770 }
2771
2772 set_all_unchanged();
2773 set_changed(0);
2774 get_boot(create_empty_sun);
2775}
2776
2777static void
2778toggle_sunflags(int i, unsigned char mask)
2779{
2780 if (sunlabel->infos[i].flags & mask)
2781 sunlabel->infos[i].flags &= ~mask;
2782 else
2783 sunlabel->infos[i].flags |= mask;
2784 set_changed(i);
2785}
2786
2787static void
2788fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
2789{
2790 int i, continuous = 1;
2791
2792 *start = 0;
2793 *stop = cylinders * heads * sectors;
2794 for (i = 0; i < partitions; i++) {
2795 if (sunlabel->partitions[i].num_sectors
2796 && sunlabel->infos[i].id
2797 && sunlabel->infos[i].id != WHOLE_DISK) {
2798 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2799 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2800 if (continuous) {
2801 if (starts[i] == *start)
2802 *start += lens[i];
2803 else if (starts[i] + lens[i] >= *stop)
2804 *stop = starts[i];
2805 else
2806 continuous = 0;
2807 /* There will be probably more gaps
2808 than one, so lets check afterwards */
2809 }
2810 } else {
2811 starts[i] = 0;
2812 lens[i] = 0;
2813 }
2814 }
2815}
2816
2817static uint *verify_sun_starts;
2818
2819static int
2820verify_sun_cmp(int *a, int *b)
2821{
2822 if (*a == -1) return 1;
2823 if (*b == -1) return -1;
2824 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2825 return -1;
2826}
2827
2828static void
2829verify_sun(void)
2830{
2831 uint starts[8], lens[8], start, stop;
2832 int i,j,k,starto,endo;
2833 int array[8];
2834
2835 verify_sun_starts = starts;
2836 fetch_sun(starts,lens,&start,&stop);
2837 for (k = 0; k < 7; k++) {
2838 for (i = 0; i < 8; i++) {
2839 if (k && (lens[i] % (heads * sectors))) {
2840 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2841 }
2842 if (lens[i]) {
2843 for (j = 0; j < i; j++)
2844 if (lens[j]) {
2845 if (starts[j] == starts[i]+lens[i]) {
2846 starts[j] = starts[i]; lens[j] += lens[i];
2847 lens[i] = 0;
2848 } else if (starts[i] == starts[j]+lens[j]){
2849 lens[j] += lens[i];
2850 lens[i] = 0;
2851 } else if (!k) {
2852 if (starts[i] < starts[j]+lens[j]
2853 && starts[j] < starts[i]+lens[i]) {
2854 starto = starts[i];
2855 if (starts[j] > starto)
2856 starto = starts[j];
2857 endo = starts[i]+lens[i];
2858 if (starts[j]+lens[j] < endo)
2859 endo = starts[j]+lens[j];
2860 printf(_("Partition %d overlaps with others in "
2861 "sectors %d-%d\n"), i+1, starto, endo);
2862 }
2863 }
2864 }
2865 }
2866 }
2867 }
2868 for (i = 0; i < 8; i++) {
2869 if (lens[i])
2870 array[i] = i;
2871 else
2872 array[i] = -1;
2873 }
2874 qsort(array,SIZE(array),sizeof(array[0]),
2875 (int (*)(const void *,const void *)) verify_sun_cmp);
2876 if (array[0] == -1) {
2877 printf(_("No partitions defined\n"));
2878 return;
2879 }
2880 stop = cylinders * heads * sectors;
2881 if (starts[array[0]])
2882 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2883 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2884 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2885 }
2886 start = starts[array[i]] + lens[array[i]];
2887 if (start < stop)
2888 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2889}
2890 402
2891static void 403static const struct systypes sun_sys_types[];
2892add_sun_partition(int n, int sys) 404static void sun_delete_partition(int i);
2893{ 405static void sun_change_sysid(int i, int sys);
2894 uint start, stop, stop2; 406static void sun_list_table(int xtra);
2895 uint starts[8], lens[8]; 407static void sun_set_xcyl(void);
2896 int whole_disk = 0; 408static void add_sun_partition(int n, int sys);
2897 409static void sun_set_alt_cyl(void);
2898 char mesg[256]; 410static void sun_set_ncyl(int cyl);
2899 int i, first, last; 411static void sun_set_xcyl(void);
2900 412static void sun_set_ilfact(void);
2901 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) { 413static void sun_set_rspeed(void);
2902 printf(_("Partition %d is already defined. Delete " 414static void sun_set_pcylcount(void);
2903 "it before re-adding it.\n"), n + 1); 415static void toggle_sunflags(int i, unsigned char mask);
2904 return; 416static void verify_sun(void);
2905 } 417static void sun_write_table(void);
2906 418#include "fdisk_sun.c"
2907 fetch_sun(starts,lens,&start,&stop);
2908 if (stop <= start) {
2909 if (n == 2)
2910 whole_disk = 1;
2911 else {
2912 printf(_("Other partitions already cover the whole disk.\nDelete "
2913 "some/shrink them before retry.\n"));
2914 return;
2915 }
2916 }
2917 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2918 while (1) {
2919 if (whole_disk)
2920 first = read_int(0, 0, 0, 0, mesg);
2921 else
2922 first = read_int(scround(start), scround(stop)+1,
2923 scround(stop), 0, mesg);
2924 if (display_in_cyl_units)
2925 first *= units_per_sector;
2926 else
2927 /* Starting sector has to be properly aligned */
2928 first = (first + heads * sectors - 1) / (heads * sectors);
2929 if (n == 2 && first != 0)
2930 printf("\
2931It is highly recommended that the third partition covers the whole disk\n\
2932and is of type `Whole disk'\n");
2933 /* ewt asks to add: "don't start a partition at cyl 0"
2934 However, edmundo@rano.demon.co.uk writes:
2935 "In addition to having a Sun partition table, to be able to
2936 boot from the disc, the first partition, /dev/sdX1, must
2937 start at cylinder 0. This means that /dev/sdX1 contains
2938 the partition table and the boot block, as these are the
2939 first two sectors of the disc. Therefore you must be
2940 careful what you use /dev/sdX1 for. In particular, you must
2941 not use a partition starting at cylinder 0 for Linux swap,
2942 as that would overwrite the partition table and the boot
2943 block. You may, however, use such a partition for a UFS
2944 or EXT2 file system, as these file systems leave the first
2945 1024 bytes undisturbed. */
2946 /* On the other hand, one should not use partitions
2947 starting at block 0 in an md, or the label will
2948 be trashed. */
2949 for (i = 0; i < partitions; i++)
2950 if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
2951 break;
2952 if (i < partitions && !whole_disk) {
2953 if (n == 2 && !first) {
2954 whole_disk = 1;
2955 break;
2956 }
2957 printf(_("Sector %d is already allocated\n"), first);
2958 } else
2959 break;
2960 }
2961 stop = cylinders * heads * sectors;
2962 stop2 = stop;
2963 for (i = 0; i < partitions; i++) {
2964 if (starts[i] > first && starts[i] < stop)
2965 stop = starts[i];
2966 }
2967 snprintf(mesg, sizeof(mesg),
2968 _("Last %s or +size or +sizeM or +sizeK"),
2969 str_units(SINGULAR));
2970 if (whole_disk)
2971 last = read_int(scround(stop2), scround(stop2), scround(stop2),
2972 0, mesg);
2973 else if (n == 2 && !first)
2974 last = read_int(scround(first), scround(stop2), scround(stop2),
2975 scround(first), mesg);
2976 else
2977 last = read_int(scround(first), scround(stop), scround(stop),
2978 scround(first), mesg);
2979 if (display_in_cyl_units)
2980 last *= units_per_sector;
2981 if (n == 2 && !first) {
2982 if (last >= stop2) {
2983 whole_disk = 1;
2984 last = stop2;
2985 } else if (last > stop) {
2986 printf(_("You haven't covered the whole disk with "
2987 "the 3rd partition, but your value\n"
2988 "%d %s covers some other partition. "
2989 "Your entry has been changed\n"
2990 "to %d %s\n"),
2991 scround(last), str_units(SINGULAR),
2992 scround(stop), str_units(SINGULAR));
2993 last = stop;
2994 }
2995 } else if (!whole_disk && last > stop)
2996 last = stop;
2997
2998 if (whole_disk)
2999 sys = WHOLE_DISK;
3000 set_sun_partition(n, first, last, sys);
3001}
3002
3003static void
3004sun_delete_partition(int i)
3005{
3006 unsigned int nsec;
3007
3008 if (i == 2
3009 && sunlabel->infos[i].id == WHOLE_DISK
3010 && !sunlabel->partitions[i].start_cylinder
3011 && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
3012 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3013 "consider leaving this\n"
3014 "partition as Whole disk (5), starting at 0, with %u "
3015 "sectors\n"), nsec);
3016 sunlabel->infos[i].id = 0;
3017 sunlabel->partitions[i].num_sectors = 0;
3018}
3019
3020static void
3021sun_change_sysid(int i, int sys)
3022{
3023 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3024 read_chars(
3025 _("It is highly recommended that the partition at offset 0\n"
3026 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3027 "there may destroy your partition table and bootblock.\n"
3028 "Type YES if you're very sure you would like that partition\n"
3029 "tagged with 82 (Linux swap): "));
3030 if (strcmp (line_ptr, _("YES\n")))
3031 return;
3032 }
3033 switch (sys) {
3034 case SUNOS_SWAP:
3035 case LINUX_SWAP:
3036 /* swaps are not mountable by default */
3037 sunlabel->infos[i].flags |= 0x01;
3038 break;
3039 default:
3040 /* assume other types are mountable;
3041 user can change it anyway */
3042 sunlabel->infos[i].flags &= ~0x01;
3043 break;
3044 }
3045 sunlabel->infos[i].id = sys;
3046}
3047
3048static void
3049sun_list_table(int xtra)
3050{
3051 int i, w;
3052
3053 w = strlen(disk_device);
3054 if (xtra)
3055 printf(
3056 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3057 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3058 "%d extra sects/cyl, interleave %d:1\n"
3059 "%s\n"
3060 "Units = %s of %d * 512 bytes\n\n"),
3061 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3062 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3063 SUN_SSWAP16(sunlabel->pcylcount),
3064 SUN_SSWAP16(sunlabel->sparecyl),
3065 SUN_SSWAP16(sunlabel->ilfact),
3066 (char *)sunlabel,
3067 str_units(PLURAL), units_per_sector);
3068 else
3069 printf(
3070 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3071 "Units = %s of %d * 512 bytes\n\n"),
3072 disk_device, heads, sectors, cylinders,
3073 str_units(PLURAL), units_per_sector);
3074
3075 printf(_("%*s Flag Start End Blocks Id System\n"),
3076 w + 1, _("Device"));
3077 for (i = 0 ; i < partitions; i++) {
3078 if (sunlabel->partitions[i].num_sectors) {
3079 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3080 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3081 printf("%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3082 partname(disk_device, i+1, w), /* device */
3083 (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', /* flags */
3084 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3085 (long) scround(start), /* start */
3086 (long) scround(start+len), /* end */
3087 (long) len / 2, len & 1 ? '+' : ' ', /* odd flag on end */
3088 sunlabel->infos[i].id, /* type id */
3089 partition_type(sunlabel->infos[i].id)); /* type name */
3090 }
3091 }
3092}
3093
3094#ifdef CONFIG_FEATURE_FDISK_ADVANCED
3095
3096static void
3097sun_set_alt_cyl(void)
3098{
3099 sunlabel->nacyl =
3100 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3101 _("Number of alternate cylinders")));
3102}
3103
3104static void
3105sun_set_ncyl(int cyl)
3106{
3107 sunlabel->ncyl = SUN_SSWAP16(cyl);
3108}
3109
3110static void
3111sun_set_xcyl(void)
3112{
3113 sunlabel->sparecyl =
3114 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3115 _("Extra sectors per cylinder")));
3116}
3117
3118static void
3119sun_set_ilfact(void)
3120{
3121 sunlabel->ilfact =
3122 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3123 _("Interleave factor")));
3124}
3125
3126static void
3127sun_set_rspeed(void)
3128{
3129 sunlabel->rspeed =
3130 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3131 _("Rotation speed (rpm)")));
3132}
3133
3134static void
3135sun_set_pcylcount(void)
3136{
3137 sunlabel->pcylcount =
3138 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3139 _("Number of physical cylinders")));
3140}
3141#endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3142
3143static void
3144sun_write_table(void)
3145{
3146 unsigned short *ush = (unsigned short *)sunlabel;
3147 unsigned short csum = 0;
3148
3149 while (ush < (unsigned short *)(&sunlabel->csum))
3150 csum ^= *ush++;
3151 sunlabel->csum = csum;
3152 if (lseek(fd, 0, SEEK_SET) < 0)
3153 fdisk_fatal(unable_to_seek);
3154 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3155 fdisk_fatal(unable_to_write);
3156}
3157#endif /* SUN_LABEL */
3158 419
3159/* DOS partition types */ 420/* DOS partition types */
3160 421
@@ -3362,27 +623,25 @@ static void fdisk_fatal(enum failure why)
3362 623
3363 switch (why) { 624 switch (why) {
3364 case unable_to_open: 625 case unable_to_open:
3365 message = "Unable to open %s\n"; 626 message = "\nUnable to open %s";
3366 break; 627 break;
3367 case unable_to_read: 628 case unable_to_read:
3368 message = "Unable to read %s\n"; 629 message = "\nUnable to read %s";
3369 break; 630 break;
3370 case unable_to_seek: 631 case unable_to_seek:
3371 message = "Unable to seek on %s\n"; 632 message = "\nUnable to seek on %s";
3372 break; 633 break;
3373 case unable_to_write: 634 case unable_to_write:
3374 message = "Unable to write %s\n"; 635 message = "\nUnable to write %s";
3375 break; 636 break;
3376 case ioctl_error: 637 case ioctl_error:
3377 message = "BLKGETSIZE ioctl failed on %s\n"; 638 message = "\nBLKGETSIZE ioctl failed on %s";
3378 break; 639 break;
3379 default: 640 default:
3380 message = "Fatal error\n"; 641 message = "\nFatal error";
3381 } 642 }
3382 643
3383 fputc('\n', stderr); 644 bb_error_msg_and_die(message, disk_device);
3384 fprintf(stderr, message, disk_device);
3385 exit(1);
3386} 645}
3387 646
3388static void 647static void
@@ -3444,8 +703,7 @@ is_dos_partition(int t)
3444static void 703static void
3445menu(void) 704menu(void)
3446{ 705{
3447#ifdef CONFIG_FEATURE_SUN_LABEL 706 if (LABEL_IS_SUN) {
3448 if (label_sun == current_label_type) {
3449 puts(_("Command action")); 707 puts(_("Command action"));
3450 puts(_("\ta\ttoggle a read only flag")); /* sun */ 708 puts(_("\ta\ttoggle a read only flag")); /* sun */
3451 puts(_("\tb\tedit bsd disklabel")); 709 puts(_("\tb\tedit bsd disklabel"));
@@ -3466,9 +724,7 @@ menu(void)
3466 puts(_("\tx\textra functionality (experts only)")); 724 puts(_("\tx\textra functionality (experts only)"));
3467#endif 725#endif
3468 } else 726 } else
3469#endif 727 if (LABEL_IS_SGI) {
3470#ifdef CONFIG_FEATURE_SGI_LABEL
3471 if (label_sgi == current_label_type) {
3472 puts(_("Command action")); 728 puts(_("Command action"));
3473 puts(_("\ta\tselect bootable partition")); /* sgi flavour */ 729 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3474 puts(_("\tb\tedit bootfile entry")); /* sgi */ 730 puts(_("\tb\tedit bootfile entry")); /* sgi */
@@ -3486,16 +742,13 @@ menu(void)
3486 puts(_("\tv\tverify the partition table")); 742 puts(_("\tv\tverify the partition table"));
3487 puts(_("\tw\twrite table to disk and exit")); 743 puts(_("\tw\twrite table to disk and exit"));
3488 } else 744 } else
3489#endif 745 if (LABEL_IS_AIX) {
3490#ifdef CONFIG_FEATURE_AIX_LABEL
3491 if (label_aix == current_label_type) {
3492 puts(_("Command action")); 746 puts(_("Command action"));
3493 puts(_("\tm\tprint this menu")); 747 puts(_("\tm\tprint this menu"));
3494 puts(_("\to\tcreate a new empty DOS partition table")); 748 puts(_("\to\tcreate a new empty DOS partition table"));
3495 puts(_("\tq\tquit without saving changes")); 749 puts(_("\tq\tquit without saving changes"));
3496 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */ 750 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3497 } else 751 } else
3498#endif
3499 { 752 {
3500 puts(_("Command action")); 753 puts(_("Command action"));
3501 puts(_("\ta\ttoggle a bootable flag")); 754 puts(_("\ta\ttoggle a bootable flag"));
@@ -3525,28 +778,25 @@ menu(void)
3525static void 778static void
3526xmenu(void) 779xmenu(void)
3527{ 780{
3528#ifdef CONFIG_FEATURE_SUN_LABEL 781 if (LABEL_IS_SUN) {
3529 if (label_sun == current_label_type) { 782 puts(_("Command action"));
3530 puts(_("Command action")); 783 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3531 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/ 784 puts(_("\tc\tchange number of cylinders"));
3532 puts(_("\tc\tchange number of cylinders")); 785 puts(_("\td\tprint the raw data in the partition table"));
3533 puts(_("\td\tprint the raw data in the partition table")); 786 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3534 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/ 787 puts(_("\th\tchange number of heads"));
3535 puts(_("\th\tchange number of heads")); 788 puts(_("\ti\tchange interleave factor")); /*sun*/
3536 puts(_("\ti\tchange interleave factor")); /*sun*/ 789 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3537 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/ 790 puts(_("\tm\tprint this menu"));
3538 puts(_("\tm\tprint this menu")); 791 puts(_("\tp\tprint the partition table"));
3539 puts(_("\tp\tprint the partition table")); 792 puts(_("\tq\tquit without saving changes"));
3540 puts(_("\tq\tquit without saving changes")); 793 puts(_("\tr\treturn to main menu"));
3541 puts(_("\tr\treturn to main menu")); 794 puts(_("\ts\tchange number of sectors/track"));
3542 puts(_("\ts\tchange number of sectors/track")); 795 puts(_("\tv\tverify the partition table"));
3543 puts(_("\tv\tverify the partition table")); 796 puts(_("\tw\twrite table to disk and exit"));
3544 puts(_("\tw\twrite table to disk and exit")); 797 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3545 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3546 } else 798 } else
3547#endif 799 if (LABEL_IS_SGI) {
3548#ifdef CONFIG_FEATURE_SGI_LABEL
3549 if (label_sgi == current_label_type) {
3550 puts(_("Command action")); 800 puts(_("Command action"));
3551 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */ 801 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3552 puts(_("\tc\tchange number of cylinders")); 802 puts(_("\tc\tchange number of cylinders"));
@@ -3562,9 +812,7 @@ xmenu(void)
3562 puts(_("\tv\tverify the partition table")); 812 puts(_("\tv\tverify the partition table"));
3563 puts(_("\tw\twrite table to disk and exit")); 813 puts(_("\tw\twrite table to disk and exit"));
3564 } else 814 } else
3565#endif 815 if (LABEL_IS_AIX) {
3566#ifdef CONFIG_FEATURE_AIX_LABEL
3567 if (label_aix == current_label_type) {
3568 puts(_("Command action")); 816 puts(_("Command action"));
3569 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */ 817 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3570 puts(_("\tc\tchange number of cylinders")); 818 puts(_("\tc\tchange number of cylinders"));
@@ -3579,9 +827,7 @@ xmenu(void)
3579 puts(_("\ts\tchange number of sectors/track")); 827 puts(_("\ts\tchange number of sectors/track"));
3580 puts(_("\tv\tverify the partition table")); 828 puts(_("\tv\tverify the partition table"));
3581 puts(_("\tw\twrite table to disk and exit")); 829 puts(_("\tw\twrite table to disk and exit"));
3582 } else 830 } else {
3583#endif
3584 {
3585 puts(_("Command action")); 831 puts(_("Command action"));
3586 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */ 832 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3587 puts(_("\tc\tchange number of cylinders")); 833 puts(_("\tc\tchange number of cylinders"));
@@ -3608,12 +854,8 @@ static const struct systypes *
3608get_sys_types(void) 854get_sys_types(void)
3609{ 855{
3610 return ( 856 return (
3611#ifdef CONFIG_FEATURE_SUN_LABEL 857 LABEL_IS_SUN ? sun_sys_types :
3612 label_sun == current_label_type ? sun_sys_types : 858 LABEL_IS_SGI ? sgi_sys_types :
3613#endif
3614#ifdef CONFIG_FEATURE_SGI_LABEL
3615 label_sgi == current_label_type ? sgi_sys_types :
3616#endif
3617 i386_sys_types); 859 i386_sys_types);
3618} 860}
3619#else 861#else
@@ -3637,14 +879,9 @@ static const char *partition_type(unsigned char type)
3637static int 879static int
3638get_sysid(int i) 880get_sysid(int i)
3639{ 881{
3640 return ( 882 return LABEL_IS_SUN ? sunlabel->infos[i].id :
3641#ifdef CONFIG_FEATURE_SUN_LABEL 883 (LABEL_IS_SGI ? sgi_get_sysid(i) :
3642 label_sun == current_label_type ? sunlabel->infos[i].id : 884 ptes[i].part_table->sys_ind);
3643#endif
3644#ifdef CONFIG_FEATURE_SGI_LABEL
3645 label_sgi == current_label_type ? sgi_get_sysid(i) :
3646#endif
3647 ptes[i].part_table->sys_ind);
3648} 885}
3649 886
3650void list_types(const struct systypes *sys) 887void list_types(const struct systypes *sys)
@@ -3722,9 +959,9 @@ test_c(const char **m, const char *mesg)
3722{ 959{
3723 int val = 0; 960 int val = 0;
3724 if (!*m) 961 if (!*m)
3725 fprintf(stderr, _("You must set")); 962 printf(_("You must set"));
3726 else { 963 else {
3727 fprintf(stderr, " %s", *m); 964 printf(" %s", *m);
3728 val = 1; 965 val = 1;
3729 } 966 }
3730 *m = mesg; 967 *m = mesg;
@@ -3746,9 +983,9 @@ warn_geometry(void)
3746 if (!m) 983 if (!m)
3747 return 0; 984 return 0;
3748 985
3749 fprintf(stderr, "%s%s.\n" 986 printf("%s%s.\n"
3750#ifdef CONFIG_FEATURE_FDISK_WRITABLE 987#ifdef CONFIG_FEATURE_FDISK_WRITABLE
3751 "You can do this from the extra functions menu.\n" 988 "You can do this from the extra functions menu.\n"
3752#endif 989#endif
3753 , prev ? _(" and ") : " ", m); 990 , prev ? _(" and ") : " ", m);
3754 991
@@ -3769,8 +1006,8 @@ static void update_units(void)
3769static void 1006static void
3770warn_cylinders(void) 1007warn_cylinders(void)
3771{ 1008{
3772 if (label_dos == current_label_type && cylinders > 1024 && !nowarn) 1009 if (LABEL_IS_DOS && cylinders > 1024 && !nowarn)
3773 fprintf(stderr, _("\n" 1010 printf(_("\n"
3774"The number of cylinders for this disk is set to %d.\n" 1011"The number of cylinders for this disk is set to %d.\n"
3775"There is nothing wrong with that, but this is larger than 1024,\n" 1012"There is nothing wrong with that, but this is larger than 1024,\n"
3776"and could in certain setups cause problems with:\n" 1013"and could in certain setups cause problems with:\n"
@@ -3794,8 +1031,7 @@ read_extended(int ext)
3794 1031
3795 p = pex->part_table; 1032 p = pex->part_table;
3796 if (!get_start_sect(p)) { 1033 if (!get_start_sect(p)) {
3797 fprintf(stderr, 1034 printf(_("Bad offset in primary extended partition\n"));
3798 _("Bad offset in primary extended partition\n"));
3799 return; 1035 return;
3800 } 1036 }
3801 1037
@@ -3808,8 +1044,7 @@ read_extended(int ext)
3808 Do not try to `improve' this test. */ 1044 Do not try to `improve' this test. */
3809 struct pte *pre = &ptes[partitions-1]; 1045 struct pte *pre = &ptes[partitions-1];
3810#ifdef CONFIG_FEATURE_FDISK_WRITABLE 1046#ifdef CONFIG_FEATURE_FDISK_WRITABLE
3811 fprintf(stderr, 1047 printf(_("Warning: deleting partitions after %d\n"),
3812 _("Warning: deleting partitions after %d\n"),
3813 partitions); 1048 partitions);
3814 pre->changed = 1; 1049 pre->changed = 1;
3815#endif 1050#endif
@@ -3826,16 +1061,14 @@ read_extended(int ext)
3826 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) { 1061 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3827 if (IS_EXTENDED(p->sys_ind)) { 1062 if (IS_EXTENDED(p->sys_ind)) {
3828 if (pe->ext_pointer) 1063 if (pe->ext_pointer)
3829 fprintf(stderr, 1064 printf(_("Warning: extra link "
3830 _("Warning: extra link " 1065 "pointer in partition table"
3831 "pointer in partition table" 1066 " %d\n"), partitions + 1);
3832 " %d\n"), partitions + 1);
3833 else 1067 else
3834 pe->ext_pointer = p; 1068 pe->ext_pointer = p;
3835 } else if (p->sys_ind) { 1069 } else if (p->sys_ind) {
3836 if (pe->part_table) 1070 if (pe->part_table)
3837 fprintf(stderr, 1071 printf(_("Warning: ignoring extra "
3838 _("Warning: ignoring extra "
3839 "data in partition table" 1072 "data in partition table"
3840 " %d\n"), partitions + 1); 1073 " %d\n"), partitions + 1);
3841 else 1074 else
@@ -3883,7 +1116,7 @@ create_doslabel(void)
3883{ 1116{
3884 int i; 1117 int i;
3885 1118
3886 fprintf(stderr, 1119 printf(
3887 _("Building a new DOS disklabel. Changes will remain in memory only,\n" 1120 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3888 "until you decide to write them. After that, of course, the previous\n" 1121 "until you decide to write them. After that, of course, the previous\n"
3889 "content won't be recoverable.\n\n")); 1122 "content won't be recoverable.\n\n"));
@@ -4107,8 +1340,7 @@ get_boot(enum action what)
4107#else 1340#else
4108 switch (what) { 1341 switch (what) {
4109 case fdisk: 1342 case fdisk:
4110 fprintf(stderr, 1343 printf(_("Device contains neither a valid DOS "
4111 _("Device contains neither a valid DOS "
4112 "partition table, nor Sun, SGI or OSF " 1344 "partition table, nor Sun, SGI or OSF "
4113 "disklabel\n")); 1345 "disklabel\n"));
4114#ifdef __sparc__ 1346#ifdef __sparc__
@@ -4127,8 +1359,7 @@ get_boot(enum action what)
4127#endif 1359#endif
4128 break; 1360 break;
4129 default: 1361 default:
4130 fprintf(stderr, _("Internal error\n")); 1362 bb_error_msg_and_die(_("Internal error"));
4131 exit(1);
4132 } 1363 }
4133#endif /* CONFIG_FEATURE_FDISK_WRITABLE */ 1364#endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4134 } 1365 }
@@ -4143,7 +1374,7 @@ get_boot(enum action what)
4143 1374
4144 if (IS_EXTENDED(pe->part_table->sys_ind)) { 1375 if (IS_EXTENDED(pe->part_table->sys_ind)) {
4145 if (partitions != 4) 1376 if (partitions != 4)
4146 fprintf(stderr, _("Ignoring extra extended " 1377 printf(_("Ignoring extra extended "
4147 "partition %d\n"), i + 1); 1378 "partition %d\n"), i + 1);
4148 else 1379 else
4149 read_extended(i); 1380 read_extended(i);
@@ -4154,8 +1385,7 @@ get_boot(enum action what)
4154 struct pte *pe = &ptes[i]; 1385 struct pte *pe = &ptes[i];
4155 1386
4156 if (!valid_part_table_flag(pe->sectorbuffer)) { 1387 if (!valid_part_table_flag(pe->sectorbuffer)) {
4157 fprintf(stderr, 1388 printf(_("Warning: invalid flag 0x%04x of partition "
4158 _("Warning: invalid flag 0x%04x of partition "
4159 "table %d will be corrected by w(rite)\n"), 1389 "table %d will be corrected by w(rite)\n"),
4160 part_table_flag(pe->sectorbuffer), i + 1); 1390 part_table_flag(pe->sectorbuffer), i + 1);
4161#ifdef CONFIG_FEATURE_FDISK_WRITABLE 1391#ifdef CONFIG_FEATURE_FDISK_WRITABLE
@@ -4180,36 +1410,28 @@ read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4180{ 1410{
4181 uint i; 1411 uint i;
4182 int default_ok = 1; 1412 int default_ok = 1;
4183 static char *ms = NULL; 1413 const char *fmt = "%s (%u-%u, default %u): ";
4184 static int mslen = 0;
4185
4186 if (!ms || strlen(mesg)+100 > mslen) {
4187 mslen = strlen(mesg)+200;
4188 ms = xrealloc(ms,mslen);
4189 }
4190 1414
4191 if (dflt < low || dflt > high) 1415 if (dflt < low || dflt > high) {
1416 fmt = "%s (%u-%u): ";
4192 default_ok = 0; 1417 default_ok = 0;
4193 1418 }
4194 if (default_ok)
4195 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4196 mesg, low, high, dflt);
4197 else
4198 snprintf(ms, mslen, "%s (%u-%u): ", mesg, low, high);
4199 1419
4200 while (1) { 1420 while (1) {
4201 int use_default = default_ok; 1421 int use_default = default_ok;
4202 1422
4203 /* ask question and read answer */ 1423 /* ask question and read answer */
4204 while (read_chars(ms) != '\n' && !isdigit(*line_ptr) 1424 do {
4205 && *line_ptr != '-' && *line_ptr != '+') 1425 printf(fmt, mesg, low, high, dflt);
4206 continue; 1426 read_maybe_empty("");
1427 } while (*line_ptr != '\n' && !isdigit(*line_ptr)
1428 && *line_ptr != '-' && *line_ptr != '+');
4207 1429
4208 if (*line_ptr == '+' || *line_ptr == '-') { 1430 if (*line_ptr == '+' || *line_ptr == '-') {
4209 int minus = (*line_ptr == '-'); 1431 int minus = (*line_ptr == '-');
4210 int absolute = 0; 1432 int absolute = 0;
4211 1433
4212 i = atoi(line_ptr+1); 1434 i = atoi(line_ptr + 1);
4213 1435
4214 while (isdigit(*++line_ptr)) 1436 while (isdigit(*++line_ptr))
4215 use_default = 0; 1437 use_default = 0;
@@ -4262,7 +1484,7 @@ read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4262 if (i >= low && i <= high) 1484 if (i >= low && i <= high)
4263 break; 1485 break;
4264 else 1486 else
4265 printf(_("Value out of range.\n")); 1487 printf(_("Value is out of range\n"));
4266 } 1488 }
4267 return i; 1489 return i;
4268} 1490}
@@ -4277,32 +1499,11 @@ get_partition(int warn, int max)
4277 pe = &ptes[i]; 1499 pe = &ptes[i];
4278 1500
4279 if (warn) { 1501 if (warn) {
4280 if ( 1502 if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind)
4281 ( 1503 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
4282 label_sun != current_label_type && 1504 || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
4283 label_sgi != current_label_type && 1505 ) {
4284 !pe->part_table->sys_ind 1506 printf(_("Warning: partition %d has empty type\n"), i+1);
4285 )
4286#ifdef CONFIG_FEATURE_SUN_LABEL
4287 || (
4288 label_sun == current_label_type &&
4289 (
4290 !sunlabel->partitions[i].num_sectors
4291 || !sunlabel->infos[i].id
4292 )
4293 )
4294#endif
4295#ifdef CONFIG_FEATURE_SGI_LABEL
4296 || (
4297 label_sgi == current_label_type &&
4298 !sgi_get_num_sectors(i)
4299 )
4300#endif
4301 ){
4302 fprintf(stderr,
4303 _("Warning: partition %d has empty type\n"),
4304 i+1
4305 );
4306 } 1507 }
4307 } 1508 }
4308 return i; 1509 return i;
@@ -4363,7 +1564,8 @@ get_nonexisting_partition(int warn, int max)
4363} 1564}
4364 1565
4365 1566
4366void change_units(void) 1567static void
1568change_units(void)
4367{ 1569{
4368 display_in_cyl_units = !display_in_cyl_units; 1570 display_in_cyl_units = !display_in_cyl_units;
4369 update_units(); 1571 update_units();
@@ -4378,9 +1580,7 @@ toggle_active(int i)
4378 struct partition *p = pe->part_table; 1580 struct partition *p = pe->part_table;
4379 1581
4380 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind) 1582 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
4381 fprintf(stderr, 1583 printf(_("WARNING: Partition %d is an extended partition\n"), i + 1);
4382 _("WARNING: Partition %d is an extended partition\n"),
4383 i + 1);
4384 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG); 1584 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4385 pe->changed = 1; 1585 pe->changed = 1;
4386} 1586}
@@ -4414,18 +1614,14 @@ delete_partition(int i)
4414 return; /* C/H/S not set */ 1614 return; /* C/H/S not set */
4415 pe->changed = 1; 1615 pe->changed = 1;
4416 1616
4417#ifdef CONFIG_FEATURE_SUN_LABEL 1617 if (LABEL_IS_SUN) {
4418 if (label_sun == current_label_type) {
4419 sun_delete_partition(i); 1618 sun_delete_partition(i);
4420 return; 1619 return;
4421 } 1620 }
4422#endif 1621 if (LABEL_IS_SGI) {
4423#ifdef CONFIG_FEATURE_SGI_LABEL
4424 if (label_sgi == current_label_type) {
4425 sgi_delete_partition(i); 1622 sgi_delete_partition(i);
4426 return; 1623 return;
4427 } 1624 }
4428#endif
4429 1625
4430 if (i < 4) { 1626 if (i < 4) {
4431 if (IS_EXTENDED(p->sys_ind) && i == ext_index) { 1627 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
@@ -4482,18 +1678,14 @@ change_sysid(void)
4482 int i, sys, origsys; 1678 int i, sys, origsys;
4483 struct partition *p; 1679 struct partition *p;
4484 1680
4485#ifdef CONFIG_FEATURE_SGI_LABEL
4486 /* If sgi_label then don't use get_existing_partition, 1681 /* If sgi_label then don't use get_existing_partition,
4487 let the user select a partition, since get_existing_partition() 1682 let the user select a partition, since get_existing_partition()
4488 only works for Linux like partition tables. */ 1683 only works for Linux like partition tables. */
4489 if (label_sgi != current_label_type) { 1684 if (!LABEL_IS_SGI) {
4490 i = get_existing_partition(0, partitions); 1685 i = get_existing_partition(0, partitions);
4491 } else { 1686 } else {
4492 i = get_partition(0, partitions); 1687 i = get_partition(0, partitions);
4493 } 1688 }
4494#else
4495 i = get_existing_partition(0, partitions);
4496#endif
4497 if (i == -1) 1689 if (i == -1)
4498 return; 1690 return;
4499 p = ptes[i].part_table; 1691 p = ptes[i].part_table;
@@ -4501,16 +1693,14 @@ change_sysid(void)
4501 1693
4502 /* if changing types T to 0 is allowed, then 1694 /* if changing types T to 0 is allowed, then
4503 the reverse change must be allowed, too */ 1695 the reverse change must be allowed, too */
4504 if (!sys && label_sgi != current_label_type && 1696 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
4505 label_sun != current_label_type && !get_nr_sects(p))
4506 {
4507 printf(_("Partition %d does not exist yet!\n"), i + 1); 1697 printf(_("Partition %d does not exist yet!\n"), i + 1);
4508 } else while (1) { 1698 return;
1699 }
1700 while (1) {
4509 sys = read_hex (get_sys_types()); 1701 sys = read_hex (get_sys_types());
4510 1702
4511 if (!sys && label_sgi != current_label_type && 1703 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
4512 label_sun != current_label_type)
4513 {
4514 printf(_("Type 0 means free space to many systems\n" 1704 printf(_("Type 0 means free space to many systems\n"
4515 "(but not to Linux). Having partitions of\n" 1705 "(but not to Linux). Having partitions of\n"
4516 "type 0 is probably unwise. You can delete\n" 1706 "type 0 is probably unwise. You can delete\n"
@@ -4518,7 +1708,7 @@ change_sysid(void)
4518 /* break; */ 1708 /* break; */
4519 } 1709 }
4520 1710
4521 if (label_sun != current_label_type && label_sgi != current_label_type) { 1711 if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
4522 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) { 1712 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
4523 printf(_("You cannot change a partition into" 1713 printf(_("You cannot change a partition into"
4524 " an extended one or vice versa\n" 1714 " an extended one or vice versa\n"
@@ -4528,17 +1718,14 @@ change_sysid(void)
4528 } 1718 }
4529 1719
4530 if (sys < 256) { 1720 if (sys < 256) {
4531#ifdef CONFIG_FEATURE_SUN_LABEL 1721 if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
4532 if (label_sun == current_label_type && i == 2 && sys != WHOLE_DISK)
4533 printf(_("Consider leaving partition 3 " 1722 printf(_("Consider leaving partition 3 "
4534 "as Whole disk (5),\n" 1723 "as Whole disk (5),\n"
4535 "as SunOS/Solaris expects it and " 1724 "as SunOS/Solaris expects it and "
4536 "even Linux likes it.\n\n")); 1725 "even Linux likes it.\n\n"));
4537#endif 1726 if (LABEL_IS_SGI &&
4538#ifdef CONFIG_FEATURE_SGI_LABEL
4539 if (label_sgi == current_label_type &&
4540 ( 1727 (
4541 (i == 10 && sys != ENTIRE_DISK) || 1728 (i == 10 && sys != SGI_ENTIRE_DISK) ||
4542 (i == 8 && sys != 0) 1729 (i == 8 && sys != 0)
4543 ) 1730 )
4544 ){ 1731 ){
@@ -4547,19 +1734,13 @@ change_sysid(void)
4547 "partition 11 as entire volume (6)" 1734 "partition 11 as entire volume (6)"
4548 "as IRIX expects it.\n\n")); 1735 "as IRIX expects it.\n\n"));
4549 } 1736 }
4550#endif
4551 if (sys == origsys) 1737 if (sys == origsys)
4552 break; 1738 break;
4553#ifdef CONFIG_FEATURE_SUN_LABEL 1739 if (LABEL_IS_SUN) {
4554 if (label_sun == current_label_type) {
4555 sun_change_sysid(i, sys); 1740 sun_change_sysid(i, sys);
4556 } else 1741 } else if (LABEL_IS_SGI) {
4557#endif
4558#ifdef CONFIG_FEATURE_SGI_LABEL
4559 if (label_sgi == current_label_type) {
4560 sgi_change_sysid(i, sys); 1742 sgi_change_sysid(i, sys);
4561 } else 1743 } else
4562#endif
4563 p->sys_ind = sys; 1744 p->sys_ind = sys;
4564 1745
4565 printf(_("Changed system type of partition %d " 1746 printf(_("Changed system type of partition %d "
@@ -4811,28 +1992,21 @@ list_table(int xtra)
4811 const struct partition *p; 1992 const struct partition *p;
4812 int i, w; 1993 int i, w;
4813 1994
4814#ifdef CONFIG_FEATURE_SUN_LABEL 1995 if (LABEL_IS_SUN) {
4815 if (label_sun == current_label_type) {
4816 sun_list_table(xtra); 1996 sun_list_table(xtra);
4817 return; 1997 return;
4818 } 1998 }
4819#endif 1999 if (LABEL_IS_SUN) {
4820
4821#ifdef CONFIG_FEATURE_SGI_LABEL
4822 if (label_sgi == current_label_type) {
4823 sgi_list_table(xtra); 2000 sgi_list_table(xtra);
4824 return; 2001 return;
4825 } 2002 }
4826#endif
4827 2003
4828 list_disk_geometry(); 2004 list_disk_geometry();
4829 2005
4830#ifdef CONFIG_FEATURE_OSF_LABEL 2006 if (LABEL_IS_OSF) {
4831 if (label_osf == current_label_type) {
4832 xbsd_print_disklabel(xtra); 2007 xbsd_print_disklabel(xtra);
4833 return; 2008 return;
4834 } 2009 }
4835#endif
4836 2010
4837 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3, 2011 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4838 but if the device name ends in a digit, say /dev/foo1, 2012 but if the device name ends in a digit, say /dev/foo1,
@@ -4843,43 +2017,49 @@ list_table(int xtra)
4843 if (w < 5) 2017 if (w < 5)
4844 w = 5; 2018 w = 5;
4845 2019
4846 printf(_("%*s Boot Start End Blocks Id System\n"), 2020 // 1 12345678901 12345678901 12345678901 12
2021 printf(_("%*s Boot Start End Blocks Id System\n"),
4847 w+1, _("Device")); 2022 w+1, _("Device"));
4848 2023
4849 for (i = 0; i < partitions; i++) { 2024 for (i = 0; i < partitions; i++) {
4850 const struct pte *pe = &ptes[i]; 2025 const struct pte *pe = &ptes[i];
2026 off_t psects;
2027 off_t pblocks;
2028 unsigned int podd;
4851 2029
4852 p = pe->part_table; 2030 p = pe->part_table;
4853 if (p && !is_cleared_partition(p)) { 2031 if (!p || is_cleared_partition(p))
4854 off_t psects = get_nr_sects(p); 2032 continue;
4855 off_t pblocks = psects;
4856 unsigned int podd = 0;
4857 2033
4858 if (sector_size < 1024) { 2034 psects = get_nr_sects(p);
4859 pblocks /= (1024 / sector_size); 2035 pblocks = psects;
4860 podd = psects % (1024 / sector_size); 2036 podd = 0;
4861 } 2037
4862 if (sector_size > 1024) 2038 if (sector_size < 1024) {
4863 pblocks *= (sector_size / 1024); 2039 pblocks /= (1024 / sector_size);
4864 printf( 2040 podd = psects % (1024 / sector_size);
4865 "%s %c %11llu %11llu %11llu%c %2x %s\n", 2041 }
2042 if (sector_size > 1024)
2043 pblocks *= (sector_size / 1024);
2044
2045 printf("%s %c %11llu %11llu %11llu%c %2x %s\n",
4866 partname(disk_device, i+1, w+2), 2046 partname(disk_device, i+1, w+2),
4867/* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG 2047 !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
4868 ? '*' : '?', 2048 ? '*' : '?',
4869/* start */ (unsigned long long) cround(get_partition_start(pe)), 2049 (unsigned long long) cround(get_partition_start(pe)), /* start */
4870/* end */ (unsigned long long) cround(get_partition_start(pe) + psects 2050 (unsigned long long) cround(get_partition_start(pe) + psects /* end */
4871 - (psects ? 1 : 0)), 2051 - (psects ? 1 : 0)),
4872/* odd flag on end */ (unsigned long long) pblocks, podd ? '+' : ' ', 2052 (unsigned long long) pblocks, podd ? '+' : ' ', /* odd flag on end */
4873/* type id */ p->sys_ind, 2053 p->sys_ind, /* type id */
4874/* type name */ partition_type(p->sys_ind)); 2054 partition_type(p->sys_ind)); /* type name */
4875 check_consistency(p, i); 2055
4876 } 2056 check_consistency(p, i);
4877 } 2057 }
4878 2058
4879 /* Is partition table in disk order? It need not be, but... */ 2059 /* Is partition table in disk order? It need not be, but... */
4880 /* partition table entries are not checked for correct order if this 2060 /* partition table entries are not checked for correct order if this
4881 is a sgi, sun or aix labeled disk... */ 2061 is a sgi, sun or aix labeled disk... */
4882 if (label_dos == current_label_type && wrong_p_order(NULL)) { 2062 if (LABEL_IS_DOS && wrong_p_order(NULL)) {
4883 /* FIXME */ 2063 /* FIXME */
4884 printf(_("\nPartition table entries are not in disk order\n")); 2064 printf(_("\nPartition table entries are not in disk order\n"));
4885 } 2065 }
@@ -4895,7 +2075,7 @@ x_list_table(int extend)
4895 2075
4896 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"), 2076 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4897 disk_device, heads, sectors, cylinders); 2077 disk_device, heads, sectors, cylinders);
4898 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n")); 2078 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4899 for (i = 0 ; i < partitions; i++) { 2079 for (i = 0 ; i < partitions; i++) {
4900 pe = &ptes[i]; 2080 pe = &ptes[i];
4901 p = (extend ? pe->ext_pointer : pe->part_table); 2081 p = (extend ? pe->ext_pointer : pe->part_table);
@@ -4943,20 +2123,18 @@ check(int n, uint h, uint s, uint c, off_t start)
4943 real_c = cylinder(s, c); 2123 real_c = cylinder(s, c);
4944 total = (real_c * sectors + real_s) * heads + h; 2124 total = (real_c * sectors + real_s) * heads + h;
4945 if (!total) 2125 if (!total)
4946 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n); 2126 printf(_("Warning: partition %d contains sector 0\n"), n);
4947 if (h >= heads) 2127 if (h >= heads)
4948 fprintf(stderr, 2128 printf(_("Partition %d: head %d greater than maximum %d\n"),
4949 _("Partition %d: head %d greater than maximum %d\n"),
4950 n, h + 1, heads); 2129 n, h + 1, heads);
4951 if (real_s >= sectors) 2130 if (real_s >= sectors)
4952 fprintf(stderr, _("Partition %d: sector %d greater than " 2131 printf(_("Partition %d: sector %d greater than "
4953 "maximum %d\n"), n, s, sectors); 2132 "maximum %d\n"), n, s, sectors);
4954 if (real_c >= cylinders) 2133 if (real_c >= cylinders)
4955 fprintf(stderr, _("Partitions %d: cylinder %llu greater than " 2134 printf(_("Partitions %d: cylinder %llu greater than "
4956 "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders); 2135 "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
4957 if (cylinders <= 1024 && start != total) 2136 if (cylinders <= 1024 && start != total)
4958 fprintf(stderr, 2137 printf(_("Partition %d: previous sectors %llu disagrees with "
4959 _("Partition %d: previous sectors %llu disagrees with "
4960 "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total); 2138 "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
4961} 2139}
4962 2140
@@ -4971,18 +2149,14 @@ verify(void)
4971 if (warn_geometry()) 2149 if (warn_geometry())
4972 return; 2150 return;
4973 2151
4974#ifdef CONFIG_FEATURE_SUN_LABEL 2152 if (LABEL_IS_SUN) {
4975 if (label_sun == current_label_type) {
4976 verify_sun(); 2153 verify_sun();
4977 return; 2154 return;
4978 } 2155 }
4979#endif 2156 if (LABEL_IS_SGI) {
4980#ifdef CONFIG_FEATURE_SGI_LABEL
4981 if (label_sgi == current_label_type) {
4982 verify_sgi(1); 2157 verify_sgi(1);
4983 return; 2158 return;
4984 } 2159 }
4985#endif
4986 2160
4987 fill_bounds(first, last); 2161 fill_bounds(first, last);
4988 for (i = 0; i < partitions; i++) { 2162 for (i = 0; i < partitions; i++) {
@@ -5191,20 +2365,15 @@ new_partition(void)
5191 if (warn_geometry()) 2365 if (warn_geometry())
5192 return; 2366 return;
5193 2367
5194#ifdef CONFIG_FEATURE_SUN_LABEL 2368 if (LABEL_IS_SUN) {
5195 if (label_sun == current_label_type) {
5196 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE); 2369 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5197 return; 2370 return;
5198 } 2371 }
5199#endif 2372 if (LABEL_IS_SGI) {
5200#ifdef CONFIG_FEATURE_SGI_LABEL
5201 if (label_sgi == current_label_type) {
5202 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE); 2373 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5203 return; 2374 return;
5204 } 2375 }
5205#endif 2376 if (LABEL_IS_AIX) {
5206#ifdef CONFIG_FEATURE_AIX_LABEL
5207 if (label_aix == current_label_type) {
5208 printf(_("\tSorry - this fdisk cannot handle AIX disk labels." 2377 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5209 "\n\tIf you want to add DOS-type partitions, create" 2378 "\n\tIf you want to add DOS-type partitions, create"
5210 "\n\ta new empty DOS partition table first. (Use o.)" 2379 "\n\ta new empty DOS partition table first. (Use o.)"
@@ -5212,7 +2381,6 @@ new_partition(void)
5212 "This will destroy the present disk contents.\n")); 2381 "This will destroy the present disk contents.\n"));
5213 return; 2382 return;
5214 } 2383 }
5215#endif
5216 2384
5217 for (i = 0; i < 4; i++) 2385 for (i = 0; i < 4; i++)
5218 free_primary += !ptes[i].part_table->sys_ind; 2386 free_primary += !ptes[i].part_table->sys_ind;
@@ -5235,7 +2403,8 @@ new_partition(void)
5235 "Command action", (extended_offset ? 2403 "Command action", (extended_offset ?
5236 "l logical (5 or over)" : "e extended")); 2404 "l logical (5 or over)" : "e extended"));
5237 while (1) { 2405 while (1) {
5238 if ((c = read_char(line)) == 'p' || c == 'P') { 2406 c = read_nonempty(line);
2407 if (c == 'p' || c == 'P') {
5239 i = get_nonexisting_partition(0, 4); 2408 i = get_nonexisting_partition(0, 4);
5240 if (i >= 0) 2409 if (i >= 0)
5241 add_partition(i, LINUX_NATIVE); 2410 add_partition(i, LINUX_NATIVE);
@@ -5263,7 +2432,7 @@ write_table(void)
5263{ 2432{
5264 int i; 2433 int i;
5265 2434
5266 if (label_dos == current_label_type) { 2435 if (LABEL_IS_DOS) {
5267 for (i = 0; i < 3; i++) 2436 for (i = 0; i < 3; i++)
5268 if (ptes[i].changed) 2437 if (ptes[i].changed)
5269 ptes[3].changed = 1; 2438 ptes[3].changed = 1;
@@ -5276,14 +2445,11 @@ write_table(void)
5276 } 2445 }
5277 } 2446 }
5278 } 2447 }
5279#ifdef CONFIG_FEATURE_SGI_LABEL 2448 else if (LABEL_IS_SGI) {
5280 else if (label_sgi == current_label_type) {
5281 /* no test on change? the printf below might be mistaken */ 2449 /* no test on change? the printf below might be mistaken */
5282 sgi_write_table(); 2450 sgi_write_table();
5283 } 2451 }
5284#endif 2452 else if (LABEL_IS_SUN) {
5285#ifdef CONFIG_FEATURE_SUN_LABEL
5286 else if (label_sun == current_label_type) {
5287 int needw = 0; 2453 int needw = 0;
5288 2454
5289 for (i = 0; i < 8; i++) 2455 for (i = 0; i < 8; i++)
@@ -5292,7 +2458,6 @@ write_table(void)
5292 if (needw) 2458 if (needw)
5293 sun_write_table(); 2459 sun_write_table();
5294 } 2460 }
5295#endif
5296 2461
5297 printf(_("The partition table has been altered!\n\n")); 2462 printf(_("The partition table has been altered!\n\n"));
5298 reread_partition_table(1); 2463 reread_partition_table(1);
@@ -5373,13 +2538,12 @@ print_raw(void)
5373 int i; 2538 int i;
5374 2539
5375 printf(_("Device: %s\n"), disk_device); 2540 printf(_("Device: %s\n"), disk_device);
5376#if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL) 2541 if (LABEL_IS_SGI || LABEL_IS_SUN)
5377 if (label_sun == current_label_type || label_sgi == current_label_type)
5378 print_buffer(MBRbuffer); 2542 print_buffer(MBRbuffer);
5379 else 2543 else {
5380#endif
5381 for (i = 3; i < partitions; i++) 2544 for (i = 3; i < partitions; i++)
5382 print_buffer(ptes[i].sectorbuffer); 2545 print_buffer(ptes[i].sectorbuffer);
2546 }
5383} 2547}
5384 2548
5385static void 2549static void
@@ -5414,48 +2578,38 @@ xselect(void)
5414 2578
5415 while (1) { 2579 while (1) {
5416 putchar('\n'); 2580 putchar('\n');
5417 c = tolower(read_char(_("Expert command (m for help): "))); 2581 c = tolower(read_nonempty(_("Expert command (m for help): ")));
5418 switch (c) { 2582 switch (c) {
5419 case 'a': 2583 case 'a':
5420#ifdef CONFIG_FEATURE_SUN_LABEL 2584 if (LABEL_IS_SUN)
5421 if (label_sun == current_label_type)
5422 sun_set_alt_cyl(); 2585 sun_set_alt_cyl();
5423#endif
5424 break; 2586 break;
5425 case 'b': 2587 case 'b':
5426 if (label_dos == current_label_type) 2588 if (LABEL_IS_DOS)
5427 move_begin(get_partition(0, partitions)); 2589 move_begin(get_partition(0, partitions));
5428 break; 2590 break;
5429 case 'c': 2591 case 'c':
5430 user_cylinders = cylinders = 2592 user_cylinders = cylinders =
5431 read_int(1, cylinders, 1048576, 0, 2593 read_int(1, cylinders, 1048576, 0,
5432 _("Number of cylinders")); 2594 _("Number of cylinders"));
5433#ifdef CONFIG_FEATURE_SUN_LABEL 2595 if (LABEL_IS_SUN)
5434 if (label_sun == current_label_type)
5435 sun_set_ncyl(cylinders); 2596 sun_set_ncyl(cylinders);
5436#endif 2597 if (LABEL_IS_DOS)
5437 if (label_dos == current_label_type)
5438 warn_cylinders(); 2598 warn_cylinders();
5439 break; 2599 break;
5440 case 'd': 2600 case 'd':
5441 print_raw(); 2601 print_raw();
5442 break; 2602 break;
5443 case 'e': 2603 case 'e':
5444#ifdef CONFIG_FEATURE_SGI_LABEL 2604 if (LABEL_IS_SGI)
5445 if (label_sgi == current_label_type)
5446 sgi_set_xcyl(); 2605 sgi_set_xcyl();
5447 else 2606 else if (LABEL_IS_SUN)
5448#endif
5449#ifdef CONFIG_FEATURE_SUN_LABEL
5450 if (label_sun == current_label_type)
5451 sun_set_xcyl(); 2607 sun_set_xcyl();
5452 else 2608 else if (LABEL_IS_DOS)
5453#endif
5454 if (label_dos == current_label_type)
5455 x_list_table(1); 2609 x_list_table(1);
5456 break; 2610 break;
5457 case 'f': 2611 case 'f':
5458 if (label_dos == current_label_type) 2612 if (LABEL_IS_DOS)
5459 fix_partition_table_order(); 2613 fix_partition_table_order();
5460 break; 2614 break;
5461 case 'g': 2615 case 'g':
@@ -5469,23 +2623,17 @@ xselect(void)
5469 update_units(); 2623 update_units();
5470 break; 2624 break;
5471 case 'i': 2625 case 'i':
5472#ifdef CONFIG_FEATURE_SUN_LABEL 2626 if (LABEL_IS_SUN)
5473 if (label_sun == current_label_type)
5474 sun_set_ilfact(); 2627 sun_set_ilfact();
5475#endif
5476 break; 2628 break;
5477 case 'o': 2629 case 'o':
5478#ifdef CONFIG_FEATURE_SUN_LABEL 2630 if (LABEL_IS_SUN)
5479 if (label_sun == current_label_type)
5480 sun_set_rspeed(); 2631 sun_set_rspeed();
5481#endif
5482 break; 2632 break;
5483 case 'p': 2633 case 'p':
5484#ifdef CONFIG_FEATURE_SUN_LABEL 2634 if (LABEL_IS_SUN)
5485 if (label_sun == current_label_type)
5486 list_table(1); 2635 list_table(1);
5487 else 2636 else
5488#endif
5489 x_list_table(0); 2637 x_list_table(0);
5490 break; 2638 break;
5491 case 'q': 2639 case 'q':
@@ -5499,8 +2647,7 @@ xselect(void)
5499 _("Number of sectors")); 2647 _("Number of sectors"));
5500 if (dos_compatible_flag) { 2648 if (dos_compatible_flag) {
5501 sector_offset = sectors; 2649 sector_offset = sectors;
5502 fprintf(stderr, _("Warning: setting " 2650 printf(_("Warning: setting sector offset for DOS "
5503 "sector offset for DOS "
5504 "compatiblity\n")); 2651 "compatiblity\n"));
5505 } 2652 }
5506 update_units(); 2653 update_units();
@@ -5512,10 +2659,8 @@ xselect(void)
5512 write_table(); /* does not return */ 2659 write_table(); /* does not return */
5513 break; 2660 break;
5514 case 'y': 2661 case 'y':
5515#ifdef CONFIG_FEATURE_SUN_LABEL 2662 if (LABEL_IS_SUN)
5516 if (label_sun == current_label_type)
5517 sun_set_pcylcount(); 2663 sun_set_pcylcount();
5518#endif
5519 break; 2664 break;
5520 default: 2665 default:
5521 xmenu(); 2666 xmenu();
@@ -5576,21 +2721,20 @@ try(const char *device, int user_specified)
5576 close(fd); 2721 close(fd);
5577 } else if (gb < 0) { /* no DOS signature */ 2722 } else if (gb < 0) { /* no DOS signature */
5578 list_disk_geometry(); 2723 list_disk_geometry();
5579 if (label_aix == current_label_type){ 2724 if (LABEL_IS_AIX) {
5580 return; 2725 return;
5581 } 2726 }
5582#ifdef CONFIG_FEATURE_OSF_LABEL 2727#ifdef CONFIG_FEATURE_OSF_LABEL
5583 if (btrydev(device) < 0) 2728 if (btrydev(device) < 0)
5584#endif 2729#endif
5585 fprintf(stderr, 2730 printf(_("Disk %s doesn't contain a valid "
5586 _("Disk %s doesn't contain a valid "
5587 "partition table\n"), device); 2731 "partition table\n"), device);
5588 close(fd); 2732 close(fd);
5589 } else { 2733 } else {
5590 close(fd); 2734 close(fd);
5591 list_table(0); 2735 list_table(0);
5592#ifdef CONFIG_FEATURE_FDISK_WRITABLE 2736#ifdef CONFIG_FEATURE_FDISK_WRITABLE
5593 if (label_sun != current_label_type && partitions > 4){ 2737 if (!LABEL_IS_SUN && partitions > 4){
5594 delete_partition(ext_index); 2738 delete_partition(ext_index);
5595 } 2739 }
5596#endif 2740#endif
@@ -5600,7 +2744,7 @@ try(const char *device, int user_specified)
5600 and SCSI hard disks which may not be 2744 and SCSI hard disks which may not be
5601 installed on the system. */ 2745 installed on the system. */
5602 if (errno == EACCES) { 2746 if (errno == EACCES) {
5603 fprintf(stderr, _("Cannot open %s\n"), device); 2747 printf(_("Cannot open %s\n"), device);
5604 return; 2748 return;
5605 } 2749 }
5606 } 2750 }
@@ -5615,7 +2759,7 @@ tryprocpt(void)
5615 char line[100], ptname[100], devname[120], *s; 2759 char line[100], ptname[100], devname[120], *s;
5616 int ma, mi, sz; 2760 int ma, mi, sz;
5617 2761
5618 procpt = bb_wfopen(PROC_PARTITIONS, "r"); 2762 procpt = bb_wfopen("/proc/partitions", "r");
5619 2763
5620 while (fgets(line, sizeof(line), procpt)) { 2764 while (fgets(line, sizeof(line), procpt)) {
5621 if (sscanf(line, " %d %d %d %[^\n ]", 2765 if (sscanf(line, " %d %d %d %[^\n ]",
@@ -5659,7 +2803,7 @@ int fdisk_main(int argc, char **argv)
5659 * Options -C, -H, -S set the geometry. 2803 * Options -C, -H, -S set the geometry.
5660 * 2804 *
5661 */ 2805 */
5662 while ((c = getopt(argc, argv, "b:C:H:lS:uvV" 2806 while ((c = getopt(argc, argv, "b:C:H:lS:u"
5663#ifdef CONFIG_FEATURE_FDISK_BLKSIZE 2807#ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5664 "s" 2808 "s"
5665#endif 2809#endif
@@ -5703,10 +2847,6 @@ int fdisk_main(int argc, char **argv)
5703 case 'u': 2847 case 'u':
5704 display_in_cyl_units = 0; 2848 display_in_cyl_units = 0;
5705 break; 2849 break;
5706 case 'V':
5707 case 'v':
5708 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5709 return 0;
5710 default: 2850 default:
5711 bb_show_usage(); 2851 bb_show_usage();
5712 } 2852 }
@@ -5777,97 +2917,81 @@ int fdisk_main(int argc, char **argv)
5777 2917
5778 get_boot(fdisk); 2918 get_boot(fdisk);
5779 2919
5780#ifdef CONFIG_FEATURE_OSF_LABEL 2920 if (LABEL_IS_OSF) {
5781 if (label_osf == current_label_type) {
5782 /* OSF label, and no DOS label */ 2921 /* OSF label, and no DOS label */
5783 printf(_("Detected an OSF/1 disklabel on %s, entering " 2922 printf(_("Detected an OSF/1 disklabel on %s, entering "
5784 "disklabel mode.\n"), 2923 "disklabel mode.\n"), disk_device);
5785 disk_device);
5786 bselect(); 2924 bselect();
5787 /*Why do we do this? It seems to be counter-intuitive*/ 2925 /*Why do we do this? It seems to be counter-intuitive*/
5788 current_label_type = label_dos; 2926 current_label_type = label_dos;
5789 /* If we return we may want to make an empty DOS label? */ 2927 /* If we return we may want to make an empty DOS label? */
5790 } 2928 }
5791#endif
5792 2929
5793 while (1) { 2930 while (1) {
5794 putchar('\n'); 2931 putchar('\n');
5795 c = tolower(read_char(_("Command (m for help): "))); 2932 c = tolower(read_nonempty(_("Command (m for help): ")));
5796 switch (c) { 2933 switch (c) {
5797 case 'a': 2934 case 'a':
5798 if (label_dos == current_label_type) 2935 if (LABEL_IS_DOS)
5799 toggle_active(get_partition(1, partitions)); 2936 toggle_active(get_partition(1, partitions));
5800#ifdef CONFIG_FEATURE_SUN_LABEL 2937 else if (LABEL_IS_SUN)
5801 else if (label_sun == current_label_type)
5802 toggle_sunflags(get_partition(1, partitions), 2938 toggle_sunflags(get_partition(1, partitions),
5803 0x01); 2939 0x01);
5804#endif 2940 else if (LABEL_IS_SGI)
5805#ifdef CONFIG_FEATURE_SGI_LABEL
5806 else if (label_sgi == current_label_type)
5807 sgi_set_bootpartition( 2941 sgi_set_bootpartition(
5808 get_partition(1, partitions)); 2942 get_partition(1, partitions));
5809#endif
5810 else 2943 else
5811 unknown_command(c); 2944 unknown_command(c);
5812 break; 2945 break;
5813 case 'b': 2946 case 'b':
5814#ifdef CONFIG_FEATURE_SGI_LABEL 2947 if (LABEL_IS_SGI) {
5815 if (label_sgi == current_label_type) {
5816 printf(_("\nThe current boot file is: %s\n"), 2948 printf(_("\nThe current boot file is: %s\n"),
5817 sgi_get_bootfile()); 2949 sgi_get_bootfile());
5818 if (read_chars(_("Please enter the name of the " 2950 if (read_maybe_empty(_("Please enter the name of the "
5819 "new boot file: ")) == '\n') 2951 "new boot file: ")) == '\n')
5820 printf(_("Boot file unchanged\n")); 2952 printf(_("Boot file unchanged\n"));
5821 else 2953 else
5822 sgi_set_bootfile(line_ptr); 2954 sgi_set_bootfile(line_ptr);
5823 } else 2955 } else
5824#endif
5825#ifdef CONFIG_FEATURE_OSF_LABEL 2956#ifdef CONFIG_FEATURE_OSF_LABEL
5826 bselect(); 2957 bselect();
5827#endif 2958#endif
2959
2960/* BUG!? Think what will happen if !CONFIG_FEATURE_OSF_LABEL !!! */
2961
5828 break; 2962 break;
5829 case 'c': 2963 case 'c':
5830 if (label_dos == current_label_type) 2964 if (LABEL_IS_DOS)
5831 toggle_dos_compatibility_flag(); 2965 toggle_dos_compatibility_flag();
5832#ifdef CONFIG_FEATURE_SUN_LABEL 2966 else if (LABEL_IS_SUN)
5833 else if (label_sun == current_label_type)
5834 toggle_sunflags(get_partition(1, partitions), 2967 toggle_sunflags(get_partition(1, partitions),
5835 0x10); 2968 0x10);
5836#endif 2969 else if (LABEL_IS_SGI)
5837#ifdef CONFIG_FEATURE_SGI_LABEL
5838 else if (label_sgi == current_label_type)
5839 sgi_set_swappartition( 2970 sgi_set_swappartition(
5840 get_partition(1, partitions)); 2971 get_partition(1, partitions));
5841#endif
5842 else 2972 else
5843 unknown_command(c); 2973 unknown_command(c);
5844 break; 2974 break;
5845 case 'd': 2975 case 'd':
5846 { 2976 {
5847 int j; 2977 int j;
5848#ifdef CONFIG_FEATURE_SGI_LABEL
5849 /* If sgi_label then don't use get_existing_partition, 2978 /* If sgi_label then don't use get_existing_partition,
5850 let the user select a partition, since 2979 let the user select a partition, since
5851 get_existing_partition() only works for Linux-like 2980 get_existing_partition() only works for Linux-like
5852 partition tables */ 2981 partition tables */
5853 if (label_sgi != current_label_type) { 2982 if (!LABEL_IS_SGI) {
5854 j = get_existing_partition(1, partitions); 2983 j = get_existing_partition(1, partitions);
5855 } else { 2984 } else {
5856 j = get_partition(1, partitions); 2985 j = get_partition(1, partitions);
5857 } 2986 }
5858#else
5859 j = get_existing_partition(1, partitions);
5860#endif
5861 if (j >= 0) 2987 if (j >= 0)
5862 delete_partition(j); 2988 delete_partition(j);
5863 } 2989 }
5864 break; 2990 break;
5865 case 'i': 2991 case 'i':
5866#ifdef CONFIG_FEATURE_SGI_LABEL 2992 if (LABEL_IS_SGI)
5867 if (label_sgi == current_label_type)
5868 create_sgiinfo(); 2993 create_sgiinfo();
5869 else 2994 else
5870#endif
5871 unknown_command(c); 2995 unknown_command(c);
5872 case 'l': 2996 case 'l':
5873 list_types(get_sys_types()); 2997 list_types(get_sys_types());
@@ -5907,14 +3031,10 @@ int fdisk_main(int argc, char **argv)
5907 break; 3031 break;
5908#ifdef CONFIG_FEATURE_FDISK_ADVANCED 3032#ifdef CONFIG_FEATURE_FDISK_ADVANCED
5909 case 'x': 3033 case 'x':
5910#ifdef CONFIG_FEATURE_SGI_LABEL 3034 if (LABEL_IS_SGI) {
5911 if (label_sgi == current_label_type) { 3035 printf(_("\n\tSorry, no experts menu for SGI "
5912 fprintf(stderr,
5913 _("\n\tSorry, no experts menu for SGI "
5914 "partition tables available.\n\n")); 3036 "partition tables available.\n\n"));
5915 } else 3037 } else
5916#endif
5917
5918 xselect(); 3038 xselect();
5919 break; 3039 break;
5920#endif 3040#endif
diff --git a/util-linux/fdisk_aix.c b/util-linux/fdisk_aix.c
new file mode 100644
index 000000000..a3d5fe15f
--- /dev/null
+++ b/util-linux/fdisk_aix.c
@@ -0,0 +1,76 @@
1#ifdef CONFIG_FEATURE_AIX_LABEL
2/*
3 * Copyright (C) Andreas Neuper, Sep 1998.
4 * This file may be redistributed under
5 * the terms of the GNU Public License.
6 */
7
8typedef struct {
9 unsigned int magic; /* expect AIX_LABEL_MAGIC */
10 unsigned int fillbytes1[124];
11 unsigned int physical_volume_id;
12 unsigned int fillbytes2[124];
13} aix_partition;
14
15#define AIX_LABEL_MAGIC 0xc9c2d4c1
16#define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
17#define AIX_INFO_MAGIC 0x00072959
18#define AIX_INFO_MAGIC_SWAPPED 0x59290700
19
20#define aixlabel ((aix_partition *)MBRbuffer)
21
22
23/*
24 Changes:
25 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
26 * Internationalization
27 *
28 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
29 * Some fixes
30*/
31
32static int aix_other_endian;
33static short aix_volumes = 1;
34
35/*
36 * only dealing with free blocks here
37 */
38
39static void
40aix_info(void)
41{
42 puts(
43 _("\n\tThere is a valid AIX label on this disk.\n"
44 "\tUnfortunately Linux cannot handle these\n"
45 "\tdisks at the moment. Nevertheless some\n"
46 "\tadvice:\n"
47 "\t1. fdisk will destroy its contents on write.\n"
48 "\t2. Be sure that this disk is NOT a still vital\n"
49 "\t part of a volume group. (Otherwise you may\n"
50 "\t erase the other disks as well, if unmirrored.)\n"
51 "\t3. Before deleting this physical volume be sure\n"
52 "\t to remove the disk logically from your AIX\n"
53 "\t machine. (Otherwise you become an AIXpert).")
54 );
55}
56
57static int
58check_aix_label(void)
59{
60 if (aixlabel->magic != AIX_LABEL_MAGIC &&
61 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
62 current_label_type = 0;
63 aix_other_endian = 0;
64 return 0;
65 }
66 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
67 update_units();
68 current_label_type = label_aix;
69 partitions = 1016;
70 aix_volumes = 15;
71 aix_info();
72 /*aix_nolabel();*/ /* %% */
73 /*aix_label = 1;*/ /* %% */
74 return 1;
75}
76#endif /* AIX_LABEL */
diff --git a/util-linux/fdisk_osf.c b/util-linux/fdisk_osf.c
new file mode 100644
index 000000000..97fe79aca
--- /dev/null
+++ b/util-linux/fdisk_osf.c
@@ -0,0 +1,1046 @@
1#ifdef CONFIG_FEATURE_OSF_LABEL
2/*
3 * Copyright (c) 1987, 1988 Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgment:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35
36#ifndef BSD_DISKMAGIC
37#define BSD_DISKMAGIC ((uint32_t) 0x82564557)
38#endif
39
40#ifndef BSD_MAXPARTITIONS
41#define BSD_MAXPARTITIONS 16
42#endif
43
44#define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
45
46#if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__m68k__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
47#define BSD_LABELSECTOR 1
48#define BSD_LABELOFFSET 0
49#elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
50#define BSD_LABELSECTOR 0
51#define BSD_LABELOFFSET 64
52#elif defined (__s390__) || defined (__s390x__)
53#define BSD_LABELSECTOR 1
54#define BSD_LABELOFFSET 0
55#else
56#error unknown architecture
57#endif
58
59#define BSD_BBSIZE 8192 /* size of boot area, with label */
60#define BSD_SBSIZE 8192 /* max size of fs superblock */
61
62struct xbsd_disklabel {
63 uint32_t d_magic; /* the magic number */
64 int16_t d_type; /* drive type */
65 int16_t d_subtype; /* controller/d_type specific */
66 char d_typename[16]; /* type name, e.g. "eagle" */
67 char d_packname[16]; /* pack identifier */
68 /* disk geometry: */
69 uint32_t d_secsize; /* # of bytes per sector */
70 uint32_t d_nsectors; /* # of data sectors per track */
71 uint32_t d_ntracks; /* # of tracks per cylinder */
72 uint32_t d_ncylinders; /* # of data cylinders per unit */
73 uint32_t d_secpercyl; /* # of data sectors per cylinder */
74 uint32_t d_secperunit; /* # of data sectors per unit */
75 /*
76 * Spares (bad sector replacements) below
77 * are not counted in d_nsectors or d_secpercyl.
78 * Spare sectors are assumed to be physical sectors
79 * which occupy space at the end of each track and/or cylinder.
80 */
81 uint16_t d_sparespertrack; /* # of spare sectors per track */
82 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
83 /*
84 * Alternate cylinders include maintenance, replacement,
85 * configuration description areas, etc.
86 */
87 uint32_t d_acylinders; /* # of alt. cylinders per unit */
88
89 /* hardware characteristics: */
90 /*
91 * d_interleave, d_trackskew and d_cylskew describe perturbations
92 * in the media format used to compensate for a slow controller.
93 * Interleave is physical sector interleave, set up by the formatter
94 * or controller when formatting. When interleaving is in use,
95 * logically adjacent sectors are not physically contiguous,
96 * but instead are separated by some number of sectors.
97 * It is specified as the ratio of physical sectors traversed
98 * per logical sector. Thus an interleave of 1:1 implies contiguous
99 * layout, while 2:1 implies that logical sector 0 is separated
100 * by one sector from logical sector 1.
101 * d_trackskew is the offset of sector 0 on track N
102 * relative to sector 0 on track N-1 on the same cylinder.
103 * Finally, d_cylskew is the offset of sector 0 on cylinder N
104 * relative to sector 0 on cylinder N-1.
105 */
106 uint16_t d_rpm; /* rotational speed */
107 uint16_t d_interleave; /* hardware sector interleave */
108 uint16_t d_trackskew; /* sector 0 skew, per track */
109 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
110 uint32_t d_headswitch; /* head switch time, usec */
111 uint32_t d_trkseek; /* track-to-track seek, usec */
112 uint32_t d_flags; /* generic flags */
113#define NDDATA 5
114 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
115#define NSPARE 5
116 uint32_t d_spare[NSPARE]; /* reserved for future use */
117 uint32_t d_magic2; /* the magic number (again) */
118 uint16_t d_checksum; /* xor of data incl. partitions */
119 /* filesystem and partition information: */
120 uint16_t d_npartitions; /* number of partitions in following */
121 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
122 uint32_t d_sbsize; /* max size of fs superblock, bytes */
123 struct xbsd_partition { /* the partition table */
124 uint32_t p_size; /* number of sectors in partition */
125 uint32_t p_offset; /* starting sector */
126 uint32_t p_fsize; /* filesystem basic fragment size */
127 uint8_t p_fstype; /* filesystem type, see below */
128 uint8_t p_frag; /* filesystem fragments per block */
129 uint16_t p_cpg; /* filesystem cylinders per group */
130 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
131};
132
133/* d_type values: */
134#define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
135#define BSD_DTYPE_MSCP 2 /* MSCP */
136#define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
137#define BSD_DTYPE_SCSI 4 /* SCSI */
138#define BSD_DTYPE_ESDI 5 /* ESDI interface */
139#define BSD_DTYPE_ST506 6 /* ST506 etc. */
140#define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
141#define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
142#define BSD_DTYPE_FLOPPY 10 /* floppy */
143
144/* d_subtype values: */
145#define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
146#define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
147#define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
148
149static const char * const xbsd_dktypenames[] = {
150 "unknown",
151 "SMD",
152 "MSCP",
153 "old DEC",
154 "SCSI",
155 "ESDI",
156 "ST506",
157 "HP-IB",
158 "HP-FL",
159 "type 9",
160 "floppy",
161 0
162};
163#define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
164
165/*
166 * Filesystem type and version.
167 * Used to interpret other filesystem-specific
168 * per-partition information.
169 */
170#define BSD_FS_UNUSED 0 /* unused */
171#define BSD_FS_SWAP 1 /* swap */
172#define BSD_FS_V6 2 /* Sixth Edition */
173#define BSD_FS_V7 3 /* Seventh Edition */
174#define BSD_FS_SYSV 4 /* System V */
175#define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
176#define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
177#define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
178#define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
179#define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
180#define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
181#define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
182#define BSD_FS_ISOFS BSD_FS_ISO9660
183#define BSD_FS_BOOT 13 /* partition contains bootstrap */
184#define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
185#define BSD_FS_HFS 15 /* Macintosh HFS */
186#define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
187
188/* this is annoying, but it's also the way it is :-( */
189#ifdef __alpha__
190#define BSD_FS_EXT2 8 /* ext2 file system */
191#else
192#define BSD_FS_MSDOS 8 /* MS-DOS file system */
193#endif
194
195static const struct systypes xbsd_fstypes[] = {
196 { "\x00" "unused" }, /* BSD_FS_UNUSED */
197 { "\x01" "swap" }, /* BSD_FS_SWAP */
198 { "\x02" "Version 6" }, /* BSD_FS_V6 */
199 { "\x03" "Version 7" }, /* BSD_FS_V7 */
200 { "\x04" "System V" }, /* BSD_FS_SYSV */
201 { "\x05" "4.1BSD" }, /* BSD_FS_V71K */
202 { "\x06" "Eighth Edition" }, /* BSD_FS_V8 */
203 { "\x07" "4.2BSD" }, /* BSD_FS_BSDFFS */
204#ifdef __alpha__
205 { "\x08" "ext2" }, /* BSD_FS_EXT2 */
206#else
207 { "\x08" "MS-DOS" }, /* BSD_FS_MSDOS */
208#endif
209 { "\x09" "4.4LFS" }, /* BSD_FS_BSDLFS */
210 { "\x0a" "unknown" }, /* BSD_FS_OTHER */
211 { "\x0b" "HPFS" }, /* BSD_FS_HPFS */
212 { "\x0c" "ISO-9660" }, /* BSD_FS_ISO9660 */
213 { "\x0d" "boot" }, /* BSD_FS_BOOT */
214 { "\x0e" "ADOS" }, /* BSD_FS_ADOS */
215 { "\x0f" "HFS" }, /* BSD_FS_HFS */
216 { "\x10" "AdvFS" }, /* BSD_FS_ADVFS */
217 { NULL }
218};
219#define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
220
221
222/*
223 * flags shared by various drives:
224 */
225#define BSD_D_REMOVABLE 0x01 /* removable media */
226#define BSD_D_ECC 0x02 /* supports ECC */
227#define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
228#define BSD_D_RAMDISK 0x08 /* disk emulator */
229#define BSD_D_CHAIN 0x10 /* can do back-back transfers */
230#define BSD_D_DOSPART 0x20 /* within MSDOS partition */
231
232/*
233 Changes:
234 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
235
236 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
237 support for OSF/1 disklabels on Alpha.
238 Also fixed unaligned accesses in alpha_bootblock_checksum()
239*/
240
241static int possibly_osf_label;
242
243#define FREEBSD_PARTITION 0xa5
244#define NETBSD_PARTITION 0xa9
245
246static void xbsd_delete_part(void);
247static void xbsd_new_part(void);
248static void xbsd_write_disklabel(void);
249static int xbsd_create_disklabel(void);
250static void xbsd_edit_disklabel(void);
251static void xbsd_write_bootstrap(void);
252static void xbsd_change_fstype(void);
253static int xbsd_get_part_index(int max);
254static int xbsd_check_new_partition(int *i);
255static void xbsd_list_types(void);
256static u_short xbsd_dkcksum(struct xbsd_disklabel *lp);
257static int xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d);
258static int xbsd_readlabel(struct partition *p, struct xbsd_disklabel *d);
259static int xbsd_writelabel(struct partition *p, struct xbsd_disklabel *d);
260
261#if defined (__alpha__)
262static void alpha_bootblock_checksum(char *boot);
263#endif
264
265#if !defined (__alpha__)
266static int xbsd_translate_fstype(int linux_type);
267static void xbsd_link_part(void);
268static struct partition *xbsd_part;
269static int xbsd_part_index;
270#endif
271
272#if defined (__alpha__)
273/* We access this through a uint64_t * when checksumming */
274static char disklabelbuffer[BSD_BBSIZE] ATTRIBUTE_ALIGNED(8);
275#else
276static char disklabelbuffer[BSD_BBSIZE];
277#endif
278
279static struct xbsd_disklabel xbsd_dlabel;
280
281#define bsd_cround(n) \
282 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
283
284/*
285 * Test whether the whole disk has BSD disk label magic.
286 *
287 * Note: often reformatting with DOS-type label leaves the BSD magic,
288 * so this does not mean that there is a BSD disk label.
289 */
290static int
291check_osf_label(void)
292{
293 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
294 return 0;
295 return 1;
296}
297
298static int
299btrydev(const char * dev)
300{
301 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
302 return -1;
303 printf(_("\nBSD label for device: %s\n"), dev);
304 xbsd_print_disklabel (0);
305 return 0;
306}
307
308static void
309bmenu(void)
310{
311 puts (_("Command action"));
312 puts (_("\td\tdelete a BSD partition"));
313 puts (_("\te\tedit drive data"));
314 puts (_("\ti\tinstall bootstrap"));
315 puts (_("\tl\tlist known filesystem types"));
316 puts (_("\tm\tprint this menu"));
317 puts (_("\tn\tadd a new BSD partition"));
318 puts (_("\tp\tprint BSD partition table"));
319 puts (_("\tq\tquit without saving changes"));
320 puts (_("\tr\treturn to main menu"));
321 puts (_("\ts\tshow complete disklabel"));
322 puts (_("\tt\tchange a partition's filesystem id"));
323 puts (_("\tu\tchange units (cylinders/sectors)"));
324 puts (_("\tw\twrite disklabel to disk"));
325#if !defined (__alpha__)
326 puts (_("\tx\tlink BSD partition to non-BSD partition"));
327#endif
328}
329
330#if !defined (__alpha__)
331static int
332hidden(int type)
333{
334 return type ^ 0x10;
335}
336
337static int
338is_bsd_partition_type(int type)
339{
340 return (type == FREEBSD_PARTITION ||
341 type == hidden(FREEBSD_PARTITION) ||
342 type == NETBSD_PARTITION ||
343 type == hidden(NETBSD_PARTITION));
344}
345#endif
346
347static void
348bselect(void)
349{
350#if !defined (__alpha__)
351 int t, ss;
352 struct partition *p;
353
354 for (t = 0; t < 4; t++) {
355 p = get_part_table(t);
356 if (p && is_bsd_partition_type(p->sys_ind)) {
357 xbsd_part = p;
358 xbsd_part_index = t;
359 ss = get_start_sect(xbsd_part);
360 if (ss == 0) {
361 fprintf(stderr, _("Partition %s has invalid starting sector 0.\n"),
362 partname(disk_device, t+1, 0));
363 return;
364 }
365 printf(_("Reading disklabel of %s at sector %d.\n"),
366 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
367 if (xbsd_readlabel(xbsd_part, &xbsd_dlabel) == 0)
368 if (xbsd_create_disklabel() == 0)
369 return;
370 break;
371 }
372 }
373
374 if (t == 4) {
375 printf(_("There is no *BSD partition on %s.\n"), disk_device);
376 return;
377 }
378
379#elif defined (__alpha__)
380
381 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
382 if (xbsd_create_disklabel() == 0)
383 exit (EXIT_SUCCESS);
384
385#endif
386
387 while (1) {
388 putchar('\n');
389 switch (tolower(read_nonempty(_("BSD disklabel command (m for help): ")))) {
390 case 'd':
391 xbsd_delete_part();
392 break;
393 case 'e':
394 xbsd_edit_disklabel();
395 break;
396 case 'i':
397 xbsd_write_bootstrap();
398 break;
399 case 'l':
400 xbsd_list_types();
401 break;
402 case 'n':
403 xbsd_new_part();
404 break;
405 case 'p':
406 xbsd_print_disklabel(0);
407 break;
408 case 'q':
409 close(fd);
410 exit(EXIT_SUCCESS);
411 case 'r':
412 return;
413 case 's':
414 xbsd_print_disklabel(1);
415 break;
416 case 't':
417 xbsd_change_fstype();
418 break;
419 case 'u':
420 change_units();
421 break;
422 case 'w':
423 xbsd_write_disklabel();
424 break;
425#if !defined (__alpha__)
426 case 'x':
427 xbsd_link_part();
428 break;
429#endif
430 default:
431 bmenu();
432 break;
433 }
434 }
435}
436
437static void
438xbsd_delete_part(void)
439{
440 int i;
441
442 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
443 xbsd_dlabel.d_partitions[i].p_size = 0;
444 xbsd_dlabel.d_partitions[i].p_offset = 0;
445 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
446 if (xbsd_dlabel.d_npartitions == i + 1)
447 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
448 xbsd_dlabel.d_npartitions--;
449}
450
451static void
452xbsd_new_part(void)
453{
454 off_t begin, end;
455 char mesg[256];
456 int i;
457
458 if (!xbsd_check_new_partition(&i))
459 return;
460
461#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
462 begin = get_start_sect(xbsd_part);
463 end = begin + get_nr_sects(xbsd_part) - 1;
464#else
465 begin = 0;
466 end = xbsd_dlabel.d_secperunit - 1;
467#endif
468
469 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
470 begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end),
471 0, mesg);
472
473 if (display_in_cyl_units)
474 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
475
476 snprintf(mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
477 str_units(SINGULAR));
478 end = read_int(bsd_cround (begin), bsd_cround (end), bsd_cround (end),
479 bsd_cround (begin), mesg);
480
481 if (display_in_cyl_units)
482 end = end * xbsd_dlabel.d_secpercyl - 1;
483
484 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
485 xbsd_dlabel.d_partitions[i].p_offset = begin;
486 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
487}
488
489static void
490xbsd_print_disklabel(int show_all)
491{
492 struct xbsd_disklabel *lp = &xbsd_dlabel;
493 struct xbsd_partition *pp;
494 int i, j;
495
496 if (show_all) {
497#if defined (__alpha__)
498 printf("# %s:\n", disk_device);
499#else
500 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
501#endif
502 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
503 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
504 else
505 printf(_("type: %d\n"), lp->d_type);
506 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
507 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
508 printf(_("flags:"));
509 if (lp->d_flags & BSD_D_REMOVABLE)
510 printf(_(" removable"));
511 if (lp->d_flags & BSD_D_ECC)
512 printf(_(" ecc"));
513 if (lp->d_flags & BSD_D_BADSECT)
514 printf(_(" badsect"));
515 printf("\n");
516 /* On various machines the fields of *lp are short/int/long */
517 /* In order to avoid problems, we cast them all to long. */
518 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
519 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
520 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
521 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
522 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
523 printf(_("rpm: %d\n"), lp->d_rpm);
524 printf(_("interleave: %d\n"), lp->d_interleave);
525 printf(_("trackskew: %d\n"), lp->d_trackskew);
526 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
527 printf(_("headswitch: %ld\t\t# milliseconds\n"),
528 (long) lp->d_headswitch);
529 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
530 (long) lp->d_trkseek);
531 printf(_("drivedata: "));
532 for (i = NDDATA - 1; i >= 0; i--)
533 if (lp->d_drivedata[i])
534 break;
535 if (i < 0)
536 i = 0;
537 for (j = 0; j <= i; j++)
538 printf("%ld ", (long) lp->d_drivedata[j]);
539 }
540 printf(_("\n%d partitions:\n"), lp->d_npartitions);
541 printf(_("# start end size fstype [fsize bsize cpg]\n"));
542 pp = lp->d_partitions;
543 for (i = 0; i < lp->d_npartitions; i++, pp++) {
544 if (pp->p_size) {
545 if (display_in_cyl_units && lp->d_secpercyl) {
546 printf(" %c: %8ld%c %8ld%c %8ld%c ",
547 'a' + i,
548 (long) pp->p_offset / lp->d_secpercyl + 1,
549 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
550 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl,
551 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
552 (long) pp->p_size / lp->d_secpercyl,
553 (pp->p_size % lp->d_secpercyl) ? '*' : ' '
554 );
555 } else {
556 printf(" %c: %8ld %8ld %8ld ",
557 'a' + i,
558 (long) pp->p_offset,
559 (long) pp->p_offset + pp->p_size - 1,
560 (long) pp->p_size
561 );
562 }
563
564 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
565 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
566 else
567 printf("%8x", pp->p_fstype);
568
569 switch (pp->p_fstype) {
570 case BSD_FS_UNUSED:
571 printf(" %5ld %5ld %5.5s ",
572 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
573 break;
574 case BSD_FS_BSDFFS:
575 printf(" %5ld %5ld %5d ",
576 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg);
577 break;
578 default:
579 printf("%22.22s", "");
580 break;
581 }
582 printf("\n");
583 }
584 }
585}
586
587static void
588xbsd_write_disklabel(void)
589{
590#if defined (__alpha__)
591 printf(_("Writing disklabel to %s.\n"), disk_device);
592 xbsd_writelabel(NULL, &xbsd_dlabel);
593#else
594 printf(_("Writing disklabel to %s.\n"),
595 partname(disk_device, xbsd_part_index + 1, 0));
596 xbsd_writelabel(xbsd_part, &xbsd_dlabel);
597#endif
598 reread_partition_table(0); /* no exit yet */
599}
600
601static int
602xbsd_create_disklabel(void)
603{
604 char c;
605
606#if defined (__alpha__)
607 fprintf(stderr, _("%s contains no disklabel.\n"), disk_device);
608#else
609 fprintf(stderr, _("%s contains no disklabel.\n"),
610 partname(disk_device, xbsd_part_index + 1, 0));
611#endif
612
613 while (1) {
614 c = read_nonempty(_("Do you want to create a disklabel? (y/n) "));
615 if (c == 'y' || c == 'Y') {
616 if (xbsd_initlabel(
617#if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
618 defined (__s390__) || defined (__s390x__)
619 NULL, &xbsd_dlabel
620#else
621 xbsd_part, &xbsd_dlabel/* not used, xbsd_part_index*/
622#endif
623 ) == 1) {
624 xbsd_print_disklabel (1);
625 return 1;
626 } else
627 return 0;
628 } else if (c == 'n')
629 return 0;
630 }
631}
632
633static int
634edit_int(int def, char *mesg)
635{
636 do {
637 fputs(mesg, stdout);
638 printf(" (%d): ", def);
639 if (!read_line())
640 return def;
641 } while (!isdigit(*line_ptr));
642 return atoi(line_ptr);
643}
644
645static void
646xbsd_edit_disklabel(void)
647{
648 struct xbsd_disklabel *d;
649
650 d = &xbsd_dlabel;
651
652#if defined (__alpha__) || defined (__ia64__)
653 d->d_secsize = (u_long) edit_int((u_long) d->d_secsize ,_("bytes/sector"));
654 d->d_nsectors = (u_long) edit_int((u_long) d->d_nsectors ,_("sectors/track"));
655 d->d_ntracks = (u_long) edit_int((u_long) d->d_ntracks ,_("tracks/cylinder"));
656 d->d_ncylinders = (u_long) edit_int((u_long) d->d_ncylinders ,_("cylinders"));
657#endif
658
659 /* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */
660 while (1) {
661 d->d_secpercyl = (u_long) edit_int((u_long) d->d_nsectors * d->d_ntracks,
662 _("sectors/cylinder"));
663 if (d->d_secpercyl <= d->d_nsectors * d->d_ntracks)
664 break;
665
666 printf(_("Must be <= sectors/track * tracks/cylinder (default).\n"));
667 }
668 d->d_rpm = (u_short) edit_int((u_short) d->d_rpm ,_("rpm"));
669 d->d_interleave = (u_short) edit_int((u_short) d->d_interleave,_("interleave"));
670 d->d_trackskew = (u_short) edit_int((u_short) d->d_trackskew ,_("trackskew"));
671 d->d_cylskew = (u_short) edit_int((u_short) d->d_cylskew ,_("cylinderskew"));
672 d->d_headswitch = (u_long) edit_int((u_long) d->d_headswitch ,_("headswitch"));
673 d->d_trkseek = (u_long) edit_int((u_long) d->d_trkseek ,_("track-to-track seek"));
674
675 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
676}
677
678static int
679xbsd_get_bootstrap (char *path, void *ptr, int size)
680{
681 int fdb;
682
683 if ((fdb = open (path, O_RDONLY)) < 0) {
684 perror(path);
685 return 0;
686 }
687 if (read(fdb, ptr, size) < 0) {
688 perror(path);
689 close(fdb);
690 return 0;
691 }
692 printf(" ... %s\n", path);
693 close(fdb);
694 return 1;
695}
696
697static void
698sync_disks(void)
699{
700 printf(_("\nSyncing disks.\n"));
701 sync();
702 sleep(4); /* What? */
703}
704
705static void
706xbsd_write_bootstrap(void)
707{
708 char *bootdir = BSD_LINUX_BOOTDIR;
709 char path[MAXPATHLEN];
710 char *dkbasename;
711 struct xbsd_disklabel dl;
712 char *d, *p, *e;
713 int sector;
714
715 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
716 dkbasename = "sd";
717 else
718 dkbasename = "wd";
719
720 printf(_("Bootstrap: %sboot -> boot%s (%s): "),
721 dkbasename, dkbasename, dkbasename);
722 if (read_line()) {
723 line_ptr[strlen(line_ptr)-1] = '\0';
724 dkbasename = line_ptr;
725 }
726 snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
727 if (!xbsd_get_bootstrap(path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
728 return;
729
730/* We need a backup of the disklabel (xbsd_dlabel might have changed). */
731 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
732 memmove(&dl, d, sizeof(struct xbsd_disklabel));
733
734/* The disklabel will be overwritten by 0's from bootxx anyway */
735 memset(d, 0, sizeof(struct xbsd_disklabel));
736
737 snprintf(path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
738 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
739 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
740 return;
741
742 e = d + sizeof(struct xbsd_disklabel);
743 for (p = d; p < e; p++)
744 if (*p) {
745 fprintf(stderr, _("Bootstrap overlaps with disk label!\n"));
746 exit(EXIT_FAILURE);
747 }
748
749 memmove(d, &dl, sizeof(struct xbsd_disklabel));
750
751#if defined (__powerpc__) || defined (__hppa__)
752 sector = 0;
753#elif defined (__alpha__)
754 sector = 0;
755 alpha_bootblock_checksum(disklabelbuffer);
756#else
757 sector = get_start_sect(xbsd_part);
758#endif
759
760 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
761 fdisk_fatal(unable_to_seek);
762 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
763 fdisk_fatal(unable_to_write);
764
765#if defined (__alpha__)
766 printf(_("Bootstrap installed on %s.\n"), disk_device);
767#else
768 printf(_("Bootstrap installed on %s.\n"),
769 partname (disk_device, xbsd_part_index+1, 0));
770#endif
771
772 sync_disks();
773}
774
775static void
776xbsd_change_fstype(void)
777{
778 int i;
779
780 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
781 xbsd_dlabel.d_partitions[i].p_fstype = read_hex(xbsd_fstypes);
782}
783
784static int
785xbsd_get_part_index(int max)
786{
787 char prompt[256];
788 char l;
789
790 snprintf(prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
791 do
792 l = tolower(read_nonempty(prompt));
793 while (l < 'a' || l > 'a' + max - 1);
794 return l - 'a';
795}
796
797static int
798xbsd_check_new_partition(int *i)
799{
800 /* room for more? various BSD flavours have different maxima */
801 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
802 int t;
803
804 for (t = 0; t < BSD_MAXPARTITIONS; t++)
805 if (xbsd_dlabel.d_partitions[t].p_size == 0)
806 break;
807
808 if (t == BSD_MAXPARTITIONS) {
809 fprintf(stderr, _("The maximum number of partitions "
810 "has been created\n"));
811 return 0;
812 }
813 }
814
815 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
816
817 if (*i >= xbsd_dlabel.d_npartitions)
818 xbsd_dlabel.d_npartitions = (*i) + 1;
819
820 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
821 fprintf(stderr, _("This partition already exists.\n"));
822 return 0;
823 }
824
825 return 1;
826}
827
828static void
829xbsd_list_types(void)
830{
831 list_types(xbsd_fstypes);
832}
833
834static u_short
835xbsd_dkcksum(struct xbsd_disklabel *lp)
836{
837 u_short *start, *end;
838 u_short sum = 0;
839
840 start = (u_short *) lp;
841 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
842 while (start < end)
843 sum ^= *start++;
844 return sum;
845}
846
847static int
848xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d)
849{
850 struct xbsd_partition *pp;
851
852 get_geometry();
853 memset(d, 0, sizeof(struct xbsd_disklabel));
854
855 d->d_magic = BSD_DISKMAGIC;
856
857 if (strncmp(disk_device, "/dev/sd", 7) == 0)
858 d->d_type = BSD_DTYPE_SCSI;
859 else
860 d->d_type = BSD_DTYPE_ST506;
861
862#if !defined (__alpha__)
863 d->d_flags = BSD_D_DOSPART;
864#else
865 d->d_flags = 0;
866#endif
867 d->d_secsize = SECTOR_SIZE; /* bytes/sector */
868 d->d_nsectors = sectors; /* sectors/track */
869 d->d_ntracks = heads; /* tracks/cylinder (heads) */
870 d->d_ncylinders = cylinders;
871 d->d_secpercyl = sectors * heads;/* sectors/cylinder */
872 if (d->d_secpercyl == 0)
873 d->d_secpercyl = 1; /* avoid segfaults */
874 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
875
876 d->d_rpm = 3600;
877 d->d_interleave = 1;
878 d->d_trackskew = 0;
879 d->d_cylskew = 0;
880 d->d_headswitch = 0;
881 d->d_trkseek = 0;
882
883 d->d_magic2 = BSD_DISKMAGIC;
884 d->d_bbsize = BSD_BBSIZE;
885 d->d_sbsize = BSD_SBSIZE;
886
887#if !defined (__alpha__)
888 d->d_npartitions = 4;
889 pp = &d->d_partitions[2]; /* Partition C should be
890 the NetBSD partition */
891 pp->p_offset = get_start_sect(p);
892 pp->p_size = get_nr_sects(p);
893 pp->p_fstype = BSD_FS_UNUSED;
894 pp = &d->d_partitions[3]; /* Partition D should be
895 the whole disk */
896 pp->p_offset = 0;
897 pp->p_size = d->d_secperunit;
898 pp->p_fstype = BSD_FS_UNUSED;
899#elif defined (__alpha__)
900 d->d_npartitions = 3;
901 pp = &d->d_partitions[2]; /* Partition C should be
902 the whole disk */
903 pp->p_offset = 0;
904 pp->p_size = d->d_secperunit;
905 pp->p_fstype = BSD_FS_UNUSED;
906#endif
907
908 return 1;
909}
910
911/*
912 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
913 * If it has the right magic, return 1.
914 */
915static int
916xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
917{
918 int t, sector;
919
920 /* p is used only to get the starting sector */
921#if !defined (__alpha__)
922 sector = (p ? get_start_sect(p) : 0);
923#elif defined (__alpha__)
924 sector = 0;
925#endif
926
927 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
928 fdisk_fatal(unable_to_seek);
929 if (BSD_BBSIZE != read(fd, disklabelbuffer, BSD_BBSIZE))
930 fdisk_fatal(unable_to_read);
931
932 memmove(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
933 sizeof(struct xbsd_disklabel));
934
935 if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC)
936 return 0;
937
938 for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) {
939 d->d_partitions[t].p_size = 0;
940 d->d_partitions[t].p_offset = 0;
941 d->d_partitions[t].p_fstype = BSD_FS_UNUSED;
942 }
943
944 if (d->d_npartitions > BSD_MAXPARTITIONS)
945 fprintf(stderr, _("Warning: too many partitions "
946 "(%d, maximum is %d).\n"),
947 d->d_npartitions, BSD_MAXPARTITIONS);
948 return 1;
949}
950
951static int
952xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
953{
954 unsigned int sector;
955
956#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
957 sector = get_start_sect(p) + BSD_LABELSECTOR;
958#else
959 sector = BSD_LABELSECTOR;
960#endif
961
962 d->d_checksum = 0;
963 d->d_checksum = xbsd_dkcksum (d);
964
965 /* This is necessary if we want to write the bootstrap later,
966 otherwise we'd write the old disklabel with the bootstrap.
967 */
968 memmove(&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
969 d, sizeof(struct xbsd_disklabel));
970
971#if defined (__alpha__) && BSD_LABELSECTOR == 0
972 alpha_bootblock_checksum (disklabelbuffer);
973 if (lseek(fd, 0, SEEK_SET) == -1)
974 fdisk_fatal(unable_to_seek);
975 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
976 fdisk_fatal(unable_to_write);
977#else
978 if (lseek(fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1)
979 fdisk_fatal(unable_to_seek);
980 if (sizeof(struct xbsd_disklabel) != write(fd, d, sizeof(struct xbsd_disklabel)))
981 fdisk_fatal(unable_to_write);
982#endif
983 sync_disks();
984 return 1;
985}
986
987
988#if !defined (__alpha__)
989static int
990xbsd_translate_fstype(int linux_type)
991{
992 switch (linux_type) {
993 case 0x01: /* DOS 12-bit FAT */
994 case 0x04: /* DOS 16-bit <32M */
995 case 0x06: /* DOS 16-bit >=32M */
996 case 0xe1: /* DOS access */
997 case 0xe3: /* DOS R/O */
998 case 0xf2: /* DOS secondary */
999 return BSD_FS_MSDOS;
1000 case 0x07: /* OS/2 HPFS */
1001 return BSD_FS_HPFS;
1002 default:
1003 return BSD_FS_OTHER;
1004 }
1005}
1006
1007static void
1008xbsd_link_part(void)
1009{
1010 int k, i;
1011 struct partition *p;
1012
1013 k = get_partition(1, partitions);
1014
1015 if (!xbsd_check_new_partition(&i))
1016 return;
1017
1018 p = get_part_table(k);
1019
1020 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1021 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1022 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1023}
1024#endif
1025
1026#if defined (__alpha__)
1027
1028#if !defined(__GLIBC__)
1029typedef unsigned long long uint64_t;
1030#endif
1031
1032static void
1033alpha_bootblock_checksum(char *boot)
1034{
1035 uint64_t *dp, sum;
1036 int i;
1037
1038 dp = (uint64_t *)boot;
1039 sum = 0;
1040 for (i = 0; i < 63; i++)
1041 sum += dp[i];
1042 dp[63] = sum;
1043}
1044#endif /* __alpha__ */
1045
1046#endif /* OSF_LABEL */
diff --git a/util-linux/fdisk_sgi.c b/util-linux/fdisk_sgi.c
new file mode 100644
index 000000000..98abcc086
--- /dev/null
+++ b/util-linux/fdisk_sgi.c
@@ -0,0 +1,887 @@
1#ifdef CONFIG_FEATURE_SGI_LABEL
2
3/*
4 * Copyright (C) Andreas Neuper, Sep 1998.
5 * This file may be modified and redistributed under
6 * the terms of the GNU Public License.
7 */
8
9struct device_parameter { /* 48 bytes */
10 unsigned char skew;
11 unsigned char gap1;
12 unsigned char gap2;
13 unsigned char sparecyl;
14 unsigned short pcylcount;
15 unsigned short head_vol0;
16 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
17 unsigned char cmd_tag_queue_depth;
18 unsigned char unused0;
19 unsigned short unused1;
20 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
21 unsigned short bytes;
22 unsigned short ilfact;
23 unsigned int flags; /* controller flags */
24 unsigned int datarate;
25 unsigned int retries_on_error;
26 unsigned int ms_per_word;
27 unsigned short xylogics_gap1;
28 unsigned short xylogics_syncdelay;
29 unsigned short xylogics_readdelay;
30 unsigned short xylogics_gap2;
31 unsigned short xylogics_readgate;
32 unsigned short xylogics_writecont;
33};
34
35/*
36 * controller flags
37 */
38#define SECTOR_SLIP 0x01
39#define SECTOR_FWD 0x02
40#define TRACK_FWD 0x04
41#define TRACK_MULTIVOL 0x08
42#define IGNORE_ERRORS 0x10
43#define RESEEK 0x20
44#define ENABLE_CMDTAGQ 0x40
45
46typedef struct {
47 unsigned int magic; /* expect SGI_LABEL_MAGIC */
48 unsigned short boot_part; /* active boot partition */
49 unsigned short swap_part; /* active swap partition */
50 unsigned char boot_file[16]; /* name of the bootfile */
51 struct device_parameter devparam; /* 1 * 48 bytes */
52 struct volume_directory { /* 15 * 16 bytes */
53 unsigned char vol_file_name[8]; /* a character array */
54 unsigned int vol_file_start; /* number of logical block */
55 unsigned int vol_file_size; /* number of bytes */
56 } directory[15];
57 struct sgi_partinfo { /* 16 * 12 bytes */
58 unsigned int num_sectors; /* number of blocks */
59 unsigned int start_sector; /* must be cylinder aligned */
60 unsigned int id;
61 } partitions[16];
62 unsigned int csum;
63 unsigned int fillbytes;
64} sgi_partition;
65
66typedef struct {
67 unsigned int magic; /* looks like a magic number */
68 unsigned int a2;
69 unsigned int a3;
70 unsigned int a4;
71 unsigned int b1;
72 unsigned short b2;
73 unsigned short b3;
74 unsigned int c[16];
75 unsigned short d[3];
76 unsigned char scsi_string[50];
77 unsigned char serial[137];
78 unsigned short check1816;
79 unsigned char installer[225];
80} sgiinfo;
81
82#define SGI_LABEL_MAGIC 0x0be5a941
83#define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
84#define SGI_INFO_MAGIC 0x00072959
85#define SGI_INFO_MAGIC_SWAPPED 0x59290700
86
87#define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
88 : (uint16_t)(x))
89#define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
90 : (uint32_t)(x))
91
92#define sgilabel ((sgi_partition *)MBRbuffer)
93#define sgiparam (sgilabel->devparam)
94
95/*
96 *
97 * fdisksgilabel.c
98 *
99 * Copyright (C) Andreas Neuper, Sep 1998.
100 * This file may be modified and redistributed under
101 * the terms of the GNU Public License.
102 *
103 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
104 * Internationalization
105 */
106
107
108static int sgi_other_endian;
109static int debug;
110static short sgi_volumes = 1;
111
112/*
113 * only dealing with free blocks here
114 */
115
116typedef struct {
117 unsigned int first;
118 unsigned int last;
119} freeblocks;
120static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
121
122static void
123setfreelist(int i, unsigned int f, unsigned int l)
124{
125 freelist[i].first = f;
126 freelist[i].last = l;
127}
128
129static void
130add2freelist(unsigned int f, unsigned int l)
131{
132 int i;
133 for (i = 0; i < 17 ; i++)
134 if (freelist[i].last == 0)
135 break;
136 setfreelist(i, f, l);
137}
138
139static void
140clearfreelist(void)
141{
142 int i;
143
144 for (i = 0; i < 17 ; i++)
145 setfreelist(i, 0, 0);
146}
147
148static unsigned int
149isinfreelist(unsigned int b)
150{
151 int i;
152
153 for (i = 0; i < 17 ; i++)
154 if (freelist[i].first <= b && freelist[i].last >= b)
155 return freelist[i].last;
156 return 0;
157}
158 /* return last vacant block of this stride (never 0). */
159 /* the '>=' is not quite correct, but simplifies the code */
160/*
161 * end of free blocks section
162 */
163
164static const struct systypes sgi_sys_types[] = {
165/* SGI_VOLHDR */ { "\x00" "SGI volhdr" },
166/* 0x01 */ { "\x01" "SGI trkrepl" },
167/* 0x02 */ { "\x02" "SGI secrepl" },
168/* SGI_SWAP */ { "\x03" "SGI raw" },
169/* 0x04 */ { "\x04" "SGI bsd" },
170/* 0x05 */ { "\x05" "SGI sysv" },
171/* SGI_ENTIRE_DISK */ { "\x06" "SGI volume" },
172/* SGI_EFS */ { "\x07" "SGI efs" },
173/* 0x08 */ { "\x08" "SGI lvol" },
174/* 0x09 */ { "\x09" "SGI rlvol" },
175/* SGI_XFS */ { "\x0a" "SGI xfs" },
176/* SGI_XFSLOG */ { "\x0b" "SGI xfslog" },
177/* SGI_XLV */ { "\x0c" "SGI xlv" },
178/* SGI_XVM */ { "\x0d" "SGI xvm" },
179/* LINUX_SWAP */ { "\x82" "Linux swap" },
180/* LINUX_NATIVE */ { "\x83" "Linux native" },
181/* LINUX_LVM */ { "\x8d" "Linux LVM" },
182/* LINUX_RAID */ { "\xfd" "Linux RAID" },
183 { NULL }
184};
185
186
187static int
188sgi_get_nsect(void)
189{
190 return SGI_SSWAP16(sgilabel->devparam.nsect);
191}
192
193static int
194sgi_get_ntrks(void)
195{
196 return SGI_SSWAP16(sgilabel->devparam.ntrks);
197}
198
199static unsigned int
200two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */)
201{
202 int i = 0;
203 unsigned int sum = 0;
204
205 size /= sizeof(unsigned int);
206 for (i = 0; i < size; i++)
207 sum -= SGI_SSWAP32(base[i]);
208 return sum;
209}
210
211static int
212check_sgi_label(void)
213{
214 if (sizeof(sgilabel) > 512) {
215 fprintf(stderr,
216 _("According to MIPS Computer Systems, Inc the "
217 "Label must not contain more than 512 bytes\n"));
218 exit(1);
219 }
220
221 if (sgilabel->magic != SGI_LABEL_MAGIC
222 && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
223 current_label_type = label_dos;
224 return 0;
225 }
226
227 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
228 /*
229 * test for correct checksum
230 */
231 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
232 sizeof(*sgilabel))) {
233 fprintf(stderr,
234 _("Detected sgi disklabel with wrong checksum.\n"));
235 }
236 update_units();
237 current_label_type = label_sgi;
238 partitions = 16;
239 sgi_volumes = 15;
240 return 1;
241}
242
243static unsigned int
244sgi_get_start_sector(int i)
245{
246 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
247}
248
249static unsigned int
250sgi_get_num_sectors(int i)
251{
252 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
253}
254
255static int
256sgi_get_sysid(int i)
257{
258 return SGI_SSWAP32(sgilabel->partitions[i].id);
259}
260
261static int
262sgi_get_bootpartition(void)
263{
264 return SGI_SSWAP16(sgilabel->boot_part);
265}
266
267static int
268sgi_get_swappartition(void)
269{
270 return SGI_SSWAP16(sgilabel->swap_part);
271}
272
273static void
274sgi_list_table(int xtra)
275{
276 int i, w, wd;
277 int kpi = 0; /* kernel partition ID */
278
279 if(xtra) {
280 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
281 "%d cylinders, %d physical cylinders\n"
282 "%d extra sects/cyl, interleave %d:1\n"
283 "%s\n"
284 "Units = %s of %d * 512 bytes\n\n"),
285 disk_device, heads, sectors, cylinders,
286 SGI_SSWAP16(sgiparam.pcylcount),
287 SGI_SSWAP16(sgiparam.sparecyl),
288 SGI_SSWAP16(sgiparam.ilfact),
289 (char *)sgilabel,
290 str_units(PLURAL), units_per_sector);
291 } else {
292 printf( _("\nDisk %s (SGI disk label): "
293 "%d heads, %d sectors, %d cylinders\n"
294 "Units = %s of %d * 512 bytes\n\n"),
295 disk_device, heads, sectors, cylinders,
296 str_units(PLURAL), units_per_sector );
297 }
298
299 w = strlen(disk_device);
300 wd = strlen(_("Device"));
301 if (w < wd)
302 w = wd;
303
304 printf(_("----- partitions -----\n"
305 "Pt# %*s Info Start End Sectors Id System\n"),
306 w + 2, _("Device"));
307 for (i = 0 ; i < partitions; i++) {
308 if( sgi_get_num_sectors(i) || debug ) {
309 uint32_t start = sgi_get_start_sector(i);
310 uint32_t len = sgi_get_num_sectors(i);
311 kpi++; /* only count nonempty partitions */
312 printf(
313 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
314/* fdisk part number */ i+1,
315/* device */ partname(disk_device, kpi, w+3),
316/* flags */ (sgi_get_swappartition() == i) ? "swap" :
317/* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
318/* start */ (long) scround(start),
319/* end */ (long) scround(start+len)-1,
320/* no odd flag on end */(long) len,
321/* type id */ sgi_get_sysid(i),
322/* type name */ partition_type(sgi_get_sysid(i)));
323 }
324 }
325 printf(_("----- Bootinfo -----\nBootfile: %s\n"
326 "----- Directory Entries -----\n"),
327 sgilabel->boot_file);
328 for (i = 0 ; i < sgi_volumes; i++) {
329 if (sgilabel->directory[i].vol_file_size) {
330 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
331 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
332 unsigned char *name = sgilabel->directory[i].vol_file_name;
333
334 printf(_("%2d: %-10s sector%5u size%8u\n"),
335 i, (char*)name, (unsigned int) start, (unsigned int) len);
336 }
337 }
338}
339
340static void
341sgi_set_bootpartition(int i)
342{
343 sgilabel->boot_part = SGI_SSWAP16(((short)i));
344}
345
346static unsigned int
347sgi_get_lastblock(void)
348{
349 return heads * sectors * cylinders;
350}
351
352static void
353sgi_set_swappartition(int i)
354{
355 sgilabel->swap_part = SGI_SSWAP16(((short)i));
356}
357
358static int
359sgi_check_bootfile(const char* aFile)
360{
361 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
362 printf(_("\nInvalid Bootfile!\n"
363 "\tThe bootfile must be an absolute non-zero pathname,\n"
364 "\te.g. \"/unix\" or \"/unix.save\".\n"));
365 return 0;
366 } else {
367 if (strlen(aFile) > 16) {
368 printf(_("\n\tName of Bootfile too long: "
369 "16 bytes maximum.\n"));
370 return 0;
371 } else {
372 if (aFile[0] != '/') {
373 printf(_("\n\tBootfile must have a "
374 "fully qualified pathname.\n"));
375 return 0;
376 }
377 }
378 }
379 if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
380 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
381 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
382 /* filename is correct and did change */
383 return 1;
384 }
385 return 0; /* filename did not change */
386}
387
388static const char *
389sgi_get_bootfile(void)
390{
391 return (char*)sgilabel->boot_file;
392}
393
394static void
395sgi_set_bootfile(const char* aFile)
396{
397 int i = 0;
398
399 if (sgi_check_bootfile(aFile)) {
400 while (i < 16) {
401 if ((aFile[i] != '\n') /* in principle caught again by next line */
402 && (strlen(aFile) > i))
403 sgilabel->boot_file[i] = aFile[i];
404 else
405 sgilabel->boot_file[i] = 0;
406 i++;
407 }
408 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
409 }
410}
411
412static void
413create_sgiinfo(void)
414{
415 /* I keep SGI's habit to write the sgilabel to the second block */
416 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
417 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
418 strncpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8);
419}
420
421static sgiinfo *fill_sgiinfo(void);
422
423static void
424sgi_write_table(void)
425{
426 sgilabel->csum = 0;
427 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
428 (unsigned int*)sgilabel, sizeof(*sgilabel)));
429 assert(two_s_complement_32bit_sum(
430 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
431
432 if (lseek(fd, 0, SEEK_SET) < 0)
433 fdisk_fatal(unable_to_seek);
434 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
435 fdisk_fatal(unable_to_write);
436 if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
437 /*
438 * keep this habit of first writing the "sgilabel".
439 * I never tested whether it works without (AN 981002).
440 */
441 sgiinfo *info = fill_sgiinfo();
442 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
443 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
444 fdisk_fatal(unable_to_seek);
445 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
446 fdisk_fatal(unable_to_write);
447 free(info);
448 }
449}
450
451static int
452compare_start(int *x, int *y)
453{
454 /*
455 * sort according to start sectors
456 * and prefers largest partition:
457 * entry zero is entire disk entry
458 */
459 unsigned int i = *x;
460 unsigned int j = *y;
461 unsigned int a = sgi_get_start_sector(i);
462 unsigned int b = sgi_get_start_sector(j);
463 unsigned int c = sgi_get_num_sectors(i);
464 unsigned int d = sgi_get_num_sectors(j);
465
466 if (a == b)
467 return (d > c) ? 1 : (d == c) ? 0 : -1;
468 return (a > b) ? 1 : -1;
469}
470
471
472static int
473verify_sgi(int verbose)
474{
475 int Index[16]; /* list of valid partitions */
476 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
477 int entire = 0, i = 0;
478 unsigned int start = 0;
479 long long gap = 0; /* count unused blocks */
480 unsigned int lastblock = sgi_get_lastblock();
481
482 clearfreelist();
483 for (i = 0; i < 16; i++) {
484 if (sgi_get_num_sectors(i) != 0) {
485 Index[sortcount++] = i;
486 if (sgi_get_sysid(i) == SGI_ENTIRE_DISK) {
487 if (entire++ == 1) {
488 if (verbose)
489 printf(_("More than one entire disk entry present.\n"));
490 }
491 }
492 }
493 }
494 if (sortcount == 0) {
495 if (verbose)
496 printf(_("No partitions defined\n"));
497 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
498 }
499 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
500 if (sgi_get_sysid(Index[0]) == SGI_ENTIRE_DISK) {
501 if ((Index[0] != 10) && verbose)
502 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
503 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
504 printf(_("The entire disk partition should start "
505 "at block 0,\n"
506 "not at diskblock %d.\n"),
507 sgi_get_start_sector(Index[0]));
508 if (debug) /* I do not understand how some disks fulfil it */
509 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
510 printf(_("The entire disk partition is only %d diskblock large,\n"
511 "but the disk is %d diskblocks long.\n"),
512 sgi_get_num_sectors(Index[0]), lastblock);
513 lastblock = sgi_get_num_sectors(Index[0]);
514 } else {
515 if (verbose)
516 printf(_("One Partition (#11) should cover the entire disk.\n"));
517 if (debug > 2)
518 printf("sysid=%d\tpartition=%d\n",
519 sgi_get_sysid(Index[0]), Index[0]+1);
520 }
521 for (i = 1, start = 0; i < sortcount; i++) {
522 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
523
524 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
525 if (debug) /* I do not understand how some disks fulfil it */
526 if (verbose)
527 printf(_("Partition %d does not start on cylinder boundary.\n"),
528 Index[i]+1);
529 }
530 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
531 if (debug) /* I do not understand how some disks fulfil it */
532 if (verbose)
533 printf(_("Partition %d does not end on cylinder boundary.\n"),
534 Index[i]+1);
535 }
536 /* We cannot handle several "entire disk" entries. */
537 if (sgi_get_sysid(Index[i]) == SGI_ENTIRE_DISK) continue;
538 if (start > sgi_get_start_sector(Index[i])) {
539 if (verbose)
540 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
541 Index[i-1]+1, Index[i]+1,
542 start - sgi_get_start_sector(Index[i]));
543 if (gap > 0) gap = -gap;
544 if (gap == 0) gap = -1;
545 }
546 if (start < sgi_get_start_sector(Index[i])) {
547 if (verbose)
548 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
549 sgi_get_start_sector(Index[i]) - start,
550 start, sgi_get_start_sector(Index[i])-1);
551 gap += sgi_get_start_sector(Index[i]) - start;
552 add2freelist(start, sgi_get_start_sector(Index[i]));
553 }
554 start = sgi_get_start_sector(Index[i])
555 + sgi_get_num_sectors(Index[i]);
556 if (debug > 1) {
557 if (verbose)
558 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
559 sgi_get_start_sector(Index[i]),
560 sgi_get_num_sectors(Index[i]),
561 sgi_get_sysid(Index[i]));
562 }
563 }
564 if (start < lastblock) {
565 if (verbose)
566 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
567 lastblock - start, start, lastblock-1);
568 gap += lastblock - start;
569 add2freelist(start, lastblock);
570 }
571 /*
572 * Done with arithmetics
573 * Go for details now
574 */
575 if (verbose) {
576 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
577 printf(_("\nThe boot partition does not exist.\n"));
578 }
579 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
580 printf(_("\nThe swap partition does not exist.\n"));
581 } else {
582 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
583 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
584 printf(_("\nThe swap partition has no swap type.\n"));
585 }
586 if (sgi_check_bootfile("/unix"))
587 printf(_("\tYou have chosen an unusual boot file name.\n"));
588 }
589 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
590}
591
592static int
593sgi_gaps(void)
594{
595 /*
596 * returned value is:
597 * = 0 : disk is properly filled to the rim
598 * < 0 : there is an overlap
599 * > 0 : there is still some vacant space
600 */
601 return verify_sgi(0);
602}
603
604static void
605sgi_change_sysid(int i, int sys)
606{
607 if( sgi_get_num_sectors(i) == 0 ) { /* caught already before, ... */
608 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
609 return;
610 }
611 if (((sys != SGI_ENTIRE_DISK) && (sys != SGI_VOLHDR))
612 && (sgi_get_start_sector(i) < 1) ) {
613 read_maybe_empty(
614 _("It is highly recommended that the partition at offset 0\n"
615 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
616 "retrieve from its directory standalone tools like sash and fx.\n"
617 "Only the \"SGI volume\" entire disk section may violate this.\n"
618 "Type YES if you are sure about tagging this partition differently.\n"));
619 if (strcmp(line_ptr, _("YES\n")))
620 return;
621 }
622 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
623}
624
625/* returns partition index of first entry marked as entire disk */
626static int
627sgi_entire(void)
628{
629 int i;
630
631 for (i = 0; i < 16; i++)
632 if (sgi_get_sysid(i) == SGI_VOLUME)
633 return i;
634 return -1;
635}
636
637static void
638sgi_set_partition(int i, unsigned int start, unsigned int length, int sys)
639{
640 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
641 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
642 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
643 set_changed(i);
644 if (sgi_gaps() < 0) /* rebuild freelist */
645 printf(_("Do You know, You got a partition overlap on the disk?\n"));
646}
647
648static void
649sgi_set_entire(void)
650{
651 int n;
652
653 for (n = 10; n < partitions; n++) {
654 if(!sgi_get_num_sectors(n) ) {
655 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
656 break;
657 }
658 }
659}
660
661static void
662sgi_set_volhdr(void)
663{
664 int n;
665
666 for (n = 8; n < partitions; n++) {
667 if (!sgi_get_num_sectors(n)) {
668 /*
669 * 5 cylinders is an arbitrary value I like
670 * IRIX 5.3 stored files in the volume header
671 * (like sash, symmon, fx, ide) with ca. 3200
672 * sectors.
673 */
674 if (heads * sectors * 5 < sgi_get_lastblock())
675 sgi_set_partition(n, 0, heads * sectors * 5, SGI_VOLHDR);
676 break;
677 }
678 }
679}
680
681static void
682sgi_delete_partition(int i)
683{
684 sgi_set_partition(i, 0, 0, 0);
685}
686
687static void
688sgi_add_partition(int n, int sys)
689{
690 char mesg[256];
691 unsigned int first = 0, last = 0;
692
693 if (n == 10) {
694 sys = SGI_VOLUME;
695 } else if (n == 8) {
696 sys = 0;
697 }
698 if(sgi_get_num_sectors(n)) {
699 printf(_("Partition %d is already defined. Delete "
700 "it before re-adding it.\n"), n + 1);
701 return;
702 }
703 if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) {
704 printf(_("Attempting to generate entire disk entry automatically.\n"));
705 sgi_set_entire();
706 sgi_set_volhdr();
707 }
708 if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
709 printf(_("The entire disk is already covered with partitions.\n"));
710 return;
711 }
712 if (sgi_gaps() < 0) {
713 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
714 return;
715 }
716 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
717 while (1) {
718 if(sys == SGI_VOLUME) {
719 last = sgi_get_lastblock();
720 first = read_int(0, 0, last-1, 0, mesg);
721 if (first != 0) {
722 printf(_("It is highly recommended that eleventh partition\n"
723 "covers the entire disk and is of type `SGI volume'\n"));
724 }
725 } else {
726 first = freelist[0].first;
727 last = freelist[0].last;
728 first = read_int(scround(first), scround(first), scround(last)-1,
729 0, mesg);
730 }
731 if (display_in_cyl_units)
732 first *= units_per_sector;
733 else
734 first = first; /* align to cylinder if you know how ... */
735 if(!last )
736 last = isinfreelist(first);
737 if(last == 0) {
738 printf(_("You will get a partition overlap on the disk. "
739 "Fix it first!\n"));
740 } else
741 break;
742 }
743 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
744 last = read_int(scround(first), scround(last)-1, scround(last)-1,
745 scround(first), mesg)+1;
746 if (display_in_cyl_units)
747 last *= units_per_sector;
748 else
749 last = last; /* align to cylinder if You know how ... */
750 if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
751 printf(_("It is highly recommended that eleventh partition\n"
752 "covers the entire disk and is of type `SGI volume'\n"));
753 sgi_set_partition(n, first, last-first, sys);
754}
755
756#ifdef CONFIG_FEATURE_FDISK_ADVANCED
757static void
758create_sgilabel(void)
759{
760 struct hd_geometry geometry;
761 struct {
762 unsigned int start;
763 unsigned int nsect;
764 int sysid;
765 } old[4];
766 int i = 0;
767 long longsectors; /* the number of sectors on the device */
768 int res; /* the result from the ioctl */
769 int sec_fac; /* the sector factor */
770
771 sec_fac = sector_size / 512; /* determine the sector factor */
772
773 fprintf( stderr,
774 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
775 "until you decide to write them. After that, of course, the previous\n"
776 "content will be unrecoverably lost.\n\n"));
777
778 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
779 res = ioctl(fd, BLKGETSIZE, &longsectors);
780 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
781 heads = geometry.heads;
782 sectors = geometry.sectors;
783 if (res == 0) {
784 /* the get device size ioctl was successful */
785 cylinders = longsectors / (heads * sectors);
786 cylinders /= sec_fac;
787 } else {
788 /* otherwise print error and use truncated version */
789 cylinders = geometry.cylinders;
790 fprintf(stderr,
791 _("Warning: BLKGETSIZE ioctl failed on %s. "
792 "Using geometry cylinder value of %d.\n"
793 "This value may be truncated for devices"
794 " > 33.8 GB.\n"), disk_device, cylinders);
795 }
796 }
797 for (i = 0; i < 4; i++) {
798 old[i].sysid = 0;
799 if (valid_part_table_flag(MBRbuffer)) {
800 if(get_part_table(i)->sys_ind) {
801 old[i].sysid = get_part_table(i)->sys_ind;
802 old[i].start = get_start_sect(get_part_table(i));
803 old[i].nsect = get_nr_sects(get_part_table(i));
804 printf(_("Trying to keep parameters of partition %d.\n"), i);
805 if (debug)
806 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
807 old[i].sysid, old[i].start, old[i].nsect);
808 }
809 }
810 }
811
812 memset(MBRbuffer, 0, sizeof(MBRbuffer));
813 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
814 sgilabel->boot_part = SGI_SSWAP16(0);
815 sgilabel->swap_part = SGI_SSWAP16(1);
816
817 /* sizeof(sgilabel->boot_file) = 16 > 6 */
818 memset(sgilabel->boot_file, 0, 16);
819 strcpy((char*)sgilabel->boot_file, "/unix");
820
821 sgilabel->devparam.skew = (0);
822 sgilabel->devparam.gap1 = (0);
823 sgilabel->devparam.gap2 = (0);
824 sgilabel->devparam.sparecyl = (0);
825 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
826 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
827 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
828 /* tracks/cylinder (heads) */
829 sgilabel->devparam.cmd_tag_queue_depth = (0);
830 sgilabel->devparam.unused0 = (0);
831 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
832 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
833 /* sectors/track */
834 sgilabel->devparam.bytes = SGI_SSWAP16(512);
835 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
836 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
837 IGNORE_ERRORS|RESEEK);
838 sgilabel->devparam.datarate = SGI_SSWAP32(0);
839 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
840 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
841 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
842 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
843 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
844 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
845 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
846 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
847 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
848 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partinfo)*16 );
849 current_label_type = label_sgi;
850 partitions = 16;
851 sgi_volumes = 15;
852 sgi_set_entire();
853 sgi_set_volhdr();
854 for (i = 0; i < 4; i++) {
855 if(old[i].sysid) {
856 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
857 }
858 }
859}
860
861static void
862sgi_set_xcyl(void)
863{
864 /* do nothing in the beginning */
865}
866#endif /* CONFIG_FEATURE_FDISK_ADVANCED */
867
868/* _____________________________________________________________
869 */
870
871static sgiinfo *
872fill_sgiinfo(void)
873{
874 sgiinfo *info = calloc(1, sizeof(sgiinfo));
875
876 info->magic = SGI_SSWAP32(SGI_INFO_MAGIC);
877 info->b1 = SGI_SSWAP32(-1);
878 info->b2 = SGI_SSWAP16(-1);
879 info->b3 = SGI_SSWAP16(1);
880 /* You may want to replace this string !!!!!!! */
881 strcpy( (char*)info->scsi_string, "IBM OEM 0662S12 3 30" );
882 strcpy( (char*)info->serial, "0000" );
883 info->check1816 = SGI_SSWAP16(18*256 +16 );
884 strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" );
885 return info;
886}
887#endif /* SGI_LABEL */
diff --git a/util-linux/fdisk_sun.c b/util-linux/fdisk_sun.c
new file mode 100644
index 000000000..6973fbf30
--- /dev/null
+++ b/util-linux/fdisk_sun.c
@@ -0,0 +1,731 @@
1#ifdef CONFIG_FEATURE_SUN_LABEL
2
3#define SUN_LABEL_MAGIC 0xDABE
4#define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
5#define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
6 : (uint16_t)(x))
7#define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
8 : (uint32_t)(x))
9
10/* Copied from linux/major.h */
11#define FLOPPY_MAJOR 2
12
13#define SCSI_IOCTL_GET_IDLUN 0x5382
14
15/*
16 * fdisksunlabel.c
17 *
18 * I think this is mostly, or entirely, due to
19 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
20 *
21 * Merged with fdisk for other architectures, aeb, June 1998.
22 *
23 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
24 * Internationalization
25 */
26
27
28static int sun_other_endian;
29static int scsi_disk;
30static int floppy;
31
32#ifndef IDE0_MAJOR
33#define IDE0_MAJOR 3
34#endif
35#ifndef IDE1_MAJOR
36#define IDE1_MAJOR 22
37#endif
38
39static void
40guess_device_type(void)
41{
42 struct stat bootstat;
43
44 if (fstat(fd, &bootstat) < 0) {
45 scsi_disk = 0;
46 floppy = 0;
47 } else if (S_ISBLK(bootstat.st_mode)
48 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
49 major(bootstat.st_rdev) == IDE1_MAJOR)) {
50 scsi_disk = 0;
51 floppy = 0;
52 } else if (S_ISBLK(bootstat.st_mode)
53 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
54 scsi_disk = 0;
55 floppy = 1;
56 } else {
57 scsi_disk = 1;
58 floppy = 0;
59 }
60}
61
62static const struct systypes sun_sys_types[] = {
63 { "\x00" "Empty" }, /* 0 */
64 { "\x01" "Boot" }, /* 1 */
65 { "\x02" "SunOS root" }, /* 2 */
66 { "\x03" "SunOS swap" }, /* SUNOS_SWAP */
67 { "\x04" "SunOS usr" }, /* 4 */
68 { "\x05" "Whole disk" }, /* SUN_WHOLE_DISK */
69 { "\x06" "SunOS stand" }, /* 6 */
70 { "\x07" "SunOS var" }, /* 7 */
71 { "\x08" "SunOS home" }, /* 8 */
72 { "\x82" "Linux swap" }, /* LINUX_SWAP */
73 { "\x83" "Linux native" }, /* LINUX_NATIVE */
74 { "\x8e" "Linux LVM" }, /* 0x8e */
75/* New (2.2.x) raid partition with autodetect using persistent superblock */
76 { "\xfd" "Linux raid autodetect" }, /* 0xfd */
77 { NULL }
78};
79
80
81static void
82set_sun_partition(int i, uint start, uint stop, int sysid)
83{
84 sunlabel->infos[i].id = sysid;
85 sunlabel->partitions[i].start_cylinder =
86 SUN_SSWAP32(start / (heads * sectors));
87 sunlabel->partitions[i].num_sectors =
88 SUN_SSWAP32(stop - start);
89 set_changed(i);
90}
91
92static int
93check_sun_label(void)
94{
95 unsigned short *ush;
96 int csum;
97
98 if (sunlabel->magic != SUN_LABEL_MAGIC
99 && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
100 current_label_type = label_dos;
101 sun_other_endian = 0;
102 return 0;
103 }
104 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
105 ush = ((unsigned short *) (sunlabel + 1)) - 1;
106 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
107 if (csum) {
108 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
109 "Probably you'll have to set all the values,\n"
110 "e.g. heads, sectors, cylinders and partitions\n"
111 "or force a fresh label (s command in main menu)\n"));
112 } else {
113 heads = SUN_SSWAP16(sunlabel->ntrks);
114 cylinders = SUN_SSWAP16(sunlabel->ncyl);
115 sectors = SUN_SSWAP16(sunlabel->nsect);
116 }
117 update_units();
118 current_label_type = label_sun;
119 partitions = 8;
120 return 1;
121}
122
123static const struct sun_predefined_drives {
124 const char *vendor;
125 const char *model;
126 unsigned short sparecyl;
127 unsigned short ncyl;
128 unsigned short nacyl;
129 unsigned short pcylcount;
130 unsigned short ntrks;
131 unsigned short nsect;
132 unsigned short rspeed;
133} sun_drives[] = {
134 { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
135 { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
136 { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
137 { "IBM","DPES-31080",0,4901,2,4903,4,108,5400},
138 { "IBM","DORS-32160",0,1015,2,1017,67,62,5400},
139 { "IBM","DNES-318350",0,11199,2,11474,10,320,7200},
140 { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
141 { "","SUN0104",1,974,2,1019,6,35,3662},
142 { "","SUN0207",4,1254,2,1272,9,36,3600},
143 { "","SUN0327",3,1545,2,1549,9,46,3600},
144 { "","SUN0340",0,1538,2,1544,6,72,4200},
145 { "","SUN0424",2,1151,2,2500,9,80,4400},
146 { "","SUN0535",0,1866,2,2500,7,80,5400},
147 { "","SUN0669",5,1614,2,1632,15,54,3600},
148 { "","SUN1.0G",5,1703,2,1931,15,80,3597},
149 { "","SUN1.05",0,2036,2,2038,14,72,5400},
150 { "","SUN1.3G",6,1965,2,3500,17,80,5400},
151 { "","SUN2.1G",0,2733,2,3500,19,80,5400},
152 { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
153};
154
155static const struct sun_predefined_drives *
156sun_autoconfigure_scsi(void)
157{
158 const struct sun_predefined_drives *p = NULL;
159
160#ifdef SCSI_IOCTL_GET_IDLUN
161 unsigned int id[2];
162 char buffer[2048];
163 char buffer2[2048];
164 FILE *pfd;
165 char *vendor;
166 char *model;
167 char *q;
168 int i;
169
170 if (ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id))
171 return NULL;
172
173 sprintf(buffer,
174 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
175 /* This is very wrong (works only if you have one HBA),
176 but I haven't found a way how to get hostno
177 from the current kernel */
178 0,
179 (id[0]>>16) & 0xff,
180 id[0] & 0xff,
181 (id[0]>>8) & 0xff
182 );
183 pfd = fopen("/proc/scsi/scsi", "r");
184 if (!pfd) {
185 return NULL;
186 }
187 while (fgets(buffer2, 2048, pfd)) {
188 if (strcmp(buffer, buffer2))
189 continue;
190 if (!fgets(buffer2, 2048, pfd))
191 break;
192 q = strstr(buffer2, "Vendor: ");
193 if (!q)
194 break;
195 q += 8;
196 vendor = q;
197 q = strstr(q, " ");
198 *q++ = '\0'; /* truncate vendor name */
199 q = strstr(q, "Model: ");
200 if (!q)
201 break;
202 *q = '\0';
203 q += 7;
204 model = q;
205 q = strstr(q, " Rev: ");
206 if (!q)
207 break;
208 *q = '\0';
209 for (i = 0; i < SIZE(sun_drives); i++) {
210 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
211 continue;
212 if (!strstr(model, sun_drives[i].model))
213 continue;
214 printf(_("Autoconfigure found a %s%s%s\n"),
215 sun_drives[i].vendor,
216 (*sun_drives[i].vendor) ? " " : "",
217 sun_drives[i].model);
218 p = sun_drives + i;
219 break;
220 }
221 break;
222 }
223 fclose(pfd);
224#endif
225 return p;
226}
227
228static void
229create_sunlabel(void)
230{
231 struct hd_geometry geometry;
232 unsigned int ndiv;
233 int i;
234 unsigned char c;
235 const struct sun_predefined_drives *p = NULL;
236
237 fprintf(stderr,
238 _("Building a new sun disklabel. Changes will remain in memory only,\n"
239 "until you decide to write them. After that, of course, the previous\n"
240 "content won't be recoverable.\n\n"));
241 sun_other_endian = BB_LITTLE_ENDIAN;
242 memset(MBRbuffer, 0, sizeof(MBRbuffer));
243 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
244 if (!floppy) {
245 puts(_("Drive type\n"
246 " ? auto configure\n"
247 " 0 custom (with hardware detected defaults)"));
248 for (i = 0; i < SIZE(sun_drives); i++) {
249 printf(" %c %s%s%s\n",
250 i + 'a', sun_drives[i].vendor,
251 (*sun_drives[i].vendor) ? " " : "",
252 sun_drives[i].model);
253 }
254 while (1) {
255 c = read_nonempty(_("Select type (? for auto, 0 for custom): "));
256 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
257 p = sun_drives + c - 'a';
258 break;
259 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
260 p = sun_drives + c - 'A';
261 break;
262 } else if (c == '0') {
263 break;
264 } else if (c == '?' && scsi_disk) {
265 p = sun_autoconfigure_scsi();
266 if (!p)
267 printf(_("Autoconfigure failed.\n"));
268 else
269 break;
270 }
271 }
272 }
273 if (!p || floppy) {
274 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
275 heads = geometry.heads;
276 sectors = geometry.sectors;
277 cylinders = geometry.cylinders;
278 } else {
279 heads = 0;
280 sectors = 0;
281 cylinders = 0;
282 }
283 if (floppy) {
284 sunlabel->nacyl = 0;
285 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
286 sunlabel->rspeed = SUN_SSWAP16(300);
287 sunlabel->ilfact = SUN_SSWAP16(1);
288 sunlabel->sparecyl = 0;
289 } else {
290 heads = read_int(1,heads,1024,0,_("Heads"));
291 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
292 if (cylinders)
293 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
294 else
295 cylinders = read_int(1,0,65535,0,_("Cylinders"));
296 sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders")));
297 sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders")));
298 sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)")));
299 sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor")));
300 sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder")));
301 }
302 } else {
303 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
304 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
305 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
306 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
307 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
308 sunlabel->nsect = SUN_SSWAP16(p->nsect);
309 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
310 sunlabel->ilfact = SUN_SSWAP16(1);
311 cylinders = p->ncyl;
312 heads = p->ntrks;
313 sectors = p->nsect;
314 puts(_("You may change all the disk params from the x menu"));
315 }
316
317 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
318 "%s%s%s cyl %d alt %d hd %d sec %d",
319 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
320 p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")),
321 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
322
323 sunlabel->ntrks = SUN_SSWAP16(heads);
324 sunlabel->nsect = SUN_SSWAP16(sectors);
325 sunlabel->ncyl = SUN_SSWAP16(cylinders);
326 if (floppy)
327 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
328 else {
329 if (cylinders * heads * sectors >= 150 * 2048) {
330 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
331 } else
332 ndiv = cylinders * 2 / 3;
333 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
334 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
335 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
336 }
337 set_sun_partition(2, 0, cylinders * heads * sectors, SUN_WHOLE_DISK);
338 {
339 unsigned short *ush = (unsigned short *)sunlabel;
340 unsigned short csum = 0;
341 while (ush < (unsigned short *)(&sunlabel->csum))
342 csum ^= *ush++;
343 sunlabel->csum = csum;
344 }
345
346 set_all_unchanged();
347 set_changed(0);
348 get_boot(create_empty_sun);
349}
350
351static void
352toggle_sunflags(int i, unsigned char mask)
353{
354 if (sunlabel->infos[i].flags & mask)
355 sunlabel->infos[i].flags &= ~mask;
356 else
357 sunlabel->infos[i].flags |= mask;
358 set_changed(i);
359}
360
361static void
362fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
363{
364 int i, continuous = 1;
365
366 *start = 0;
367 *stop = cylinders * heads * sectors;
368 for (i = 0; i < partitions; i++) {
369 if (sunlabel->partitions[i].num_sectors
370 && sunlabel->infos[i].id
371 && sunlabel->infos[i].id != SUN_WHOLE_DISK) {
372 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
373 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
374 if (continuous) {
375 if (starts[i] == *start)
376 *start += lens[i];
377 else if (starts[i] + lens[i] >= *stop)
378 *stop = starts[i];
379 else
380 continuous = 0;
381 /* There will be probably more gaps
382 than one, so lets check afterwards */
383 }
384 } else {
385 starts[i] = 0;
386 lens[i] = 0;
387 }
388 }
389}
390
391static uint *verify_sun_starts;
392
393static int
394verify_sun_cmp(int *a, int *b)
395{
396 if (*a == -1) return 1;
397 if (*b == -1) return -1;
398 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
399 return -1;
400}
401
402static void
403verify_sun(void)
404{
405 uint starts[8], lens[8], start, stop;
406 int i,j,k,starto,endo;
407 int array[8];
408
409 verify_sun_starts = starts;
410 fetch_sun(starts,lens,&start,&stop);
411 for (k = 0; k < 7; k++) {
412 for (i = 0; i < 8; i++) {
413 if (k && (lens[i] % (heads * sectors))) {
414 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
415 }
416 if (lens[i]) {
417 for (j = 0; j < i; j++)
418 if (lens[j]) {
419 if (starts[j] == starts[i]+lens[i]) {
420 starts[j] = starts[i]; lens[j] += lens[i];
421 lens[i] = 0;
422 } else if (starts[i] == starts[j]+lens[j]){
423 lens[j] += lens[i];
424 lens[i] = 0;
425 } else if (!k) {
426 if (starts[i] < starts[j]+lens[j]
427 && starts[j] < starts[i]+lens[i]) {
428 starto = starts[i];
429 if (starts[j] > starto)
430 starto = starts[j];
431 endo = starts[i]+lens[i];
432 if (starts[j]+lens[j] < endo)
433 endo = starts[j]+lens[j];
434 printf(_("Partition %d overlaps with others in "
435 "sectors %d-%d\n"), i+1, starto, endo);
436 }
437 }
438 }
439 }
440 }
441 }
442 for (i = 0; i < 8; i++) {
443 if (lens[i])
444 array[i] = i;
445 else
446 array[i] = -1;
447 }
448 qsort(array,SIZE(array),sizeof(array[0]),
449 (int (*)(const void *,const void *)) verify_sun_cmp);
450 if (array[0] == -1) {
451 printf(_("No partitions defined\n"));
452 return;
453 }
454 stop = cylinders * heads * sectors;
455 if (starts[array[0]])
456 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
457 for (i = 0; i < 7 && array[i+1] != -1; i++) {
458 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
459 }
460 start = starts[array[i]] + lens[array[i]];
461 if (start < stop)
462 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
463}
464
465static void
466add_sun_partition(int n, int sys)
467{
468 uint start, stop, stop2;
469 uint starts[8], lens[8];
470 int whole_disk = 0;
471
472 char mesg[256];
473 int i, first, last;
474
475 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
476 printf(_("Partition %d is already defined. Delete "
477 "it before re-adding it.\n"), n + 1);
478 return;
479 }
480
481 fetch_sun(starts,lens,&start,&stop);
482 if (stop <= start) {
483 if (n == 2)
484 whole_disk = 1;
485 else {
486 printf(_("Other partitions already cover the whole disk.\nDelete "
487 "some/shrink them before retry.\n"));
488 return;
489 }
490 }
491 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
492 while (1) {
493 if (whole_disk)
494 first = read_int(0, 0, 0, 0, mesg);
495 else
496 first = read_int(scround(start), scround(stop)+1,
497 scround(stop), 0, mesg);
498 if (display_in_cyl_units)
499 first *= units_per_sector;
500 else
501 /* Starting sector has to be properly aligned */
502 first = (first + heads * sectors - 1) / (heads * sectors);
503 if (n == 2 && first != 0)
504 printf("\
505It is highly recommended that the third partition covers the whole disk\n\
506and is of type `Whole disk'\n");
507 /* ewt asks to add: "don't start a partition at cyl 0"
508 However, edmundo@rano.demon.co.uk writes:
509 "In addition to having a Sun partition table, to be able to
510 boot from the disc, the first partition, /dev/sdX1, must
511 start at cylinder 0. This means that /dev/sdX1 contains
512 the partition table and the boot block, as these are the
513 first two sectors of the disc. Therefore you must be
514 careful what you use /dev/sdX1 for. In particular, you must
515 not use a partition starting at cylinder 0 for Linux swap,
516 as that would overwrite the partition table and the boot
517 block. You may, however, use such a partition for a UFS
518 or EXT2 file system, as these file systems leave the first
519 1024 bytes undisturbed. */
520 /* On the other hand, one should not use partitions
521 starting at block 0 in an md, or the label will
522 be trashed. */
523 for (i = 0; i < partitions; i++)
524 if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
525 break;
526 if (i < partitions && !whole_disk) {
527 if (n == 2 && !first) {
528 whole_disk = 1;
529 break;
530 }
531 printf(_("Sector %d is already allocated\n"), first);
532 } else
533 break;
534 }
535 stop = cylinders * heads * sectors;
536 stop2 = stop;
537 for (i = 0; i < partitions; i++) {
538 if (starts[i] > first && starts[i] < stop)
539 stop = starts[i];
540 }
541 snprintf(mesg, sizeof(mesg),
542 _("Last %s or +size or +sizeM or +sizeK"),
543 str_units(SINGULAR));
544 if (whole_disk)
545 last = read_int(scround(stop2), scround(stop2), scround(stop2),
546 0, mesg);
547 else if (n == 2 && !first)
548 last = read_int(scround(first), scround(stop2), scround(stop2),
549 scround(first), mesg);
550 else
551 last = read_int(scround(first), scround(stop), scround(stop),
552 scround(first), mesg);
553 if (display_in_cyl_units)
554 last *= units_per_sector;
555 if (n == 2 && !first) {
556 if (last >= stop2) {
557 whole_disk = 1;
558 last = stop2;
559 } else if (last > stop) {
560 printf(_("You haven't covered the whole disk with "
561 "the 3rd partition, but your value\n"
562 "%d %s covers some other partition. "
563 "Your entry has been changed\n"
564 "to %d %s\n"),
565 scround(last), str_units(SINGULAR),
566 scround(stop), str_units(SINGULAR));
567 last = stop;
568 }
569 } else if (!whole_disk && last > stop)
570 last = stop;
571
572 if (whole_disk)
573 sys = SUN_WHOLE_DISK;
574 set_sun_partition(n, first, last, sys);
575}
576
577static void
578sun_delete_partition(int i)
579{
580 unsigned int nsec;
581
582 if (i == 2
583 && sunlabel->infos[i].id == SUN_WHOLE_DISK
584 && !sunlabel->partitions[i].start_cylinder
585 && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
586 printf(_("If you want to maintain SunOS/Solaris compatibility, "
587 "consider leaving this\n"
588 "partition as Whole disk (5), starting at 0, with %u "
589 "sectors\n"), nsec);
590 sunlabel->infos[i].id = 0;
591 sunlabel->partitions[i].num_sectors = 0;
592}
593
594static void
595sun_change_sysid(int i, int sys)
596{
597 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
598 read_maybe_empty(
599 _("It is highly recommended that the partition at offset 0\n"
600 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
601 "there may destroy your partition table and bootblock.\n"
602 "Type YES if you're very sure you would like that partition\n"
603 "tagged with 82 (Linux swap): "));
604 if (strcmp (line_ptr, _("YES\n")))
605 return;
606 }
607 switch (sys) {
608 case SUNOS_SWAP:
609 case LINUX_SWAP:
610 /* swaps are not mountable by default */
611 sunlabel->infos[i].flags |= 0x01;
612 break;
613 default:
614 /* assume other types are mountable;
615 user can change it anyway */
616 sunlabel->infos[i].flags &= ~0x01;
617 break;
618 }
619 sunlabel->infos[i].id = sys;
620}
621
622static void
623sun_list_table(int xtra)
624{
625 int i, w;
626
627 w = strlen(disk_device);
628 if (xtra)
629 printf(
630 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
631 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
632 "%d extra sects/cyl, interleave %d:1\n"
633 "%s\n"
634 "Units = %s of %d * 512 bytes\n\n"),
635 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
636 cylinders, SUN_SSWAP16(sunlabel->nacyl),
637 SUN_SSWAP16(sunlabel->pcylcount),
638 SUN_SSWAP16(sunlabel->sparecyl),
639 SUN_SSWAP16(sunlabel->ilfact),
640 (char *)sunlabel,
641 str_units(PLURAL), units_per_sector);
642 else
643 printf(
644 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
645 "Units = %s of %d * 512 bytes\n\n"),
646 disk_device, heads, sectors, cylinders,
647 str_units(PLURAL), units_per_sector);
648
649 printf(_("%*s Flag Start End Blocks Id System\n"),
650 w + 1, _("Device"));
651 for (i = 0 ; i < partitions; i++) {
652 if (sunlabel->partitions[i].num_sectors) {
653 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
654 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
655 printf("%s %c%c %9ld %9ld %9ld%c %2x %s\n",
656 partname(disk_device, i+1, w), /* device */
657 (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', /* flags */
658 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
659 (long) scround(start), /* start */
660 (long) scround(start+len), /* end */
661 (long) len / 2, len & 1 ? '+' : ' ', /* odd flag on end */
662 sunlabel->infos[i].id, /* type id */
663 partition_type(sunlabel->infos[i].id)); /* type name */
664 }
665 }
666}
667
668#ifdef CONFIG_FEATURE_FDISK_ADVANCED
669
670static void
671sun_set_alt_cyl(void)
672{
673 sunlabel->nacyl =
674 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
675 _("Number of alternate cylinders")));
676}
677
678static void
679sun_set_ncyl(int cyl)
680{
681 sunlabel->ncyl = SUN_SSWAP16(cyl);
682}
683
684static void
685sun_set_xcyl(void)
686{
687 sunlabel->sparecyl =
688 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
689 _("Extra sectors per cylinder")));
690}
691
692static void
693sun_set_ilfact(void)
694{
695 sunlabel->ilfact =
696 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
697 _("Interleave factor")));
698}
699
700static void
701sun_set_rspeed(void)
702{
703 sunlabel->rspeed =
704 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
705 _("Rotation speed (rpm)")));
706}
707
708static void
709sun_set_pcylcount(void)
710{
711 sunlabel->pcylcount =
712 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
713 _("Number of physical cylinders")));
714}
715#endif /* CONFIG_FEATURE_FDISK_ADVANCED */
716
717static void
718sun_write_table(void)
719{
720 unsigned short *ush = (unsigned short *)sunlabel;
721 unsigned short csum = 0;
722
723 while (ush < (unsigned short *)(&sunlabel->csum))
724 csum ^= *ush++;
725 sunlabel->csum = csum;
726 if (lseek(fd, 0, SEEK_SET) < 0)
727 fdisk_fatal(unable_to_seek);
728 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
729 fdisk_fatal(unable_to_write);
730}
731#endif /* SUN_LABEL */