]> git.ipfire.org Git - thirdparty/util-linux.git/blob - fdisk/fdisksgilabel.c
Imported from util-linux-2.9v tarball.
[thirdparty/util-linux.git] / fdisk / fdisksgilabel.c
1 /*
2 *
3 * fdisksgilabel.c
4 *
5 * Copyright (C) Andreas Neuper, Sep 1998.
6 * This file may be modified and redistributed under
7 * the terms of the GNU Public License.
8 *
9 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
10 * Internationalization
11 */
12 #include <stdio.h> /* stderr */
13 #include <stdlib.h> /* uint */
14 #include <string.h> /* strstr */
15 #include <unistd.h> /* write */
16 #include <sys/ioctl.h> /* ioctl */
17 #include <sys/stat.h> /* stat */
18 #include <assert.h> /* assert */
19
20 #include <endian.h>
21 #include "nls.h"
22 #include <linux/major.h> /* FLOPPY_MAJOR */
23 #include <linux/hdreg.h> /* HDIO_GETGEO */
24
25 #include "common.h"
26 #include "fdisk.h"
27 #include "fdisksgilabel.h"
28
29 static int other_endian = 0;
30 static int debug = 0;
31 static short volumes=1;
32
33 /*
34 * only dealing with free blocks here
35 */
36
37 typedef struct { int first; int last; } freeblocks;
38 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
39 void setfreelist( int i, int f, int l ) \
40 { freelist[i].first = f; freelist[i].last = l; return; }
41 void add2freelist( int f, int l ) \
42 { int i = 0; for( ; i<17 ; i++ ) { if(freelist[i].last==0) break; }\
43 setfreelist( i, f, l ); return; }
44 void clearfreelist( void ) \
45 { int i = 0; for( ; i<17 ; i++ ) { setfreelist( i, 0, 0 ); } return; }
46 int isinfreelist( int b ) \
47 { int i = 0; for( ; i<17 ; i++ )\
48 { if( ( freelist[i].first <= b ) && ( freelist[i].last >= b) )\
49 { return freelist[i].last; } } return 0; }
50 /* return last vacant block of this stride (never 0). */
51 /* the '>=' is not quite correct, but simplifies the code */
52 /*
53 * end of free blocks section
54 */
55 struct systypes sgi_sys_types[] = {
56 {SGI_VOLHDR, N_("SGI volhdr")},
57 {0x01, N_("SGI trkrepl")},
58 {0x02, N_("SGI secrepl")},
59 {SGI_SWAP, N_("SGI raw")},
60 {0x04, N_("SGI bsd")},
61 {0x05, N_("SGI sysv")},
62 {ENTIRE_DISK, N_("SGI volume")},
63 {SGI_EFS, N_("SGI efs")},
64 {0x08, N_("SGI lvol")},
65 {0x09, N_("SGI rlvol")},
66 {0x0A, N_("SGI xfs")},
67 {0x0B, N_("SGI xlvol")},
68 {0x0C, N_("SGI rxlvol")},
69 {LINUX_SWAP, N_("Linux swap")},
70 {LINUX_NATIVE,N_("Linux native")},
71 {0, NULL }
72 };
73
74 static inline unsigned short __swap16(unsigned short x) {
75 return (((__u16)(x) & 0xFF) << 8) | (((__u16)(x) & 0xFF00) >> 8);
76 }
77 static inline __u32 __swap32(__u32 x) {
78 return (((__u32)(x) & 0xFF) << 24) | (((__u32)(x) & 0xFF00) << 8) | (((__u32)(x) & 0xFF0000) >> 8) | (((__u32)(x) & 0xFF000000) >> 24);
79 }
80
81 static
82 int
83 sgi_get_nsect( void )
84 {
85 return SSWAP16(sgilabel->devparam.nsect);
86 }
87
88 static
89 int
90 sgi_get_ntrks( void )
91 {
92 return SSWAP16(sgilabel->devparam.ntrks);
93 }
94
95 #if 0
96 static int
97 sgi_get_head_vol0( void )
98 {
99 return SSWAP16(sgilabel->devparam.head_vol0);
100 }
101
102 static int
103 sgi_get_bytes( void )
104 {
105 return SSWAP16(sgilabel->devparam.bytes);
106 }
107 #endif
108
109 static
110 int
111 sgi_get_pcylcount( void )
112 {
113 return SSWAP16(sgilabel->devparam.pcylcount);
114 }
115
116 void
117 sgi_nolabel()
118 {
119 sgilabel->magic = 0;
120 sgi_label = 0;
121 partitions = 4;
122 }
123
124 unsigned int
125 two_s_complement_32bit_sum(
126 unsigned int* base,
127 int size /* in bytes */ )
128 {
129 int i=0;
130 unsigned int sum=0;
131 size = size / sizeof( unsigned int );
132 for( i=0; i<size; i++ )
133 {
134 sum = sum - SSWAP32(base[i]);
135 }
136 return sum;
137 }
138
139 int check_sgi_label()
140 {
141 if (sizeof(sgilabel) > 512) {
142 fprintf(stderr,
143 _("According to MIPS Computer Systems, Inc the "
144 "Label must not contain more than 512 bytes\n"));
145 exit(1);
146 }
147
148 if (sgilabel->magic != SGI_LABEL_MAGIC &&
149 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
150 sgi_label = 0;
151 other_endian = 0;
152 return 0;
153 }
154
155 other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
156 /*
157 * test for correct checksum
158 */
159 if( two_s_complement_32bit_sum( (unsigned int*)sgilabel,
160 sizeof(*sgilabel) ) )
161 {
162 fprintf( stderr, _("Detected sgi disklabel with wrong checksum.\n"));
163 } else
164 {
165 heads = sgi_get_ntrks();
166 cylinders = sgi_get_pcylcount();
167 sectors = sgi_get_nsect();
168 }
169 update_units();
170 sgi_label = 1;
171 partitions= 16;
172 volumes = 15;
173 return 1;
174 }
175
176 void
177 sgi_list_table( int xtra )
178 {
179 int i, w;
180 char *type;
181
182 w = strlen( disk_device );
183
184 if( xtra )
185 {
186 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
187 "%d cylinders, %d physical cylinders\n"
188 "%d extra sects/cyl, interleave %d:1\n"
189 "%s\n"
190 "Units = %s of %d * 512 bytes\n\n"),
191 disk_device, heads, sectors, cylinders,
192 SSWAP16(sgiparam.pcylcount),
193 SSWAP16(sgiparam.sparecyl),
194 SSWAP16(sgiparam.ilfact),
195 (char *)sgilabel,
196 str_units(PLURAL), units_per_sector);
197 } else
198 {
199 printf( _("\nDisk %s (SGI disk label): "
200 "%d heads, %d sectors, %d cylinders\n"
201 "Units = %s of %d * 512 bytes\n\n"),
202 disk_device, heads, sectors, cylinders,
203 str_units(PLURAL), units_per_sector );
204 }
205 printf(_("----- partitions -----\n"
206 "%*s Info Start End Sectors Id System\n"),
207 w + 1, _("Device"));
208 for (i = 0 ; i < partitions; i++)
209 {
210 if( sgi_get_num_sectors(i) || debug )
211 {
212 __u32 start = sgi_get_start_sector(i);
213 __u32 len = sgi_get_num_sectors(i);
214 printf(
215 "%*s%-2d %4s %9ld %9ld %9ld %2x %s\n",
216 /* device */ w, disk_device, i + 1,
217 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
218 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
219 /* start */ (long) scround(start),
220 /* end */ (long) scround(start+len)-1,
221 /* no odd flag on end */ (long) len,
222 /* type id */ sgi_get_sysid(i),
223 /* type name */ (type = partition_type(sgi_get_sysid(i)))
224 ? type : _("Unknown"));
225 }
226 }
227 printf(_("----- bootinfo -----\nBootfile: %s\n"
228 "----- directory entries -----\n"),
229 sgilabel->boot_file );
230 for (i = 0 ; i < volumes; i++)
231 {
232 if (sgilabel->directory[i].vol_file_size)
233 {
234 __u32 start = SSWAP32(sgilabel->directory[i].vol_file_start);
235 __u32 len = SSWAP32(sgilabel->directory[i].vol_file_size);
236 char*name = sgilabel->directory[i].vol_file_name;
237 printf(_("%2d: %-10s sector%5u size%8u\n"),
238 i, name, (unsigned int) start, (unsigned int) len);
239 }
240 }
241 }
242
243 int
244 sgi_get_start_sector( int i )
245 {
246 return SSWAP32(sgilabel->partitions[i].start_sector);
247 }
248
249 int
250 sgi_get_num_sectors( int i )
251 {
252 return SSWAP32(sgilabel->partitions[i].num_sectors);
253 }
254
255 int
256 sgi_get_sysid( int i )
257 {
258 return SSWAP32(sgilabel->partitions[i].id);
259 }
260
261 int
262 sgi_get_bootpartition( void )
263 {
264 return SSWAP16(sgilabel->boot_part);
265 }
266
267 int
268 sgi_get_swappartition( void )
269 {
270 return SSWAP16(sgilabel->swap_part);
271 }
272
273 void
274 sgi_set_bootpartition( int i )
275 {
276 sgilabel->boot_part = SSWAP16(((short)i));
277 return;
278 }
279
280 int
281 sgi_get_lastblock( void )
282 {
283 return heads * sectors * cylinders;
284 }
285
286 void
287 sgi_set_swappartition( int i )
288 {
289 sgilabel->swap_part = SSWAP16(((short)i));
290 return;
291 }
292
293 static int
294 sgi_check_bootfile( const char* aFile )
295 {
296 if( strlen( aFile ) < 3 ) /* "/a\n" is minimum */
297 {
298 printf( _("\nInvalid Bootfile!\n"
299 "\tThe bootfile must be an absolute non-zero pathname,\n"
300 "\te.g. \"/unix\" or \"/unix.save\".\n") );
301 return 0;
302 } else
303 if( strlen( aFile ) > 16 )
304 {
305 printf( _("\n\tName of Bootfile too long: 16 bytes maximum.\n") );
306 return 0;
307 } else
308 if( aFile[0] != '/' )
309 {
310 printf( _("\n\tBootfile must have a fully qualified pathname.\n") );
311 return 0;
312 }
313 if( strncmp( aFile, sgilabel->boot_file, 16 ) )
314 {
315 printf( _("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
316 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n") );
317 /* filename is correct and did change */
318 return 1;
319 }
320 return 0; /* filename did not change */
321 }
322
323 const char *
324 sgi_get_bootfile(void) {
325 return sgilabel->boot_file;
326 }
327
328 void
329 sgi_set_bootfile( const char* aFile )
330 {
331 int i = 0;
332 if( sgi_check_bootfile( aFile ) )
333 {
334 while( i<16 )
335 {
336 if( (aFile[i] != '\n') /* in principle caught again by next line */
337 && (strlen( aFile ) > i ) )
338 sgilabel->boot_file[i] = aFile[i];
339 else
340 sgilabel->boot_file[i] = 0;
341 i++;
342 }
343 printf( _("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file );
344 }
345 return;
346 }
347
348 void
349 create_sgiinfo( void )
350 {
351 /* I keep SGI's habit to write the sgilabel to the second block */
352 sgilabel->directory[0].vol_file_start = SSWAP32( 2 );
353 sgilabel->directory[0].vol_file_size = SSWAP32( sizeof( sgiinfo ) );
354 strncpy( sgilabel->directory[0].vol_file_name, "sgilabel",8 );
355 return;
356 }
357
358 sgiinfo * fill_sgiinfo( void );
359
360 void
361 sgi_write_table( void )
362 {
363 sgilabel->csum = 0;
364 sgilabel->csum = SSWAP32( two_s_complement_32bit_sum(
365 (unsigned int*)sgilabel,
366 sizeof(*sgilabel) ) );
367 assert( two_s_complement_32bit_sum(
368 (unsigned int*)sgilabel, sizeof(*sgilabel) ) == 0 );
369 if( lseek(fd, 0, SEEK_SET) < 0 )
370 fatal(unable_to_seek);
371 if( write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE )
372 fatal(unable_to_write);
373 if( ! strncmp( sgilabel->directory[0].vol_file_name, "sgilabel",8 ) )
374 {
375 /*
376 * keep this habbit of first writing the "sgilabel".
377 * I never tested whether it works without (AN 981002).
378 */
379 sgiinfo*info = fill_sgiinfo(); /* fills the block appropriately */
380 int infostartblock = SSWAP32( sgilabel->directory[0].vol_file_start );
381 if( ext2_llseek(fd, (ext2_loff_t)infostartblock*
382 SECTOR_SIZE, SEEK_SET) < 0 )
383 fatal(unable_to_seek);
384 if( write(fd, info, SECTOR_SIZE) != SECTOR_SIZE )
385 fatal(unable_to_write);
386 free( info );
387 }
388 return;
389 }
390
391 static
392 int
393 compare_start( int *x, int *y )
394 {
395 /*
396 * sort according to start sectors
397 * and prefers largest partition:
398 * entry zero is entire disk entry
399 */
400 int i = *x;
401 int j = *y;
402 int a = sgi_get_start_sector(i);
403 int b = sgi_get_start_sector(j);
404 int c = sgi_get_num_sectors(i);
405 int d = sgi_get_num_sectors(j);
406 if( a == b )
407 {
408 return( d - c );
409 }
410 return( a - b );
411 }
412
413 static
414 int
415 sgi_gaps()
416 {
417 /*
418 * returned value is:
419 * = 0 : disk is properly filled to the rim
420 * < 0 : there is an overlap
421 * > 0 : there is still some vacant space
422 */
423 return verify_sgi(0);
424 }
425
426 int
427 verify_sgi( int verbose )
428 {
429 int Index[16]; /* list of valid partitions */
430 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
431 int entire = 0, i = 0; /* local counters */
432 int start = 0;
433 int gap = 0; /* count unused blocks */
434 int lastblock = sgi_get_lastblock();
435 /*
436 */
437 clearfreelist();
438 for( i=0; i<16; i++ )
439 {
440 if( sgi_get_num_sectors(i)!=0 )
441 {
442 Index[sortcount++]=i;
443 if( sgi_get_sysid(i) == ENTIRE_DISK )
444 {
445 if( entire++ == 1 )
446 {
447 if(verbose)
448 printf(_("More than one entire disk entry present.\n"));
449 }
450 }
451 }
452 }
453 if( sortcount == 0 )
454 {
455 if(verbose)
456 printf(_("No partitions defined\n"));
457 return lastblock;
458 }
459 qsort( Index, sortcount, sizeof(Index[0]), (void*)compare_start );
460 if( sgi_get_sysid( Index[0] ) == ENTIRE_DISK )
461 {
462 if( ( Index[0] != 10 ) && verbose )
463 printf( _("IRIX likes when Partition 11 covers the entire disk.\n") );
464 if( ( sgi_get_start_sector( Index[0] ) != 0 ) && verbose )
465 printf( _("The entire disk partition should start at block 0,\nnot "
466 "at diskblock %d.\n"), sgi_get_start_sector(Index[0] ) );
467 if(debug) /* I do not understand how some disks fulfil it */
468 if( ( sgi_get_num_sectors( Index[0] ) != lastblock ) && verbose )
469 printf( _("The entire disk partition is only %d diskblock large,\n"
470 "but the disk is %d diskblocks long.\n"),
471 sgi_get_num_sectors( Index[0] ), lastblock );
472 lastblock = sgi_get_num_sectors( Index[0] );
473 } else
474 {
475 if( verbose )
476 printf( _("One Partition (#11) should cover the entire disk.\n") );
477 if(debug>2)
478 printf( "sysid=%d\tpartition=%d\n",
479 sgi_get_sysid( Index[0] ), Index[0]+1 );
480 }
481 for( i=1, start=0; i<sortcount; i++ )
482 {
483 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
484 if( (sgi_get_start_sector( Index[i] ) % cylsize) != 0 )
485 {
486 if(debug) /* I do not understand how some disks fulfil it */
487 if( verbose )
488 printf( _("Partition %d does not start on cylinder boundary.\n"),
489 Index[i]+1 );
490 }
491 if( sgi_get_num_sectors( Index[i] ) % cylsize != 0 )
492 {
493 if(debug) /* I do not understand how some disks fulfil it */
494 if( verbose )
495 printf( _("Partition %d does not end on cylinder boundary.\n"),
496 Index[i]+1 );
497 }
498 /* We cannot handle several "entire disk" entries. */
499 if( sgi_get_sysid( Index[i] ) == ENTIRE_DISK ) continue;
500 if( start > sgi_get_start_sector( Index[i] ) )
501 {
502 if( verbose )
503 printf( _("The Partition %d and %d overlap by %d sectors.\n"),
504 Index[i-1]+1, Index[i]+1,
505 start - sgi_get_start_sector( Index[i] ) );
506 if( gap > 0 ) gap = -gap;
507 if( gap == 0 ) gap = -1;
508 }
509 if( start < sgi_get_start_sector( Index[i] ) )
510 {
511 if( verbose )
512 printf( _("Unused gap of %8d sectors - sectors %8d-%d\n"),
513 sgi_get_start_sector( Index[i] ) - start,
514 start, sgi_get_start_sector( Index[i] )-1 );
515 gap += sgi_get_start_sector( Index[i] ) - start;
516 add2freelist( start, sgi_get_start_sector( Index[i] ) );
517 }
518 start = sgi_get_start_sector( Index[i] )
519 + sgi_get_num_sectors( Index[i] );
520 if(debug>1)
521 {
522 if( verbose )
523 printf( "%2d:%12d\t%12d\t%12d\n", Index[i],
524 sgi_get_start_sector(Index[i]),
525 sgi_get_num_sectors(Index[i]),
526 sgi_get_sysid(Index[i]) );
527 }
528 }
529 if( ( start < lastblock ) )
530 {
531 if( verbose )
532 printf( _("Unused gap of %8d sectors - sectors %8d-%d\n"),
533 lastblock - start, start, lastblock-1 );
534 gap += lastblock - start;
535 add2freelist( start, lastblock );
536 }
537 /*
538 * Done with arithmetics
539 * Go for details now
540 */
541 if( verbose )
542 {
543 if( !sgi_get_num_sectors( sgi_get_bootpartition() ) )
544 {
545 printf( _("\nThe boot partition does not exist.\n") );
546 }
547 if( !sgi_get_num_sectors( sgi_get_swappartition() ) )
548 {
549 printf( _("\nThe swap partition does not exist.\n") );
550 } else
551 if( ( sgi_get_sysid( sgi_get_swappartition() ) != SGI_SWAP )
552 && ( sgi_get_sysid( sgi_get_swappartition() ) != LINUX_SWAP ) )
553 {
554 printf( _("\nThe swap partition has no swap type.\n") );
555 }
556 if( sgi_check_bootfile( "/unix" ) )
557 {
558 printf( _("\tYou have chosen an unusual boot file name.\n") );
559 }
560 }
561 return gap;
562 }
563
564 void
565 sgi_change_sysid( int i, int sys )
566 {
567 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
568 {
569 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
570 return;
571 }
572 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
573 && (sgi_get_start_sector(i)<1) )
574 {
575 read_chars(
576 _("It is highly recommended that the partition at offset 0\n"
577 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
578 "retrieve from its directory standalone tools like sash and fx.\n"
579 "Only the \"SGI volume\" entire disk section may violate this.\n"
580 "Type YES if you are sure about tagging this partition differently.\n"));
581 if (strcmp (line_ptr, "YES\n"))
582 return;
583 }
584 sgilabel->partitions[i].id = SSWAP32(sys);
585 return;
586 }
587
588 int
589 sgi_entire( void )
590 { /* returns partition index of first entry marked as entire disk */
591 int i=0;
592 for( i=0; i<16; i++ )
593 if( sgi_get_sysid(i) == SGI_VOLUME )
594 return i;
595 return -1;
596 }
597
598 int
599 sgi_num_partitions( void )
600 {
601 int i=0,
602 n=0;
603 for( i=0; i<16; i++ )
604 if( sgi_get_num_sectors(i)!=0 )
605 n++;
606 return n;
607 }
608
609 static
610 void
611 sgi_set_partition( int i, uint start, uint length, int sys )
612 {
613 sgilabel->partitions[i].id =
614 SSWAP32( sys );
615 sgilabel->partitions[i].num_sectors =
616 SSWAP32( length );
617 sgilabel->partitions[i].start_sector =
618 SSWAP32( start );
619 changed[i] = 1;
620 if( sgi_gaps(0) < 0 ) /* rebuild freelist */
621 printf(_("Do You know, You got a partition overlap on the disk?\n"));
622 return;
623 }
624
625 static
626 void
627 sgi_set_entire( void )
628 {
629 int n;
630 for( n=10; n<partitions; n++ )
631 {
632 if(!sgi_get_num_sectors( n ) )
633 {
634 sgi_set_partition( n, 0, sgi_get_lastblock(), SGI_VOLUME );
635 break;
636 }
637 }
638 return;
639 }
640
641 static
642 void
643 sgi_set_volhdr( void )
644 {
645 int n;
646 for( n=8; n<partitions; n++ )
647 {
648 if(!sgi_get_num_sectors( n ) )
649 {
650 /*
651 * 5 cylinders is an arbitrary value I like
652 * IRIX 5.3 stored files in the volume header
653 * (like sash, symmon, fx, ide) with ca. 3200
654 * sectors.
655 */
656 if( heads * sectors * 5 < sgi_get_lastblock() )
657 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
658 break;
659 }
660 }
661 return;
662 }
663
664 void
665 sgi_delete_partition( int i )
666 {
667 sgi_set_partition( i, 0, 0, 0 );
668 return;
669 }
670
671 void
672 sgi_add_partition( int n, int sys )
673 {
674 char mesg[48];
675 int first=0, last=0;
676
677 if( n == 10 ) {
678 sys = SGI_VOLUME;
679 } else if ( n == 8 ) {
680 sys = 0;
681 }
682 if( sgi_get_num_sectors(n) )
683 {
684 printf(_("Partition %d is already defined. Delete "
685 "it before re-adding it.\n"), n + 1);
686 return;
687 }
688 if( (sgi_entire() == -1)
689 && (sys != SGI_VOLUME) )
690 {
691 printf(_("Attempting to generate entire disk entry automatically.\n"));
692 sgi_set_entire();
693 sgi_set_volhdr();
694 }
695 if( (sgi_gaps() == 0)
696 && (sys != SGI_VOLUME) )
697 {
698 printf(_("The entire disk is already covered with partitions.\n"));
699 return;
700 }
701 if( sgi_gaps() < 0 )
702 {
703 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
704 return;
705 }
706 sprintf(mesg, _("First %s"), str_units(SINGULAR));
707 for(;;) {
708 if(sys == SGI_VOLUME) {
709 last = sgi_get_lastblock();
710 first = read_int(0, 0, last-1, 0, mesg);
711 if( first != 0 ) {
712 printf(_("It is highly recommended that eleventh partition\n"
713 "covers the entire disk and is of type `SGI volume'\n"));
714 }
715 } else {
716 first = freelist[0].first;
717 last = freelist[0].last;
718 first = read_int(scround(first), scround(first), scround(last)-1,
719 0, mesg);
720 }
721 if (display_in_cyl_units)
722 first *= units_per_sector;
723 else
724 first = first; /* align to cylinder if you know how ... */
725 if( !last )
726 last = isinfreelist(first);
727 if( last == 0 ) {
728 printf(_("You will get a partition overlap on the disk. "
729 "Fix it first!\n"));
730 } else
731 break;
732 }
733 sprintf(mesg, _(" Last %s"), str_units(SINGULAR));
734 last = read_int(scround(first), scround(last)-1, scround(last)-1,
735 scround(first), mesg)+1;
736 if (display_in_cyl_units)
737 last *= units_per_sector;
738 else
739 last = last; /* align to cylinder if You know how ... */
740 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
741 printf(_("It is highly recommended that eleventh partition\n"
742 "covers the entire disk and is of type `SGI volume'\n"));
743 sgi_set_partition( n, first, last-first, sys );
744 return;
745 }
746
747 void
748 create_sgilabel( void )
749 {
750 struct hd_geometry geometry;
751 struct { int start;
752 int nsect;
753 int sysid; } old[4];
754 int i=0;
755 fprintf( stderr,
756 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
757 "until you decide to write them. After that, of course, the previous\n"
758 "content will be unrecoverable lost.\n\n"));
759 #if BYTE_ORDER == LITTLE_ENDIAN
760 other_endian = 1;
761 #else
762 other_endian = 0;
763 #endif
764 #ifdef HDIO_REQ
765 if (!ioctl(fd, HDIO_REQ, &geometry))
766 #else
767 if (!ioctl(fd, HDIO_GETGEO, &geometry))
768 #endif
769 {
770 heads = geometry.heads;
771 sectors = geometry.sectors;
772 cylinders = geometry.cylinders;
773 }
774 for (i = 0; i < 4; i++)
775 {
776 old[i].sysid = 0;
777 if( valid_part_table_flag(buffer) )
778 {
779 if( part_table[i]->sys_ind )
780 {
781 old[i].sysid = part_table[i]->sys_ind;
782 old[i].start = get_start_sect( part_table[i] );
783 old[i].nsect = get_nr_sects( part_table[i] );
784 printf( _("Trying to keep parameters of partition %d.\n"), i );
785 if( debug )
786 printf( _("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
787 old[i].sysid, old[i].start, old[i].nsect );
788 }
789 }
790 }
791 memset(buffer, 0, SECTOR_SIZE);
792 sgilabel->magic = SSWAP32(SGI_LABEL_MAGIC);
793 sgilabel->boot_part = SSWAP16(0);
794 sgilabel->swap_part = SSWAP16(1); strncpy(
795 sgilabel->boot_file , "/unix\0\0\0\0\0\0\0\0\0\0\0", 16 );
796 sgilabel->devparam.skew = (0);
797 sgilabel->devparam.gap1 = (0);
798 sgilabel->devparam.gap2 = (0);
799 sgilabel->devparam.sparecyl = (0);
800 sgilabel->devparam.pcylcount = SSWAP16(geometry.cylinders);
801 sgilabel->devparam.head_vol0 = SSWAP16(0);
802 sgilabel->devparam.ntrks = SSWAP16(geometry.heads);
803 /* tracks/cylinder (heads) */
804 sgilabel->devparam.cmd_tag_queue_depth = (0);
805 sgilabel->devparam.unused0 = (0);
806 sgilabel->devparam.unused1 = SSWAP16(0);
807 sgilabel->devparam.nsect = SSWAP16(geometry.sectors);
808 /* sectors/track */
809 sgilabel->devparam.bytes = SSWAP16(512);
810 sgilabel->devparam.ilfact = SSWAP16(1);
811 sgilabel->devparam.flags = SSWAP32(TRACK_FWD|\
812 IGNORE_ERRORS|RESEEK);
813 sgilabel->devparam.datarate = SSWAP32(0);
814 sgilabel->devparam.retries_on_error = SSWAP32(1);
815 sgilabel->devparam.ms_per_word = SSWAP32(0);
816 sgilabel->devparam.xylogics_gap1 = SSWAP16(0);
817 sgilabel->devparam.xylogics_syncdelay = SSWAP16(0);
818 sgilabel->devparam.xylogics_readdelay = SSWAP16(0);
819 sgilabel->devparam.xylogics_gap2 = SSWAP16(0);
820 sgilabel->devparam.xylogics_readgate = SSWAP16(0);
821 sgilabel->devparam.xylogics_writecont = SSWAP16(0);
822 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
823 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
824 sgi_label = 1;
825 partitions = 16;
826 volumes = 15;
827 sgi_set_entire();
828 sgi_set_volhdr();
829 for (i = 0; i < 4; i++)
830 {
831 if( old[i].sysid )
832 {
833 sgi_set_partition( i, old[i].start, old[i].nsect, old[i].sysid );
834 }
835 }
836 return;
837 }
838
839 void
840 sgi_set_ilfact( void )
841 {
842 /* do nothing in the beginning */
843 }
844
845 void
846 sgi_set_rspeed( void )
847 {
848 /* do nothing in the beginning */
849 }
850
851 void
852 sgi_set_pcylcount( void )
853 {
854 /* do nothing in the beginning */
855 }
856
857 void
858 sgi_set_xcyl( void )
859 {
860 /* do nothing in the beginning */
861 }
862
863 void
864 sgi_set_ncyl( void )
865 {
866 /* do nothing in the beginning */
867 }
868
869 /* _____________________________________________________________
870 */
871
872 sgiinfo*
873 fill_sgiinfo( void )
874 {
875 sgiinfo*info=calloc( 1, sizeof(sgiinfo) );
876 info->magic=SSWAP32(SGI_INFO_MAGIC);
877 info->b1=SSWAP32(-1);
878 info->b2=SSWAP16(-1);
879 info->b3=SSWAP16(1);
880 /* You may want to replace this string !!!!!!! */
881 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
882 strcpy( info->serial, "0000" );
883 info->check1816 = SSWAP16(18*256 +16 );
884 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
885 return info;
886 }