Home | History | Annotate | Line # | Download | only in sgivol
sgivol.c revision 1.1
      1  1.1  soren /*	$NetBSD: sgivol.c,v 1.1 2001/11/20 18:35:22 soren Exp $	*/
      2  1.1  soren 
      3  1.1  soren /*-
      4  1.1  soren  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5  1.1  soren  * All rights reserved.
      6  1.1  soren  *
      7  1.1  soren  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1  soren  * by Michael Hitch and Hubert Feyrer.
      9  1.1  soren  *
     10  1.1  soren  * Redistribution and use in source and binary forms, with or without
     11  1.1  soren  * modification, are permitted provided that the following conditions
     12  1.1  soren  * are met:
     13  1.1  soren  * 1. Redistributions of source code must retain the above copyright
     14  1.1  soren  *    notice, this list of conditions and the following disclaimer.
     15  1.1  soren  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1  soren  *    notice, this list of conditions and the following disclaimer in the
     17  1.1  soren  *    documentation and/or other materials provided with the distribution.
     18  1.1  soren  * 3. All advertising materials mentioning features or use of this software
     19  1.1  soren  *    must display the following acknowledgement:
     20  1.1  soren  *        This product includes software developed by the NetBSD
     21  1.1  soren  *        Foundation, Inc. and its contributors.
     22  1.1  soren  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.1  soren  *    contributors may be used to endorse or promote products derived
     24  1.1  soren  *    from this software without specific prior written permission.
     25  1.1  soren  *
     26  1.1  soren  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.1  soren  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.1  soren  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.1  soren  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.1  soren  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.1  soren  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.1  soren  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.1  soren  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.1  soren  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.1  soren  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.1  soren  * POSSIBILITY OF SUCH DAMAGE.
     37  1.1  soren  */
     38  1.1  soren 
     39  1.1  soren #include <stdio.h>
     40  1.1  soren #include <unistd.h>
     41  1.1  soren #include <string.h>
     42  1.1  soren #include <fcntl.h>
     43  1.1  soren #include <util.h>
     44  1.1  soren 
     45  1.1  soren #include <sys/types.h>
     46  1.1  soren #include <sys/ioctl.h>
     47  1.1  soren #include <sys/disklabel.h>
     48  1.1  soren #include <sys/stat.h>
     49  1.1  soren 
     50  1.1  soren #define SGI_SIZE_VOLHDR	3135	/* XXX Irix: 2592, NetBSD: 3753 */
     51  1.1  soren 
     52  1.1  soren int	fd;
     53  1.1  soren int	n;
     54  1.1  soren int	opt_i;			/* Initialize volume header */
     55  1.1  soren int	opt_r;			/* Read a file from volume header */
     56  1.1  soren int	opt_w;			/* Write a file to volume header */
     57  1.1  soren int	opt_d;			/* Delete a file from volume header */
     58  1.1  soren int	opt_p;			/* Modify a partition */
     59  1.1  soren char	*vfilename = "";
     60  1.1  soren char	*ufilename = "";
     61  1.1  soren int	partno, partfirst, partblocks, parttype;
     62  1.1  soren struct sgilabel *volhdr;
     63  1.1  soren long	*l;
     64  1.1  soren long	checksum;
     65  1.1  soren 
     66  1.1  soren struct disklabel lbl;
     67  1.1  soren 
     68  1.1  soren unsigned char buf[512];
     69  1.1  soren 
     70  1.1  soren char *sgi_types[] = {
     71  1.1  soren 	"Volume Header",
     72  1.1  soren 	"Repl Trks",
     73  1.1  soren 	"Repl Secs",
     74  1.1  soren 	"Raw",
     75  1.1  soren 	"BSD4.2",
     76  1.1  soren 	"SysV",
     77  1.1  soren 	"Volume",
     78  1.1  soren 	"EFS",
     79  1.1  soren 	"LVol",
     80  1.1  soren 	"RLVol",
     81  1.1  soren 	"XFS",
     82  1.1  soren 	"XSFLog",
     83  1.1  soren 	"XLV",
     84  1.1  soren 	"XVM"
     85  1.1  soren };
     86  1.1  soren 
     87  1.1  soren main(argc, argv)
     88  1.1  soren 	int	argc;
     89  1.1  soren 	char	*argv[];
     90  1.1  soren {
     91  1.1  soren 	if (argc < 2)
     92  1.1  soren 		usage();
     93  1.1  soren 
     94  1.1  soren 	if (argv[1][0] == '-') {
     95  1.1  soren 		switch(argv[1][1]) {
     96  1.1  soren 		case 'i':
     97  1.1  soren 			++opt_i;
     98  1.1  soren 			argv++;
     99  1.1  soren 			argc--;
    100  1.1  soren 			break;
    101  1.1  soren 		case 'r':
    102  1.1  soren 		case 'w':
    103  1.1  soren 			if (argc < 4)
    104  1.1  soren 				usage();
    105  1.1  soren 			if (argv[1][1] == 'r')
    106  1.1  soren 				++opt_r;
    107  1.1  soren 			else
    108  1.1  soren 				++opt_w;
    109  1.1  soren 			vfilename = argv[2];
    110  1.1  soren 			ufilename = argv[3];
    111  1.1  soren 			argv += 3;
    112  1.1  soren 			argc -= 3;
    113  1.1  soren 			break;
    114  1.1  soren 		case 'd':
    115  1.1  soren 			if (argc < 3)
    116  1.1  soren 				usage();
    117  1.1  soren 			++opt_d;
    118  1.1  soren 			vfilename = argv[2];
    119  1.1  soren 			argv += 2;
    120  1.1  soren 			argc -= 2;
    121  1.1  soren 				break;
    122  1.1  soren 		case 'p':
    123  1.1  soren 			if (argc < 6)
    124  1.1  soren 				usage();
    125  1.1  soren 			++opt_p;
    126  1.1  soren 			partno = atoi(argv[2]);
    127  1.1  soren 			partfirst = atoi(argv[3]);
    128  1.1  soren 			partblocks = atoi(argv[4]);
    129  1.1  soren 			parttype = atoi(argv[5]);
    130  1.1  soren 			argv += 5;
    131  1.1  soren 			argc -= 5;
    132  1.1  soren 			break;
    133  1.1  soren 		default:
    134  1.1  soren 			printf("-%c Invalid\n", argv[1][1]);
    135  1.1  soren 			usage();
    136  1.1  soren 		}
    137  1.1  soren 	}
    138  1.1  soren 
    139  1.1  soren 	if (argc < 2)
    140  1.1  soren 		usage();
    141  1.1  soren 
    142  1.1  soren 	fd = open(argv[1], (opt_i | opt_w | opt_d | opt_p) ? O_RDWR : O_RDONLY);
    143  1.1  soren 	if (fd < 0) {
    144  1.1  soren 		sprintf(buf, "/dev/r%s%c", argv[1], 'a' + getrawpartition());
    145  1.1  soren 		fd = open(buf, (opt_i | opt_w | opt_d | opt_p) ? O_RDWR : O_RDONLY);
    146  1.1  soren 		if (fd < 0) {
    147  1.1  soren 			perror("open");
    148  1.1  soren 			exit(1);
    149  1.1  soren 		}
    150  1.1  soren 	}
    151  1.1  soren 	n = read(fd, buf, sizeof(buf));
    152  1.1  soren 	if (n != sizeof(buf)) {
    153  1.1  soren 		perror("read volhdr");
    154  1.1  soren 		exit(1);
    155  1.1  soren 	}
    156  1.1  soren 	n = ioctl(fd, DIOCGDINFO, &lbl);
    157  1.1  soren 	if (n < 0) {
    158  1.1  soren 		perror("DIOCGDINFO");
    159  1.1  soren 		exit(1);
    160  1.1  soren 	}
    161  1.1  soren 	volhdr = (struct sgilabel *)buf;
    162  1.1  soren 	if (opt_i) {
    163  1.1  soren 		init_volhdr();
    164  1.1  soren 		exit(0);
    165  1.1  soren 	}
    166  1.1  soren 	if (volhdr->magic != SGILABEL_MAGIC) {
    167  1.1  soren 		printf("No SGI volumn header found, magic=%x\n", volhdr->magic);
    168  1.1  soren 		exit(1);
    169  1.1  soren 	}
    170  1.1  soren 	if (opt_r) {
    171  1.1  soren 		read_file();
    172  1.1  soren 		exit(0);
    173  1.1  soren 	}
    174  1.1  soren 	if (opt_w) {
    175  1.1  soren 		write_file();
    176  1.1  soren 		exit(0);
    177  1.1  soren 	}
    178  1.1  soren 	if (opt_d) {
    179  1.1  soren 		delete_file();
    180  1.1  soren 		exit(0);
    181  1.1  soren 	}
    182  1.1  soren 	if (opt_p) {
    183  1.1  soren 		modify_partition();
    184  1.1  soren 		exit(0);
    185  1.1  soren 	}
    186  1.1  soren 	display_vol();
    187  1.1  soren 
    188  1.1  soren 	return 0;
    189  1.1  soren }
    190  1.1  soren 
    191  1.1  soren display_vol()
    192  1.1  soren {
    193  1.1  soren 	printf("disklabel shows %d sectors\n", lbl.d_secperunit);
    194  1.1  soren 	l = (long *)buf;
    195  1.1  soren 	checksum = 0;
    196  1.1  soren 	for (n = 0; n < 512 / 4; ++n)
    197  1.1  soren 		checksum += l[n];
    198  1.1  soren 	printf("checksum: %08x%s\n", checksum, checksum == 0 ? "" : " *ERROR*");
    199  1.1  soren 	printf("root part: %d\n", volhdr->root);
    200  1.1  soren 	printf("swap part: %d\n", volhdr->swap);
    201  1.1  soren 	printf("bootfile: %\n", volhdr->bootfile);
    202  1.1  soren 	/* volhdr->devparams[0..47] */
    203  1.1  soren 	printf("\nVolume header files:\n");
    204  1.1  soren 	for (n = 0; n < 15; ++n)
    205  1.1  soren 		if (volhdr->voldir[n].name[0])
    206  1.1  soren 			printf("%-8s offset %4d blocks, length %8d bytes (%d blocks)\n",
    207  1.1  soren 			    volhdr->voldir[n].name, volhdr->voldir[n].block,
    208  1.1  soren 			    volhdr->voldir[n].bytes, (volhdr->voldir[n].bytes + 511 ) / 512);
    209  1.1  soren 	printf("\nSGI partitions:\n");
    210  1.1  soren 	for (n = 0; n < MAXPARTITIONS; ++n)
    211  1.1  soren 		if (volhdr->partitions[n].blocks)
    212  1.1  soren 			printf("%2d:%c blocks %8d first %8d type %2d (%s)\n", n, n + 'a',
    213  1.1  soren 			    volhdr->partitions[n].blocks, volhdr->partitions[n].first,
    214  1.1  soren 			    volhdr->partitions[n].type,
    215  1.1  soren 			    volhdr->partitions[n].type > 13 ? "???" :
    216  1.1  soren 			    sgi_types[volhdr->partitions[n].type]);
    217  1.1  soren }
    218  1.1  soren 
    219  1.1  soren init_volhdr()
    220  1.1  soren {
    221  1.1  soren 	memset(buf, 0, sizeof(buf));
    222  1.1  soren 	volhdr->magic = SGILABEL_MAGIC;
    223  1.1  soren 	volhdr->root = 0;
    224  1.1  soren 	volhdr->swap = 1;
    225  1.1  soren 	strcpy(volhdr->bootfile, "netbsd");
    226  1.1  soren         volhdr->dp.dp_skew = lbl.d_trackskew;
    227  1.1  soren         volhdr->dp.dp_gap1 = 1; /* XXX */
    228  1.1  soren         volhdr->dp.dp_gap2 = 1; /* XXX */
    229  1.1  soren         volhdr->dp.dp_cyls = lbl.d_ncylinders;
    230  1.1  soren         volhdr->dp.dp_shd0 = 0;
    231  1.1  soren         volhdr->dp.dp_trks0 = lbl.d_ntracks;
    232  1.1  soren         volhdr->dp.dp_secs = lbl.d_nsectors;
    233  1.1  soren         volhdr->dp.dp_secbytes = lbl.d_secsize;
    234  1.1  soren         volhdr->dp.dp_interleave = lbl.d_interleave;
    235  1.1  soren         volhdr->dp.dp_nretries = 22;
    236  1.1  soren 	volhdr->partitions[10].blocks = lbl.d_secperunit;
    237  1.1  soren 	volhdr->partitions[10].first = 0;
    238  1.1  soren 	volhdr->partitions[10].type = SGI_PTYPE_VOLUME;
    239  1.1  soren 	volhdr->partitions[8].blocks = SGI_SIZE_VOLHDR;
    240  1.1  soren 	volhdr->partitions[8].first = 0;
    241  1.1  soren 	volhdr->partitions[8].type = SGI_PTYPE_VOLHDR;
    242  1.1  soren 	volhdr->partitions[0].blocks = lbl.d_secperunit - SGI_SIZE_VOLHDR;
    243  1.1  soren 	volhdr->partitions[0].first = SGI_SIZE_VOLHDR;
    244  1.1  soren 	volhdr->partitions[0].type = SGI_PTYPE_EFS;
    245  1.1  soren 	write_volhdr();
    246  1.1  soren }
    247  1.1  soren 
    248  1.1  soren read_file()
    249  1.1  soren {
    250  1.1  soren 	FILE *fp;
    251  1.1  soren 
    252  1.1  soren 	printf("Reading file %s\n", vfilename);
    253  1.1  soren 	for (n = 0; n < 15; ++n) {
    254  1.1  soren 		if (strcmp(vfilename, volhdr->voldir[n].name) == NULL)
    255  1.1  soren 			break;
    256  1.1  soren 	}
    257  1.1  soren 	if (n >= 15) {
    258  1.1  soren 		printf("file %s not found\n", vfilename);
    259  1.1  soren 		exit(1);
    260  1.1  soren 	}
    261  1.1  soren 	/* XXX assumes volume header starts at 0? */
    262  1.1  soren 	lseek(fd, volhdr->voldir[n].block * 512, SEEK_SET);
    263  1.1  soren 	fp = fopen(ufilename, "w");
    264  1.1  soren 	if (fp == NULL) {
    265  1.1  soren 		perror("open write");
    266  1.1  soren 		exit(1);
    267  1.1  soren 	}
    268  1.1  soren 	n = volhdr->voldir[n].bytes;
    269  1.1  soren 	while (n > 0) {
    270  1.1  soren 		if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
    271  1.1  soren 			perror("read file");
    272  1.1  soren 			exit(1);
    273  1.1  soren 		}
    274  1.1  soren 		fwrite(buf, 1, n > sizeof(buf) ? sizeof(buf) : n, fp);
    275  1.1  soren 		n -= n > sizeof(buf) ? sizeof(buf) : n;
    276  1.1  soren 	}
    277  1.1  soren 	fclose(fp);
    278  1.1  soren }
    279  1.1  soren 
    280  1.1  soren write_file()
    281  1.1  soren {
    282  1.1  soren 	FILE *fp;
    283  1.1  soren 	int fileno;
    284  1.1  soren 	int block, bytes;
    285  1.1  soren 	struct stat st;
    286  1.1  soren 	char fbuf[512];
    287  1.1  soren 
    288  1.1  soren 	printf("Writing file %s\n", ufilename);
    289  1.1  soren 	if (stat(ufilename, &st) < 0) {
    290  1.1  soren 		perror("stat");
    291  1.1  soren 		exit(1);
    292  1.1  soren 	}
    293  1.1  soren 	printf("File %s has %lld bytes\n", ufilename, st.st_size);
    294  1.1  soren 	fileno = -1;
    295  1.1  soren 	for (n = 0; n < 15; ++n) {
    296  1.1  soren 		if (volhdr->voldir[n].name[0] == '\0' && fileno < 0)
    297  1.1  soren 			fileno = n;
    298  1.1  soren 		if (strcmp(vfilename, volhdr->voldir[n].name) == 0) {
    299  1.1  soren 			fileno = n;
    300  1.1  soren 			break;
    301  1.1  soren 		}
    302  1.1  soren 	}
    303  1.1  soren 	if (fileno == -1) {
    304  1.1  soren 		printf("No directory space for file %\n", vfilename);
    305  1.1  soren 		exit(1);
    306  1.1  soren 	}
    307  1.1  soren 	/* -w can overwrite, -a won't overwrite */
    308  1.1  soren 	if (volhdr->voldir[fileno].block > 0) {
    309  1.1  soren 		printf("File %s exists, removing old file\n", vfilename);
    310  1.1  soren 		volhdr->voldir[fileno].name[0] = 0;
    311  1.1  soren 		volhdr->voldir[fileno].block = volhdr->voldir[fileno].bytes = 0;
    312  1.1  soren 	}
    313  1.1  soren 	if (st.st_size == 0) {
    314  1.1  soren 		printf("bad file size?\n");
    315  1.1  soren 		exit(1);
    316  1.1  soren 	}
    317  1.1  soren 	/* XXX assumes volume header starts at 0? */
    318  1.1  soren 	block = allocate_space((int)st.st_size);
    319  1.1  soren 	if (block < 0) {
    320  1.1  soren 		printf("No space for file\n");
    321  1.1  soren 		exit(1);
    322  1.1  soren 	}
    323  1.1  soren 
    324  1.1  soren 	/* Make sure name in volume header is max. 8 chars including NUL */
    325  1.1  soren 	if (strlen(vfilename) > sizeof(volhdr->voldir[fileno].name) - 1) {
    326  1.1  soren 		printf("Warning: '%s' is too long for volume header, ",
    327  1.1  soren 		       vfilename);
    328  1.1  soren 		vfilename[sizeof(volhdr->voldir[fileno].name) - 1] = '\0';
    329  1.1  soren 		printf("truncating to '%s'\n", vfilename);
    330  1.1  soren 	}
    331  1.1  soren 
    332  1.1  soren 	strcpy(volhdr->voldir[fileno].name, vfilename);
    333  1.1  soren 	volhdr->voldir[fileno].block = block;
    334  1.1  soren 	volhdr->voldir[fileno].bytes = st.st_size;
    335  1.1  soren 
    336  1.1  soren 	write_volhdr();
    337  1.1  soren 
    338  1.1  soren 	/* write the file itself */
    339  1.1  soren 	n = lseek(fd, block * 512, SEEK_SET);
    340  1.1  soren 	if (n < 0) {
    341  1.1  soren 		perror("lseek write");
    342  1.1  soren 		exit(1);
    343  1.1  soren 	}
    344  1.1  soren 	n = st.st_size;
    345  1.1  soren 	fp = fopen(ufilename, "r");
    346  1.1  soren 	while (n > 0) {
    347  1.1  soren 		fread(fbuf, 1, n > 512 ? 512 : n, fp);
    348  1.1  soren 		if (write(fd, fbuf, 512) != 512) {
    349  1.1  soren 			perror("write file");
    350  1.1  soren 			exit(1);
    351  1.1  soren 		}
    352  1.1  soren 		n -= n > 512 ? 512 : n;
    353  1.1  soren 	}
    354  1.1  soren }
    355  1.1  soren 
    356  1.1  soren delete_file()
    357  1.1  soren {
    358  1.1  soren 	for (n = 0; n < 15; ++n) {
    359  1.1  soren 		if (strcmp(vfilename, volhdr->voldir[n].name) == NULL) {
    360  1.1  soren 			break;
    361  1.1  soren 		}
    362  1.1  soren 	}
    363  1.1  soren 	if (n >= 15) {
    364  1.1  soren 		printf("File %s not found\n", vfilename);
    365  1.1  soren 		exit(1);
    366  1.1  soren 	}
    367  1.1  soren 	volhdr->voldir[n].name[0] = '\0';
    368  1.1  soren 	volhdr->voldir[n].block = volhdr->voldir[n].bytes = 0;
    369  1.1  soren 	write_volhdr();
    370  1.1  soren }
    371  1.1  soren 
    372  1.1  soren modify_partition()
    373  1.1  soren {
    374  1.1  soren 	printf("Modify partition %d start %d length %d\n", partno, partfirst, partblocks);
    375  1.1  soren 	if (partno < 0 || partno > 15) {
    376  1.1  soren 		printf("Invalue partition number: %d\n", partno);
    377  1.1  soren 		exit(1);
    378  1.1  soren 	}
    379  1.1  soren 	volhdr->partitions[partno].blocks = partblocks;
    380  1.1  soren 	volhdr->partitions[partno].first = partfirst;
    381  1.1  soren 	volhdr->partitions[partno].type = parttype;
    382  1.1  soren 	write_volhdr();
    383  1.1  soren }
    384  1.1  soren 
    385  1.1  soren write_volhdr()
    386  1.1  soren {
    387  1.1  soren 	checksum_vol();
    388  1.1  soren 	display_vol();
    389  1.1  soren 	printf("\nDo you want to update volume (y/n)? ");
    390  1.1  soren 	n = getchar();
    391  1.1  soren 	if (n != 'Y' && n != 'y')
    392  1.1  soren 		exit(1);
    393  1.1  soren 	n = lseek(fd, 0 , SEEK_SET);
    394  1.1  soren 	if (n < 0) {
    395  1.1  soren 		perror("lseek 0");
    396  1.1  soren 		exit(1);
    397  1.1  soren 	}
    398  1.1  soren 	n = write(fd, buf, 512);
    399  1.1  soren 	if (n < 0)
    400  1.1  soren 		perror("write volhdr");
    401  1.1  soren }
    402  1.1  soren 
    403  1.1  soren /*
    404  1.1  soren  */
    405  1.1  soren allocate_space(size)
    406  1.1  soren 	int size;
    407  1.1  soren {
    408  1.1  soren 	int n, blocks;
    409  1.1  soren 	int first;
    410  1.1  soren 
    411  1.1  soren 	blocks = (size + 511) / 512;
    412  1.1  soren 	first = 2;
    413  1.1  soren 	n = 0;
    414  1.1  soren 	while (n < 15) {
    415  1.1  soren 		if (volhdr->voldir[n].name[0]) {
    416  1.1  soren 			if (first < (volhdr->voldir[n].block +
    417  1.1  soren 			    (volhdr->voldir[n].bytes + 511) / 512) &&
    418  1.1  soren 			    (first + blocks) >= volhdr->voldir[n].block) {
    419  1.1  soren 				first = volhdr->voldir[n].block +
    420  1.1  soren 				    (volhdr->voldir[n].bytes + 511) / 512;
    421  1.1  soren #if 0
    422  1.1  soren printf("allocate: n=%d first=%d blocks=%d size=%d\n", n, first, blocks, size);
    423  1.1  soren printf("%s %d %d\n", volhdr->voldir[n].name, volhdr->voldir[n].block, volhdr->voldir[n].bytes);
    424  1.1  soren printf("first=%d block=%d last=%d end=%d\n", first, volhdr->voldir[n].block,
    425  1.1  soren     first + blocks - 1, volhdr->voldir[n].block + (volhdr->voldir[n].bytes + 511)/512);
    426  1.1  soren #endif
    427  1.1  soren 				n = 0;
    428  1.1  soren 				continue;
    429  1.1  soren 			}
    430  1.1  soren 		}
    431  1.1  soren 		++n;
    432  1.1  soren 	}
    433  1.1  soren 	if (first + blocks > lbl.d_secperunit)
    434  1.1  soren 		first = -1;
    435  1.1  soren 	/* XXX assumes volume header is partition 8 */
    436  1.1  soren 	/* XXX assumes volume header starts at 0? */
    437  1.1  soren 	if (first + blocks >= volhdr->partitions[8].blocks)
    438  1.1  soren 		first = -1;
    439  1.1  soren 	return(first);
    440  1.1  soren }
    441  1.1  soren 
    442  1.1  soren checksum_vol()
    443  1.1  soren {
    444  1.1  soren 	volhdr->checksum = checksum = 0;
    445  1.1  soren 	l = (long *)buf;
    446  1.1  soren 	for (n = 0; n < 512 / 4; ++n)
    447  1.1  soren 		checksum += l[n];
    448  1.1  soren 	volhdr->checksum = -checksum;
    449  1.1  soren }
    450  1.1  soren 
    451  1.1  soren usage()
    452  1.1  soren {
    453  1.1  soren 	printf("Usage:  sgivol [-i] device\n"
    454  1.1  soren 	       "        sgivol [-r vhfilename diskfilename] device\n"
    455  1.1  soren 	       "        sgivol [-w vhfilename diskfilename] device\n"
    456  1.1  soren 	       "        sgivol [-d vhfilename] device\n"
    457  1.1  soren 	       );
    458  1.1  soren 	exit(0);
    459  1.1  soren }
    460