summaryrefslogtreecommitdiffstats
path: root/fdisk/fdisksgilabel.c
diff options
context:
space:
mode:
Diffstat (limited to 'fdisk/fdisksgilabel.c')
-rw-r--r--fdisk/fdisksgilabel.c888
1 files changed, 888 insertions, 0 deletions
diff --git a/fdisk/fdisksgilabel.c b/fdisk/fdisksgilabel.c
new file mode 100644
index 000000000..42f7363e4
--- /dev/null
+++ b/fdisk/fdisksgilabel.c
@@ -0,0 +1,888 @@
+/*
+ *
+ * fdisksgilabel.c
+ *
+ * Copyright (C) Andreas Neuper, Sep 1998.
+ * This file may be modified and redistributed under
+ * the terms of the GNU Public License.
+ */
+#include <stdio.h> /* stderr */
+#include <stdlib.h> /* uint */
+#include <string.h> /* strstr */
+#include <unistd.h> /* write */
+#include <sys/ioctl.h> /* ioctl */
+#include <sys/stat.h> /* stat */
+#include <assert.h> /* assert */
+
+#include <endian.h>
+#include <linux/major.h> /* FLOPPY_MAJOR */
+#include <linux/hdreg.h> /* HDIO_GETGEO */
+
+#include "fdisk.h"
+#include "fdisksgilabel.h"
+
+static int other_endian = 0;
+static int debug = 0;
+static short volumes=1;
+
+/*
+ * only dealing with free blocks here
+ */
+
+typedef struct { int first; int last; } freeblocks;
+static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
+void setfreelist( int i, int f, int l ) \
+ { freelist[i].first = f; freelist[i].last = l; return; }
+void add2freelist( int f, int l ) \
+ { int i = 0; for( ; i<17 ; i++ ) { if(freelist[i].last==0) break; }\
+ setfreelist( i, f, l ); return; }
+void clearfreelist( void ) \
+ { int i = 0; for( ; i<17 ; i++ ) { setfreelist( i, 0, 0 ); } return; }
+int isinfreelist( int b ) \
+ { int i = 0; for( ; i<17 ; i++ )\
+ { if( ( freelist[i].first <= b ) && ( freelist[i].last >= b) )\
+ { return freelist[i].last; } } return 0; }
+ /* return last vacant block of this stride (never 0). */
+ /* the '>=' is not quite correct, but simplifies the code */
+/*
+ * end of free blocks section
+ */
+
+struct systypes sgi_sys_types[] = {
+ {SGI_VOLHDR, "SGI volhdr"},
+ {0x01, "SGI trkrepl"},
+ {0x02, "SGI secrepl"},
+ {SGI_SWAP, "SGI raw"},
+ {0x04, "SGI bsd"},
+ {0x05, "SGI sysv"},
+ {ENTIRE_DISK, "SGI volume"},
+ {SGI_EFS, "SGI efs"},
+ {0x08, "SGI lvol"},
+ {0x09, "SGI rlvol"},
+ {0x0A, "SGI xfs"},
+ {0x0B, "SGI xlvol"},
+ {0x0C, "SGI rxlvol"},
+ {LINUX_SWAP, "Linux swap"},
+ {LINUX_NATIVE,"Linux native"},
+ {0, NULL }
+};
+
+static inline unsigned short __swap16(unsigned short x) {
+ return (((__u16)(x) & 0xFF) << 8) | (((__u16)(x) & 0xFF00) >> 8);
+}
+static inline __u32 __swap32(__u32 x) {
+ return (((__u32)(x) & 0xFF) << 24) | (((__u32)(x) & 0xFF00) << 8) | (((__u32)(x) & 0xFF0000) >> 8) | (((__u32)(x) & 0xFF000000) >> 24);
+}
+
+static
+int
+sgi_get_nsect( void )
+{
+ return SSWAP16(sgilabel->devparam.nsect);
+}
+
+static
+int
+sgi_get_ntrks( void )
+{
+ return SSWAP16(sgilabel->devparam.ntrks);
+}
+
+#if 0
+static int
+sgi_get_head_vol0( void )
+{
+ return SSWAP16(sgilabel->devparam.head_vol0);
+}
+
+static int
+sgi_get_bytes( void )
+{
+ return SSWAP16(sgilabel->devparam.bytes);
+}
+#endif
+
+static
+int
+sgi_get_pcylcount( void )
+{
+ return SSWAP16(sgilabel->devparam.pcylcount);
+}
+
+void
+sgi_nolabel()
+{
+ sgilabel->magic = 0;
+ sgi_label = 0;
+ partitions = 4;
+}
+
+unsigned int
+two_s_complement_32bit_sum(
+ unsigned int* base,
+ int size /* in bytes */ )
+{
+ int i=0;
+ unsigned int sum=0;
+ size = size / sizeof( unsigned int );
+ for( i=0; i<size; i++ )
+ {
+ sum = sum - SSWAP32(base[i]);
+ }
+ return sum;
+}
+
+int check_sgi_label()
+{
+ if (sizeof(sgilabel) > 512) {
+ fprintf(stderr,
+ "According to MIPS Computer Systems, Inc the "
+ "Label must not contain more than 512 bytes\n");
+ exit(1);
+ }
+
+ if (sgilabel->magic != SGI_LABEL_MAGIC &&
+ sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
+ sgi_label = 0;
+ other_endian = 0;
+ return 0;
+ }
+
+ other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
+ /*
+ * test for correct checksum
+ */
+ if( two_s_complement_32bit_sum( (unsigned int*)sgilabel,
+ sizeof(*sgilabel) ) )
+ {
+ fprintf( stderr, "Detected sgi disklabel with wrong checksum.\n" );
+ } else
+ {
+ heads = sgi_get_ntrks();
+ cylinders = sgi_get_pcylcount();
+ sectors = sgi_get_nsect();
+ }
+ update_units();
+ sgi_label = 1;
+ partitions= 16;
+ volumes = 15;
+ return 1;
+}
+
+void
+sgi_list_table( int xtra )
+{
+ int i, w;
+ char *type;
+
+ w = strlen( disk_device );
+
+ if( xtra )
+ {
+ printf( "\nDisk %s (SGI disk label): %d heads, %d sectors\n"
+ "%d cylinders, %d physical cylinders\n"
+ "%d extra sects/cyl, interleave %d:1\n"
+ "%s\n"
+ "Units = %ss of %d * 512 bytes\n\n",
+ disk_device, heads, sectors, cylinders,
+ SSWAP16(sgiparam.pcylcount),
+ SSWAP16(sgiparam.sparecyl),
+ SSWAP16(sgiparam.ilfact),
+ (char *)sgilabel,
+ str_units(), display_factor);
+ } else
+ {
+ printf( "\nDisk %s (SGI disk label): %d heads, %d sectors, %d cylinders\n"
+ "Units = %ss of %d * 512 bytes\n\n",
+ disk_device, heads, sectors, cylinders,
+ str_units(), display_factor );
+ }
+ printf("----- partitions -----\n"
+ "%*s Info Start End Sectors Id System\n",
+ w + 1, "Device");
+ for (i = 0 ; i < partitions; i++)
+ {
+ if( sgi_get_num_sectors(i) || debug )
+ {
+ __u32 start = sgi_get_start_sector(i);
+ __u32 len = sgi_get_num_sectors(i);
+ printf(
+ "%*s%-2d %4s %9ld %9ld %9ld %2x %s\n",
+/* device */ w, disk_device, i + 1,
+/* flags */ (sgi_get_swappartition() == i) ? "swap" :
+/* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
+/* start */ (long) scround(start),
+/* end */ (long) scround(start+len)-1,
+/* no odd flag on end */ (long) len,
+/* type id */ sgi_get_sysid(i),
+/* type name */ (type = partition_type(sgi_get_sysid(i)))
+ ? type : "Unknown");
+ }
+ }
+ printf( "----- bootinfo -----\nBootfile: %s\n"
+ "----- directory entries -----\n",
+ sgilabel->boot_file );
+ for (i = 0 ; i < volumes; i++)
+ {
+ if (sgilabel->directory[i].vol_file_size)
+ {
+ __u32 start = SSWAP32(sgilabel->directory[i].vol_file_start);
+ __u32 len = SSWAP32(sgilabel->directory[i].vol_file_size);
+ char*name = sgilabel->directory[i].vol_file_name;
+ printf("%2d: %-10s sector%5u size%8u\n",
+ i, name, (unsigned int) start, (unsigned int) len);
+ }
+ }
+}
+
+int
+sgi_get_start_sector( int i )
+{
+ return SSWAP32(sgilabel->partitions[i].start_sector);
+}
+
+int
+sgi_get_num_sectors( int i )
+{
+ return SSWAP32(sgilabel->partitions[i].num_sectors);
+}
+
+int
+sgi_get_sysid( int i )
+{
+ return SSWAP32(sgilabel->partitions[i].id);
+}
+
+int
+sgi_get_bootpartition( void )
+{
+ return SSWAP16(sgilabel->boot_part);
+}
+
+int
+sgi_get_swappartition( void )
+{
+ return SSWAP16(sgilabel->swap_part);
+}
+
+void
+sgi_set_bootpartition( int i )
+{
+ sgilabel->boot_part = SSWAP16(((short)i));
+ return;
+}
+
+int
+sgi_get_lastblock( void )
+{
+ return heads * sectors * cylinders;
+}
+
+void
+sgi_set_swappartition( int i )
+{
+ sgilabel->swap_part = SSWAP16(((short)i));
+ return;
+}
+
+static int
+sgi_check_bootfile( const char* aFile )
+{
+ if( strlen( aFile ) < 3 ) /* "/a\n" is minimum */
+ {
+ printf( "\nInvalid Bootfile!\n"
+ "\tThe bootfile must be an absolute non-zero pathname,\n"
+ "\te.g. \"/unix\" or \"/unix.save\".\n" );
+ return 0;
+ } else
+ if( strlen( aFile ) > 16 )
+ {
+ printf( "\n\tName of Bootfile too long: 16 bytes maximum.\n" );
+ return 0;
+ } else
+ if( aFile[0] != '/' )
+ {
+ printf( "\n\tBootfile must have a fully qualified pathname.\n" );
+ return 0;
+ }
+ if( strncmp( aFile, sgilabel->boot_file, 16 ) )
+ {
+ printf( "\n\tBe aware, that the bootfile is not checked for existence.\n\t"
+ "SGI's default is \"/unix\" and for backup \"/unix.save\".\n" );
+ /* filename is correct and did change */
+ return 1;
+ }
+ return 0; /* filename did not change */
+}
+
+const char *
+sgi_get_bootfile(void) {
+ return sgilabel->boot_file;
+}
+
+void
+sgi_set_bootfile( const char* aFile )
+{
+ int i = 0;
+ if( sgi_check_bootfile( aFile ) )
+ {
+ while( i<16 )
+ {
+ if( (aFile[i] != '\n') /* in principle caught again by next line */
+ && (strlen( aFile ) > i ) )
+ sgilabel->boot_file[i] = aFile[i];
+ else
+ sgilabel->boot_file[i] = 0;
+ i++;
+ }
+ printf( "\n\tBootfile is changed to \"%s\".\n", sgilabel->boot_file );
+ }
+ return;
+}
+
+void
+create_sgiinfo( void )
+{
+ /* I keep SGI's habit to write the sgilabel to the second block */
+ sgilabel->directory[0].vol_file_start = SSWAP32( 2 );
+ sgilabel->directory[0].vol_file_size = SSWAP32( sizeof( sgiinfo ) );
+ strncpy( sgilabel->directory[0].vol_file_name, "sgilabel",8 );
+ return;
+}
+
+sgiinfo * fill_sgiinfo( void );
+
+void
+sgi_write_table( void )
+{
+ sgilabel->csum = 0;
+ sgilabel->csum = SSWAP32( two_s_complement_32bit_sum(
+ (unsigned int*)sgilabel,
+ sizeof(*sgilabel) ) );
+ assert( two_s_complement_32bit_sum(
+ (unsigned int*)sgilabel, sizeof(*sgilabel) ) == 0 );
+ if( lseek(fd, 0, SEEK_SET) < 0 )
+ fatal(unable_to_seek);
+ if( write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE )
+ fatal(unable_to_write);
+ if( ! strncmp( sgilabel->directory[0].vol_file_name, "sgilabel",8 ) )
+ {
+ /*
+ * keep this habbit of first writing the "sgilabel".
+ * I never tested whether it works without (AN 981002).
+ */
+ sgiinfo*info = fill_sgiinfo(); /* fills the block appropriately */
+ int infostartblock = SSWAP32( sgilabel->directory[0].vol_file_start );
+ if( ext2_llseek(fd, (ext2_loff_t)infostartblock*
+ SECTOR_SIZE, SEEK_SET) < 0 )
+ fatal(unable_to_seek);
+ if( write(fd, info, SECTOR_SIZE) != SECTOR_SIZE )
+ fatal(unable_to_write);
+ free( info );
+ }
+ return;
+}
+
+static
+int
+compare_start( int*x, int*y )
+{
+ /*
+ * sort according to start sectors
+ * and prefers largest partition:
+ * entry zero is entire disk entry
+ */
+ int i = *x;
+ int j = *y;
+ int a = sgi_get_start_sector(i);
+ int b = sgi_get_start_sector(j);
+ int c = sgi_get_num_sectors(i);
+ int d = sgi_get_num_sectors(j);
+ if( a == b )
+ {
+ return( d - c );
+ }
+ return( a - b );
+}
+
+static
+int
+sgi_gaps()
+{
+ /*
+ * returned value is:
+ * = 0 : disk is properly filled to the rim
+ * < 0 : there is an overlap
+ * > 0 : there is still some vacant space
+ */
+ return verify_sgi(0);
+}
+
+int
+verify_sgi( int verbose )
+{
+ int Index[16]; /* list of valid partitions */
+ int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
+ int compare_start();/* comparison function above */
+ int entire = 0, i = 0; /* local counters */
+ int start = 0;
+ int gap = 0; /* count unused blocks */
+ int lastblock = sgi_get_lastblock();
+ /*
+ */
+ clearfreelist();
+ for( i=0; i<16; i++ )
+ {
+ if( sgi_get_num_sectors(i)!=0 )
+ {
+ Index[sortcount++]=i;
+ if( sgi_get_sysid(i) == ENTIRE_DISK )
+ {
+ if( entire++ == 1 )
+ {
+ if(verbose)
+ printf("More than one entire disk entriy present.\n");
+ }
+ }
+ }
+ }
+ if( sortcount == 0 )
+ {
+ if(verbose)
+ printf("No partitions defined\n");
+ return lastblock;
+ }
+ qsort( Index, sortcount, sizeof(Index[0]), (void*)compare_start );
+ if( sgi_get_sysid( Index[0] ) == ENTIRE_DISK )
+ {
+ if( ( Index[0] != 10 ) && verbose )
+ printf( "IRIX likes when Partition 11 covers the entire disk.\n" );
+ if( ( sgi_get_start_sector( Index[0] ) != 0 ) && verbose )
+ printf( "The entire disk partition should start at block 0,\nnot "
+ "at diskblock %d.\n", sgi_get_start_sector(Index[0] ) );
+ if(debug) /* I do not understand how some disks fulfil it */
+ if( ( sgi_get_num_sectors( Index[0] ) != lastblock ) && verbose )
+ printf( "The entire disk partition is only %d diskblock large,\n"
+ "but the disk is %d diskblocks long.\n",
+ sgi_get_num_sectors( Index[0] ), lastblock );
+ lastblock = sgi_get_num_sectors( Index[0] );
+ } else
+ {
+ if( verbose )
+ printf( "One Partition (#11) should cover the entire disk.\n" );
+ if(debug>2)
+ printf( "sysid=%d\tpartition=%d\n",
+ sgi_get_sysid( Index[0] ), Index[0]+1 );
+ }
+ for( i=1, start=0; i<sortcount; i++ )
+ {
+ int cylsize = sgi_get_nsect() * sgi_get_ntrks();
+ if( (sgi_get_start_sector( Index[i] ) % cylsize) != 0 )
+ {
+ if(debug) /* I do not understand how some disks fulfil it */
+ if( verbose )
+ printf( "Partition %d does not start on cylinder boundary.\n",
+ Index[i]+1 );
+ }
+ if( sgi_get_num_sectors( Index[i] ) % cylsize != 0 )
+ {
+ if(debug) /* I do not understand how some disks fulfil it */
+ if( verbose )
+ printf( "Partition %d does not end on cylinder boundary.\n",
+ Index[i]+1 );
+ }
+ /* We cannot handle several "entire disk" entries. */
+ if( sgi_get_sysid( Index[i] ) == ENTIRE_DISK ) continue;
+ if( start > sgi_get_start_sector( Index[i] ) )
+ {
+ if( verbose )
+ printf( "The Partition %d and %d overlap by %d sectors.\n",
+ Index[i-1]+1, Index[i]+1,
+ start - sgi_get_start_sector( Index[i] ) );
+ if( gap > 0 ) gap = -gap;
+ if( gap == 0 ) gap = -1;
+ }
+ if( start < sgi_get_start_sector( Index[i] ) )
+ {
+ if( verbose )
+ printf( "Unused gap of %8d sectors - sectors %8d-%d\n",
+ sgi_get_start_sector( Index[i] ) - start,
+ start, sgi_get_start_sector( Index[i] )-1 );
+ gap += sgi_get_start_sector( Index[i] ) - start;
+ add2freelist( start, sgi_get_start_sector( Index[i] ) );
+ }
+ start = sgi_get_start_sector( Index[i] )
+ + sgi_get_num_sectors( Index[i] );
+ if(debug>1)
+ {
+ if( verbose )
+ printf( "%2d:%12d\t%12d\t%12d\n", Index[i],
+ sgi_get_start_sector(Index[i]),
+ sgi_get_num_sectors(Index[i]),
+ sgi_get_sysid(Index[i]) );
+ }
+ }
+ if( ( start < lastblock ) )
+ {
+ if( verbose )
+ printf( "Unused gap of %8d sectors - sectors %8d-%d\n",
+ lastblock - start, start, lastblock-1 );
+ gap += lastblock - start;
+ add2freelist( start, lastblock );
+ }
+ /*
+ * Done with arithmetics
+ * Go for details now
+ */
+ if( verbose )
+ {
+ if( !sgi_get_num_sectors( sgi_get_bootpartition() ) )
+ {
+ printf( "\nThe boot partition does not exist.\n" );
+ }
+ if( !sgi_get_num_sectors( sgi_get_swappartition() ) )
+ {
+ printf( "\nThe swap partition does not exist.\n" );
+ } else
+ if( ( sgi_get_sysid( sgi_get_swappartition() ) != SGI_SWAP )
+ && ( sgi_get_sysid( sgi_get_swappartition() ) != LINUX_SWAP ) )
+ {
+ printf( "\nThe swap partition has no swap type.\n" );
+ }
+ if( sgi_check_bootfile( "/unix" ) )
+ {
+ printf( "\tYou have chosen an unusual boot file name.\n" );
+ }
+ }
+ return gap;
+}
+
+void
+sgi_change_sysid( int i, int sys )
+{
+ if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
+ {
+ printf("Sorry You may change the Tag of non-empty partitions.\n");
+ return;
+ }
+ if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
+ && (sgi_get_start_sector(i)<1) )
+ {
+ read_chars(
+ "It is highly recommended that the partition at offset 0\n"
+ "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
+ "retrieve from its directory standalone tools like sash and fx.\n"
+ "Only the \"SGI volume\" entire disk section may violate this.\n"
+ "Type YES if you are sure about tagging this partition differently.\n" );
+ if (strcmp (line_ptr, "YES\n"))
+ return;
+ }
+ sgilabel->partitions[i].id = SSWAP32(sys);
+ return;
+}
+
+int
+sgi_entire( void )
+{ /* returns partition index of first entry marked as entire disk */
+ int i=0;
+ for( i=0; i<16; i++ )
+ if( sgi_get_sysid(i) == SGI_VOLUME )
+ return i;
+ return -1;
+}
+
+int
+sgi_num_partitions( void )
+{
+ int i=0,
+ n=0;
+ for( i=0; i<16; i++ )
+ if( sgi_get_num_sectors(i)!=0 )
+ n++;
+ return n;
+}
+
+static
+void
+sgi_set_partition( int i, uint start, uint length, int sys )
+{
+ sgilabel->partitions[i].id =
+ SSWAP32( sys );
+ sgilabel->partitions[i].num_sectors =
+ SSWAP32( length );
+ sgilabel->partitions[i].start_sector =
+ SSWAP32( start );
+ changed[i] = 1;
+ if( sgi_gaps(0) < 0 ) /* rebuild freelist */
+ {
+ printf( "Do You know, You got a partition overlap on the disk?\n" );
+ }
+ return;
+}
+
+static
+void
+sgi_set_entire( void )
+{
+ int n;
+ for( n=10; n<partitions; n++ )
+ {
+ if(!sgi_get_num_sectors( n ) )
+ {
+ sgi_set_partition( n, 0, sgi_get_lastblock(), SGI_VOLUME );
+ break;
+ }
+ }
+ return;
+}
+
+static
+void
+sgi_set_volhdr( void )
+{
+ int n;
+ for( n=8; n<partitions; n++ )
+ {
+ if(!sgi_get_num_sectors( n ) )
+ {
+ /*
+ * 5 cylinders is an arbitrary value I like
+ * IRIX 5.3 stored files in the volume header
+ * (like sash, symmon, fx, ide) with ca. 3200
+ * sectors.
+ */
+ if( heads * sectors * 5 < sgi_get_lastblock() )
+ sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
+ break;
+ }
+ }
+ return;
+}
+
+void
+sgi_delete_partition( int i )
+{
+ sgi_set_partition( i, 0, 0, 0 );
+ return;
+}
+
+void
+sgi_add_partition( int n, int sys )
+{
+ char mesg[48];
+ int first=0, last=0;
+
+ if( n == 10 ) {
+ sys = SGI_VOLUME;
+ } else if ( n == 8 ) {
+ sys = 0;
+ }
+ if( sgi_get_num_sectors(n) )
+ {
+ printf( "Partition %d is already defined. Delete "
+ "it before re-adding it.\n", n + 1);
+ return;
+ }
+ if( (sgi_entire() == -1)
+ && (sys != SGI_VOLUME) )
+ {
+ printf( "Attempting to generate entire disk entry automatically.\n" );
+ sgi_set_entire();
+ sgi_set_volhdr();
+ }
+ if( (sgi_gaps() == 0)
+ && (sys != SGI_VOLUME) )
+ {
+ printf( "The entire disk is already covered with partitions.\n" );
+ return;
+ }
+ if( sgi_gaps() < 0 )
+ {
+ printf( "You got a partition overlap on the disk. Fix it first!\n" );
+ return;
+ }
+ sprintf(mesg, "First %s", str_units());
+ for(;;)
+ {
+ if(sys == SGI_VOLUME)
+ {
+ last = sgi_get_lastblock();
+ first = read_int(0, 0, last-1, 0, mesg);
+ if( first != 0 ) {
+ printf( "It is highly recommended that eleventh partition\n"
+ "covers the entire disk and is of type `SGI volume'\n");
+ }
+ } else {
+ first = freelist[0].first;
+ last = freelist[0].last;
+ first = read_int(scround(first), scround(first), scround(last)-1,
+ 0, mesg);
+ }
+ if (unit_flag)
+ first *= display_factor;
+ else
+ first = first; /* align to cylinder if you know how ... */
+ if( !last )
+ last = isinfreelist(first);
+ if( last == 0 ) {
+ printf( "You will get a partition overlap on the disk. "
+ "Fix it first!\n" );
+ } else
+ break;
+ }
+ sprintf(mesg, " Last %s", str_units());
+ last = read_int(scround(first), scround(last)-1, scround(last)-1,
+ scround(first), mesg)+1;
+ if (unit_flag)
+ last *= display_factor;
+ else
+ last = last; /* align to cylinder if You know how ... */
+ if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
+ {
+ printf( "It is highly recommended that eleventh partition\n"
+ "covers the entire disk and is of type `SGI volume'\n");
+ }
+ sgi_set_partition( n, first, last-first, sys );
+ return;
+}
+
+void
+create_sgilabel( void )
+{
+ struct hd_geometry geometry;
+ struct { int start;
+ int nsect;
+ int sysid; } old[4];
+ int i=0;
+ fprintf( stderr,
+ "Building a new SGI disklabel. Changes will remain in memory only,\n"
+ "until you decide to write them. After that, of course, the previous\n"
+ "content will be unrecoverable lost.\n\n");
+#if BYTE_ORDER == LITTLE_ENDIAN
+ other_endian = 1;
+#else
+ other_endian = 0;
+#endif
+#ifdef HDIO_REQ
+ if (!ioctl(fd, HDIO_REQ, &geometry))
+#else
+ if (!ioctl(fd, HDIO_GETGEO, &geometry))
+#endif
+ {
+ heads = geometry.heads;
+ sectors = geometry.sectors;
+ cylinders = geometry.cylinders;
+ }
+ for (i = 0; i < 4; i++)
+ {
+ old[i].sysid = 0;
+ if( valid_part_table_flag(buffer) )
+ {
+ if( part_table[i]->sys_ind )
+ {
+ old[i].sysid = part_table[i]->sys_ind;
+ old[i].start = get_start_sect( part_table[i] );
+ old[i].nsect = get_nr_sects( part_table[i] );
+ printf( "Trying to keep parameters of partition %d.\n", i );
+ if( debug )
+ printf( "ID=%02x\tSTART=%d\tLENGTH=%d\n",
+ old[i].sysid, old[i].start, old[i].nsect );
+ }
+ }
+ }
+ memset(buffer, 0, SECTOR_SIZE);
+ sgilabel->magic = SSWAP32(SGI_LABEL_MAGIC);
+ sgilabel->boot_part = SSWAP16(0);
+ sgilabel->swap_part = SSWAP16(1); strncpy(
+ sgilabel->boot_file , "/unix\0\0\0\0\0\0\0\0\0\0\0", 16 );
+ sgilabel->devparam.skew = (0);
+ sgilabel->devparam.gap1 = (0);
+ sgilabel->devparam.gap2 = (0);
+ sgilabel->devparam.sparecyl = (0);
+ sgilabel->devparam.pcylcount = SSWAP16(geometry.cylinders);
+ sgilabel->devparam.head_vol0 = SSWAP16(0);
+ sgilabel->devparam.ntrks = SSWAP16(geometry.heads);
+ /* tracks/cylinder (heads) */
+ sgilabel->devparam.cmd_tag_queue_depth = (0);
+ sgilabel->devparam.unused0 = (0);
+ sgilabel->devparam.unused1 = SSWAP16(0);
+ sgilabel->devparam.nsect = SSWAP16(geometry.sectors);
+ /* sectors/track */
+ sgilabel->devparam.bytes = SSWAP16(512);
+ sgilabel->devparam.ilfact = SSWAP16(1);
+ sgilabel->devparam.flags = SSWAP32(TRACK_FWD|\
+ IGNORE_ERRORS|RESEEK);
+ sgilabel->devparam.datarate = SSWAP32(0);
+ sgilabel->devparam.retries_on_error = SSWAP32(1);
+ sgilabel->devparam.ms_per_word = SSWAP32(0);
+ sgilabel->devparam.xylogics_gap1 = SSWAP16(0);
+ sgilabel->devparam.xylogics_syncdelay = SSWAP16(0);
+ sgilabel->devparam.xylogics_readdelay = SSWAP16(0);
+ sgilabel->devparam.xylogics_gap2 = SSWAP16(0);
+ sgilabel->devparam.xylogics_readgate = SSWAP16(0);
+ sgilabel->devparam.xylogics_writecont = SSWAP16(0);
+ memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
+ memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
+ sgi_label = 1;
+ partitions = 16;
+ volumes = 15;
+ sgi_set_entire();
+ sgi_set_volhdr();
+ for (i = 0; i < 4; i++)
+ {
+ if( old[i].sysid )
+ {
+ sgi_set_partition( i, old[i].start, old[i].nsect, old[i].sysid );
+ }
+ }
+ return;
+}
+
+void
+sgi_set_ilfact( void )
+{
+ /* do nothing in the beginning */
+}
+
+void
+sgi_set_rspeed( void )
+{
+ /* do nothing in the beginning */
+}
+
+void
+sgi_set_pcylcount( void )
+{
+ /* do nothing in the beginning */
+}
+
+void
+sgi_set_xcyl( void )
+{
+ /* do nothing in the beginning */
+}
+
+void
+sgi_set_ncyl( void )
+{
+ /* do nothing in the beginning */
+}
+
+/* _____________________________________________________________
+ */
+
+sgiinfo*
+fill_sgiinfo( void )
+{
+ sgiinfo*info=calloc( 1, sizeof(sgiinfo) );
+ info->magic=SSWAP32(SGI_INFO_MAGIC);
+ info->b1=SSWAP32(-1);
+ info->b2=SSWAP16(-1);
+ info->b3=SSWAP16(1);
+ /* You may want to replace this string !!!!!!! */
+ strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
+ strcpy( info->serial, "0000" );
+ info->check1816 = SSWAP16(18*256 +16 );
+ strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
+ return info;
+}