Home | History | Annotate | Line # | Download | only in sgivol
sgivol.c revision 1.5.6.2
      1  1.5.6.1    skrll /*	$NetBSD: sgivol.c,v 1.5.6.2 2004/09/18 14:39:54 skrll 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.2  thorpej #include <sys/types.h>
     40      1.2  thorpej #include <sys/ioctl.h>
     41      1.2  thorpej #include <sys/stat.h>
     42  1.5.6.1    skrll #include <sys/disklabel.h>
     43      1.2  thorpej 
     44      1.5    rafal #include <errno.h>
     45      1.1    soren #include <stdio.h>
     46      1.2  thorpej #include <stdlib.h>
     47      1.1    soren #include <unistd.h>
     48      1.1    soren #include <string.h>
     49      1.1    soren #include <fcntl.h>
     50      1.1    soren #include <util.h>
     51  1.5.6.1    skrll #include <sys/endian.h>
     52      1.1    soren 
     53      1.5    rafal /*
     54      1.5    rafal  * Some IRIX man pages refer to the size being a multiple of whole cylinders.
     55      1.5    rafal  * Later ones only refer to the size being "typically" 2MB.  IRIX fx(1)
     56      1.5    rafal  * uses a default drive geometry if one can't be determined, suggesting
     57      1.5    rafal  * that "whole cylinder" multiples are not required.
     58      1.5    rafal  */
     59      1.5    rafal 
     60  1.5.6.1    skrll #define SGI_SIZE_VOLHDR	3135	/* Can be overridden via -h parameter */
     61  1.5.6.1    skrll 
     62  1.5.6.1    skrll struct local_devparms {
     63  1.5.6.1    skrll 	u_int8_t        dp_skew;
     64  1.5.6.1    skrll 	u_int8_t        dp_gap1;
     65  1.5.6.1    skrll 	u_int8_t        dp_gap2;
     66  1.5.6.1    skrll 	u_int8_t        dp_spares_cyl;
     67  1.5.6.1    skrll 	u_int16_t       dp_cyls;
     68  1.5.6.1    skrll 	u_int16_t       dp_shd0;
     69  1.5.6.1    skrll 	u_int16_t       dp_trks0;
     70  1.5.6.1    skrll 	u_int8_t        dp_ctq_depth;
     71  1.5.6.1    skrll 	u_int8_t        dp_cylshi;
     72  1.5.6.1    skrll 	u_int16_t       dp_unused;
     73  1.5.6.1    skrll 	u_int16_t       dp_secs;
     74  1.5.6.1    skrll 	u_int16_t       dp_secbytes;
     75  1.5.6.1    skrll 	u_int16_t       dp_interleave;
     76  1.5.6.1    skrll 	u_int32_t       dp_flags;
     77  1.5.6.1    skrll 	u_int32_t       dp_datarate;
     78  1.5.6.1    skrll 	u_int32_t       dp_nretries;
     79  1.5.6.1    skrll 	u_int32_t       dp_mspw;
     80  1.5.6.1    skrll 	u_int16_t       dp_xgap1;
     81  1.5.6.1    skrll 	u_int16_t       dp_xsync;
     82  1.5.6.1    skrll 	u_int16_t       dp_xrdly;
     83  1.5.6.1    skrll 	u_int16_t       dp_xgap2;
     84  1.5.6.1    skrll 	u_int16_t       dp_xrgate;
     85  1.5.6.1    skrll 	u_int16_t       dp_xwcont;
     86  1.5.6.1    skrll }               __attribute__((__packed__));
     87  1.5.6.1    skrll 
     88  1.5.6.1    skrll struct local_sgilabel {
     89  1.5.6.1    skrll #define SGILABEL_MAGIC  0xbe5a941
     90  1.5.6.1    skrll 	u_int32_t       magic;
     91  1.5.6.1    skrll 	int16_t         root;
     92  1.5.6.1    skrll 	int16_t         swap;
     93  1.5.6.1    skrll 	char            bootfile[16];
     94  1.5.6.1    skrll 	struct local_devparms dp;
     95  1.5.6.1    skrll 	struct {
     96  1.5.6.1    skrll 		char            name[8];
     97  1.5.6.1    skrll 		int32_t         block;
     98  1.5.6.1    skrll 		int32_t         bytes;
     99  1.5.6.1    skrll 	}               voldir[15];
    100  1.5.6.1    skrll 	struct {
    101  1.5.6.1    skrll 		int32_t         blocks;
    102  1.5.6.1    skrll 		int32_t         first;
    103  1.5.6.1    skrll 		int32_t         type;
    104  1.5.6.1    skrll 	}               partitions[MAXPARTITIONS];
    105  1.5.6.1    skrll 	int32_t         checksum;
    106  1.5.6.1    skrll 	int32_t         _pad;
    107  1.5.6.1    skrll }               __attribute__((__packed__));
    108  1.5.6.1    skrll 
    109  1.5.6.1    skrll #define SGI_PTYPE_VOLHDR        0
    110  1.5.6.1    skrll #define SGI_PTYPE_RAW           3
    111  1.5.6.1    skrll #define SGI_PTYPE_BSD           4
    112  1.5.6.1    skrll #define SGI_PTYPE_VOLUME        6
    113  1.5.6.1    skrll #define SGI_PTYPE_EFS           7
    114  1.5.6.1    skrll #define SGI_PTYPE_LVOL          8
    115  1.5.6.1    skrll #define SGI_PTYPE_RLVOL         9
    116  1.5.6.1    skrll #define SGI_PTYPE_XFS           10
    117  1.5.6.1    skrll #define SGI_PTYPE_XFSLOG        11
    118  1.5.6.1    skrll #define SGI_PTYPE_XLV           12
    119  1.5.6.1    skrll #define SGI_PTYPE_XVM           13
    120      1.1    soren 
    121      1.1    soren int	fd;
    122      1.1    soren int	opt_i;			/* Initialize volume header */
    123      1.1    soren int	opt_r;			/* Read a file from volume header */
    124      1.1    soren int	opt_w;			/* Write a file to volume header */
    125      1.1    soren int	opt_d;			/* Delete a file from volume header */
    126      1.1    soren int	opt_p;			/* Modify a partition */
    127      1.5    rafal int	opt_q;			/* quiet mode */
    128      1.5    rafal int	opt_f;			/* Don't ask, just do what you're told */
    129      1.1    soren int	partno, partfirst, partblocks, parttype;
    130  1.5.6.1    skrll struct local_sgilabel *volhdr;
    131      1.2  thorpej int32_t	checksum;
    132  1.5.6.1    skrll u_int32_t	volhdr_size = SGI_SIZE_VOLHDR;
    133      1.2  thorpej 
    134      1.2  thorpej const char *vfilename = "";
    135      1.2  thorpej const char *ufilename = "";
    136      1.1    soren 
    137      1.1    soren struct disklabel lbl;
    138      1.1    soren 
    139      1.1    soren unsigned char buf[512];
    140      1.1    soren 
    141      1.2  thorpej const char *sgi_types[] = {
    142      1.1    soren 	"Volume Header",
    143      1.1    soren 	"Repl Trks",
    144      1.1    soren 	"Repl Secs",
    145      1.1    soren 	"Raw",
    146      1.1    soren 	"BSD4.2",
    147      1.1    soren 	"SysV",
    148      1.1    soren 	"Volume",
    149      1.1    soren 	"EFS",
    150      1.1    soren 	"LVol",
    151      1.1    soren 	"RLVol",
    152      1.1    soren 	"XFS",
    153      1.1    soren 	"XSFLog",
    154      1.1    soren 	"XLV",
    155      1.1    soren 	"XVM"
    156      1.1    soren };
    157      1.1    soren 
    158      1.2  thorpej int	main(int, char *[]);
    159      1.2  thorpej 
    160      1.2  thorpej void	display_vol(void);
    161      1.2  thorpej void	init_volhdr(void);
    162      1.2  thorpej void	read_file(void);
    163      1.2  thorpej void	write_file(void);
    164      1.2  thorpej void	delete_file(void);
    165      1.2  thorpej void	modify_partition(void);
    166      1.2  thorpej void	write_volhdr(void);
    167      1.2  thorpej int	allocate_space(int);
    168      1.2  thorpej void	checksum_vol(void);
    169      1.2  thorpej void	usage(void);
    170      1.2  thorpej 
    171      1.2  thorpej int
    172      1.2  thorpej main(int argc, char *argv[])
    173      1.1    soren {
    174      1.5    rafal 	int ch;
    175  1.5.6.1    skrll 	while ((ch = getopt(argc, argv, "irwpdqfh:")) != -1) {
    176      1.5    rafal 		switch (ch) {
    177      1.5    rafal 		/* -i, -r, -w, -d and -p override each other */
    178      1.5    rafal 		/* -q implies -f */
    179      1.5    rafal 		case 'q':
    180      1.5    rafal 			++opt_q;
    181      1.5    rafal 			++opt_f;
    182      1.5    rafal 			break;
    183      1.5    rafal 		case 'f':
    184      1.5    rafal 			++opt_f;
    185      1.5    rafal 			break;
    186      1.1    soren 		case 'i':
    187      1.1    soren 			++opt_i;
    188      1.5    rafal 			opt_r = opt_w = opt_d = opt_p = 0;
    189      1.1    soren 			break;
    190  1.5.6.1    skrll 		case 'h':
    191  1.5.6.1    skrll 			volhdr_size = atoi(optarg);
    192  1.5.6.1    skrll 			break;
    193      1.1    soren 		case 'r':
    194      1.5    rafal 			++opt_r;
    195      1.5    rafal 			opt_i = opt_w = opt_d = opt_p = 0;
    196      1.5    rafal 			break;
    197      1.1    soren 		case 'w':
    198      1.5    rafal 			++opt_w;
    199      1.5    rafal 			opt_i = opt_r = opt_d = opt_p = 0;
    200      1.1    soren 			break;
    201      1.1    soren 		case 'd':
    202      1.1    soren 			++opt_d;
    203      1.5    rafal 			opt_i = opt_r = opt_w = opt_p = 0;
    204      1.5    rafal 			break;
    205      1.1    soren 		case 'p':
    206      1.1    soren 			++opt_p;
    207      1.5    rafal 			opt_i = opt_r = opt_w = opt_d = 0;
    208      1.5    rafal 			partno = atoi(argv[0]);
    209      1.5    rafal 			partfirst = atoi(argv[1]);
    210      1.5    rafal 			partblocks = atoi(argv[2]);
    211      1.5    rafal 			parttype = atoi(argv[3]);
    212      1.1    soren 			break;
    213      1.5    rafal 		case '?':
    214      1.1    soren 		default:
    215      1.1    soren 			usage();
    216      1.1    soren 		}
    217      1.1    soren 	}
    218      1.5    rafal 	argc -= optind;
    219      1.5    rafal 	argv += optind;
    220      1.5    rafal 
    221      1.5    rafal 	if (opt_r || opt_w) {
    222      1.5    rafal 		if (argc != 3)
    223      1.5    rafal 			usage();
    224      1.5    rafal 		vfilename = argv[0];
    225      1.5    rafal 		ufilename = argv[1];
    226      1.5    rafal 		argc -= 2;
    227      1.5    rafal 		argv += 2;
    228      1.5    rafal 	}
    229      1.5    rafal 	if (opt_d) {
    230      1.5    rafal 		if (argc != 2)
    231      1.5    rafal 			usage();
    232      1.5    rafal 		vfilename = argv[0];
    233      1.5    rafal 		argc--;
    234      1.5    rafal 		argv++;
    235      1.5    rafal 	}
    236      1.1    soren 
    237      1.5    rafal 	if (opt_p) {
    238      1.5    rafal 		if (argc != 5)
    239      1.5    rafal 			usage();
    240      1.5    rafal 		partno = atoi(argv[0]);
    241      1.5    rafal 		partfirst = atoi(argv[1]);
    242      1.5    rafal 		partblocks = atoi(argv[2]);
    243      1.5    rafal 		parttype = atoi(argv[3]);
    244      1.5    rafal 		argc -= 4;
    245      1.5    rafal 		argv += 4;
    246      1.5    rafal 	}
    247      1.5    rafal 	if (argc != 1)
    248      1.1    soren 		usage();
    249      1.5    rafal 
    250      1.5    rafal 	fd = open(argv[0], (opt_i | opt_w | opt_d | opt_p) ? O_RDWR : O_RDONLY);
    251      1.1    soren 	if (fd < 0) {
    252      1.5    rafal 		sprintf(buf, "/dev/r%s%c", argv[0], 'a' + getrawpartition());
    253      1.5    rafal 		fd = open(buf, (opt_i | opt_w | opt_d | opt_p)
    254      1.5    rafal 				? O_RDWR : O_RDONLY);
    255      1.1    soren 		if (fd < 0) {
    256      1.5    rafal 			printf("Error opening device %s: %s\n",
    257      1.5    rafal 				argv[0], strerror(errno));
    258      1.1    soren 			exit(1);
    259      1.1    soren 		}
    260      1.1    soren 	}
    261      1.2  thorpej 	if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
    262      1.1    soren 		perror("read volhdr");
    263      1.1    soren 		exit(1);
    264      1.1    soren 	}
    265      1.2  thorpej 	if (ioctl(fd, DIOCGDINFO, &lbl) < 0) {
    266      1.1    soren 		perror("DIOCGDINFO");
    267      1.1    soren 		exit(1);
    268      1.1    soren 	}
    269  1.5.6.1    skrll 	volhdr = (struct local_sgilabel *) buf;
    270      1.1    soren 	if (opt_i) {
    271      1.1    soren 		init_volhdr();
    272      1.1    soren 		exit(0);
    273      1.1    soren 	}
    274  1.5.6.1    skrll 	if (be32toh(volhdr->magic) != SGILABEL_MAGIC) {
    275      1.5    rafal 		printf("No Volume Header found, magic=%x.  Use -i first.\n",
    276  1.5.6.1    skrll 		       be32toh(volhdr->magic));
    277      1.1    soren 		exit(1);
    278      1.1    soren 	}
    279      1.1    soren 	if (opt_r) {
    280      1.1    soren 		read_file();
    281      1.1    soren 		exit(0);
    282      1.1    soren 	}
    283      1.1    soren 	if (opt_w) {
    284      1.1    soren 		write_file();
    285      1.1    soren 		exit(0);
    286      1.1    soren 	}
    287      1.1    soren 	if (opt_d) {
    288      1.1    soren 		delete_file();
    289      1.1    soren 		exit(0);
    290      1.1    soren 	}
    291      1.1    soren 	if (opt_p) {
    292      1.1    soren 		modify_partition();
    293      1.1    soren 		exit(0);
    294      1.1    soren 	}
    295      1.5    rafal 
    296      1.5    rafal 	if (!opt_q)
    297      1.5    rafal 		display_vol();
    298      1.1    soren 
    299      1.1    soren 	return 0;
    300      1.1    soren }
    301      1.1    soren 
    302      1.2  thorpej void
    303      1.2  thorpej display_vol(void)
    304      1.1    soren {
    305      1.2  thorpej 	int32_t *l;
    306      1.2  thorpej 	int i;
    307      1.2  thorpej 
    308      1.1    soren 	printf("disklabel shows %d sectors\n", lbl.d_secperunit);
    309      1.2  thorpej 	l = (int32_t *)buf;
    310      1.1    soren 	checksum = 0;
    311      1.2  thorpej 	for (i = 0; i < 512 / 4; ++i)
    312  1.5.6.1    skrll 		checksum += be32toh(l[i]);
    313      1.1    soren 	printf("checksum: %08x%s\n", checksum, checksum == 0 ? "" : " *ERROR*");
    314  1.5.6.1    skrll 	printf("root part: %d\n", be16toh(volhdr->root));
    315  1.5.6.1    skrll 	printf("swap part: %d\n", be16toh(volhdr->swap));
    316      1.2  thorpej 	printf("bootfile: %s\n", volhdr->bootfile);
    317      1.1    soren 	/* volhdr->devparams[0..47] */
    318      1.1    soren 	printf("\nVolume header files:\n");
    319      1.2  thorpej 	for (i = 0; i < 15; ++i)
    320      1.2  thorpej 		if (volhdr->voldir[i].name[0])
    321      1.1    soren 			printf("%-8s offset %4d blocks, length %8d bytes (%d blocks)\n",
    322  1.5.6.1    skrll 			       volhdr->voldir[i].name, be32toh(volhdr->voldir[i].block),
    323  1.5.6.1    skrll 			       be32toh(volhdr->voldir[i].bytes), (be32toh(volhdr->voldir[i].bytes) + 511) / 512);
    324      1.1    soren 	printf("\nSGI partitions:\n");
    325      1.2  thorpej 	for (i = 0; i < MAXPARTITIONS; ++i) {
    326  1.5.6.1    skrll 		if (be32toh(volhdr->partitions[i].blocks)) {
    327      1.2  thorpej 			printf("%2d:%c blocks %8d first %8d type %2d (%s)\n",
    328  1.5.6.1    skrll 			  i, i + 'a', be32toh(volhdr->partitions[i].blocks),
    329  1.5.6.1    skrll 			       be32toh(volhdr->partitions[i].first),
    330  1.5.6.1    skrll 			       be32toh(volhdr->partitions[i].type),
    331  1.5.6.1    skrll 			  be32toh(volhdr->partitions[i].type) > 13 ? "???" :
    332  1.5.6.1    skrll 			    sgi_types[be32toh(volhdr->partitions[i].type)]);
    333      1.2  thorpej 		}
    334      1.2  thorpej 	}
    335      1.1    soren }
    336      1.1    soren 
    337      1.2  thorpej void
    338      1.2  thorpej init_volhdr(void)
    339      1.1    soren {
    340      1.1    soren 	memset(buf, 0, sizeof(buf));
    341  1.5.6.1    skrll 	volhdr->magic = htobe32(SGILABEL_MAGIC);
    342  1.5.6.1    skrll 	volhdr->root = htobe16(0);
    343  1.5.6.1    skrll 	volhdr->swap = htobe16(1);
    344      1.2  thorpej 	strcpy(volhdr->bootfile, "/netbsd");
    345      1.4   simonb 	volhdr->dp.dp_skew = lbl.d_trackskew;
    346      1.4   simonb 	volhdr->dp.dp_gap1 = 1; /* XXX */
    347      1.4   simonb 	volhdr->dp.dp_gap2 = 1; /* XXX */
    348  1.5.6.1    skrll 	volhdr->dp.dp_cyls = htobe16(lbl.d_ncylinders);
    349      1.4   simonb 	volhdr->dp.dp_shd0 = 0;
    350  1.5.6.1    skrll 	volhdr->dp.dp_trks0 = htobe16(lbl.d_ntracks);
    351  1.5.6.1    skrll 	volhdr->dp.dp_secs = htobe16(lbl.d_nsectors);
    352  1.5.6.1    skrll 	volhdr->dp.dp_secbytes = htobe16(lbl.d_secsize);
    353  1.5.6.1    skrll 	volhdr->dp.dp_interleave = htobe16(lbl.d_interleave);
    354  1.5.6.1    skrll 	volhdr->dp.dp_nretries = htobe32(22);
    355  1.5.6.1    skrll 	volhdr->partitions[10].blocks = htobe32(lbl.d_secperunit);
    356      1.1    soren 	volhdr->partitions[10].first = 0;
    357  1.5.6.1    skrll 	volhdr->partitions[10].type = htobe32(SGI_PTYPE_VOLUME);
    358  1.5.6.1    skrll 	volhdr->partitions[8].blocks = htobe32(volhdr_size);
    359      1.1    soren 	volhdr->partitions[8].first = 0;
    360  1.5.6.1    skrll 	volhdr->partitions[8].type = htobe32(SGI_PTYPE_VOLHDR);
    361  1.5.6.1    skrll 	volhdr->partitions[0].blocks = htobe32(lbl.d_secperunit - volhdr_size);
    362  1.5.6.1    skrll 	volhdr->partitions[0].first = htobe32(volhdr_size);
    363  1.5.6.1    skrll 	volhdr->partitions[0].type = htobe32(SGI_PTYPE_BSD);
    364      1.1    soren 	write_volhdr();
    365      1.1    soren }
    366      1.1    soren 
    367      1.2  thorpej void
    368      1.2  thorpej read_file(void)
    369      1.1    soren {
    370      1.1    soren 	FILE *fp;
    371      1.2  thorpej 	int i;
    372      1.1    soren 
    373      1.5    rafal 	if (!opt_q)
    374      1.5    rafal 		printf("Reading file %s\n", vfilename);
    375      1.2  thorpej 	for (i = 0; i < 15; ++i) {
    376      1.3  thorpej 		if (strncmp(vfilename, volhdr->voldir[i].name,
    377  1.5.6.1    skrll 			    strlen(volhdr->voldir[i].name)) == 0)
    378      1.1    soren 			break;
    379      1.1    soren 	}
    380      1.2  thorpej 	if (i >= 15) {
    381      1.1    soren 		printf("file %s not found\n", vfilename);
    382      1.1    soren 		exit(1);
    383      1.1    soren 	}
    384      1.1    soren 	/* XXX assumes volume header starts at 0? */
    385  1.5.6.1    skrll 	lseek(fd, be32toh(volhdr->voldir[i].block) * 512, SEEK_SET);
    386      1.1    soren 	fp = fopen(ufilename, "w");
    387      1.1    soren 	if (fp == NULL) {
    388      1.1    soren 		perror("open write");
    389      1.1    soren 		exit(1);
    390      1.1    soren 	}
    391  1.5.6.1    skrll 	i = be32toh(volhdr->voldir[i].bytes);
    392      1.2  thorpej 	while (i > 0) {
    393      1.1    soren 		if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
    394      1.1    soren 			perror("read file");
    395      1.1    soren 			exit(1);
    396      1.1    soren 		}
    397      1.2  thorpej 		fwrite(buf, 1, i > sizeof(buf) ? sizeof(buf) : i, fp);
    398      1.2  thorpej 		i -= i > sizeof(buf) ? sizeof(buf) : i;
    399      1.1    soren 	}
    400      1.1    soren 	fclose(fp);
    401      1.1    soren }
    402      1.1    soren 
    403      1.2  thorpej void
    404      1.2  thorpej write_file(void)
    405      1.1    soren {
    406      1.1    soren 	FILE *fp;
    407      1.2  thorpej 	int slot;
    408      1.2  thorpej 	size_t namelen;
    409      1.2  thorpej 	int block, i;
    410      1.1    soren 	struct stat st;
    411      1.1    soren 	char fbuf[512];
    412      1.1    soren 
    413      1.5    rafal 	if (!opt_q)
    414      1.5    rafal 		printf("Writing file %s\n", ufilename);
    415      1.1    soren 	if (stat(ufilename, &st) < 0) {
    416      1.1    soren 		perror("stat");
    417      1.1    soren 		exit(1);
    418      1.1    soren 	}
    419      1.5    rafal 	if (!opt_q)
    420      1.5    rafal 		printf("File %s has %lld bytes\n", ufilename, st.st_size);
    421      1.2  thorpej 	slot = -1;
    422      1.2  thorpej 	for (i = 0; i < 15; ++i) {
    423      1.2  thorpej 		if (volhdr->voldir[i].name[0] == '\0' && slot < 0)
    424      1.2  thorpej 			slot = i;
    425      1.2  thorpej 		if (strcmp(vfilename, volhdr->voldir[i].name) == 0) {
    426      1.2  thorpej 			slot = i;
    427      1.1    soren 			break;
    428      1.1    soren 		}
    429      1.1    soren 	}
    430      1.2  thorpej 	if (slot == -1) {
    431      1.2  thorpej 		printf("No directory space for file %s\n", vfilename);
    432      1.1    soren 		exit(1);
    433      1.1    soren 	}
    434      1.1    soren 	/* -w can overwrite, -a won't overwrite */
    435  1.5.6.1    skrll 	if (be32toh(volhdr->voldir[slot].block) > 0) {
    436      1.5    rafal 		if (!opt_q)
    437      1.5    rafal 			printf("File %s exists, removing old file\n",
    438      1.5    rafal 				vfilename);
    439      1.2  thorpej 		volhdr->voldir[slot].name[0] = 0;
    440      1.2  thorpej 		volhdr->voldir[slot].block = volhdr->voldir[slot].bytes = 0;
    441      1.1    soren 	}
    442      1.1    soren 	if (st.st_size == 0) {
    443      1.5    rafal 		printf("bad file size\n");
    444      1.1    soren 		exit(1);
    445      1.1    soren 	}
    446      1.1    soren 	/* XXX assumes volume header starts at 0? */
    447      1.1    soren 	block = allocate_space((int)st.st_size);
    448      1.1    soren 	if (block < 0) {
    449      1.1    soren 		printf("No space for file\n");
    450      1.1    soren 		exit(1);
    451      1.1    soren 	}
    452      1.1    soren 
    453      1.2  thorpej 	/*
    454      1.2  thorpej 	 * Make sure the name in the volume header is max. 8 chars,
    455      1.2  thorpej 	 * NOT including NUL.
    456      1.2  thorpej 	 */
    457      1.2  thorpej 	namelen = strlen(vfilename);
    458      1.2  thorpej 	if (namelen > sizeof(volhdr->voldir[slot].name)) {
    459      1.1    soren 		printf("Warning: '%s' is too long for volume header, ",
    460      1.1    soren 		       vfilename);
    461      1.2  thorpej 		namelen = sizeof(volhdr->voldir[slot].name);
    462      1.2  thorpej 		printf("truncating to '%-8s'\n", vfilename);
    463      1.1    soren 	}
    464      1.4   simonb 
    465      1.2  thorpej 	/* Populate it w/ NULs */
    466      1.2  thorpej 	memset(volhdr->voldir[slot].name, 0,
    467      1.2  thorpej 	    sizeof(volhdr->voldir[slot].name));
    468      1.2  thorpej 	/* Then copy the name */
    469      1.2  thorpej 	memcpy(volhdr->voldir[slot].name, vfilename, namelen);
    470      1.2  thorpej 
    471  1.5.6.1    skrll 	volhdr->voldir[slot].block = htobe32(block);
    472  1.5.6.1    skrll 	volhdr->voldir[slot].bytes = htobe32(st.st_size);
    473      1.1    soren 
    474      1.1    soren 	write_volhdr();
    475      1.1    soren 
    476      1.1    soren 	/* write the file itself */
    477      1.2  thorpej 	i = lseek(fd, block * 512, SEEK_SET);
    478      1.2  thorpej 	if (i < 0) {
    479      1.1    soren 		perror("lseek write");
    480      1.1    soren 		exit(1);
    481      1.1    soren 	}
    482      1.2  thorpej 	i = st.st_size;
    483      1.1    soren 	fp = fopen(ufilename, "r");
    484      1.2  thorpej 	while (i > 0) {
    485      1.2  thorpej 		fread(fbuf, 1, i > 512 ? 512 : i, fp);
    486      1.1    soren 		if (write(fd, fbuf, 512) != 512) {
    487      1.1    soren 			perror("write file");
    488      1.1    soren 			exit(1);
    489      1.1    soren 		}
    490      1.2  thorpej 		i -= i > 512 ? 512 : i;
    491      1.1    soren 	}
    492      1.1    soren }
    493      1.1    soren 
    494      1.2  thorpej void
    495      1.2  thorpej delete_file(void)
    496      1.1    soren {
    497      1.2  thorpej 	int i;
    498      1.2  thorpej 
    499      1.2  thorpej 	for (i = 0; i < 15; ++i) {
    500  1.5.6.1    skrll 		if (strcmp(vfilename, volhdr->voldir[i].name) == 0) {
    501      1.1    soren 			break;
    502      1.1    soren 		}
    503      1.1    soren 	}
    504      1.2  thorpej 	if (i >= 15) {
    505      1.1    soren 		printf("File %s not found\n", vfilename);
    506      1.1    soren 		exit(1);
    507      1.1    soren 	}
    508      1.5    rafal 
    509      1.5    rafal 	/* XXX: we don't compact the file space, so get fragmentation */
    510      1.2  thorpej 	volhdr->voldir[i].name[0] = '\0';
    511      1.2  thorpej 	volhdr->voldir[i].block = volhdr->voldir[i].bytes = 0;
    512      1.1    soren 	write_volhdr();
    513      1.1    soren }
    514      1.1    soren 
    515      1.2  thorpej void
    516      1.2  thorpej modify_partition(void)
    517      1.1    soren {
    518      1.5    rafal 	if (!opt_q)
    519      1.5    rafal 		printf("Modify partition %d start %d length %d\n",
    520      1.5    rafal 			partno, partfirst, partblocks);
    521      1.1    soren 	if (partno < 0 || partno > 15) {
    522      1.5    rafal 		printf("Invalid partition number: %d\n", partno);
    523      1.1    soren 		exit(1);
    524      1.1    soren 	}
    525  1.5.6.1    skrll 	volhdr->partitions[partno].blocks = htobe32(partblocks);
    526  1.5.6.1    skrll 	volhdr->partitions[partno].first = htobe32(partfirst);
    527  1.5.6.1    skrll 	volhdr->partitions[partno].type = htobe32(parttype);
    528      1.1    soren 	write_volhdr();
    529      1.1    soren }
    530      1.1    soren 
    531      1.2  thorpej void
    532      1.2  thorpej write_volhdr(void)
    533      1.1    soren {
    534      1.2  thorpej 	int i;
    535      1.2  thorpej 
    536      1.1    soren 	checksum_vol();
    537      1.5    rafal 
    538      1.5    rafal 	if (!opt_q)
    539      1.5    rafal 		display_vol();
    540      1.5    rafal 	if (!opt_f) {
    541      1.5    rafal 		printf("\nDo you want to update volume (y/n)? ");
    542      1.5    rafal 		i = getchar();
    543      1.5    rafal 		if (i != 'Y' && i != 'y')
    544      1.5    rafal 			exit(1);
    545      1.5    rafal 	}
    546  1.5.6.1    skrll 	i = lseek(fd, 0, SEEK_SET);
    547      1.2  thorpej 	if (i < 0) {
    548      1.1    soren 		perror("lseek 0");
    549      1.1    soren 		exit(1);
    550      1.1    soren 	}
    551      1.2  thorpej 	i = write(fd, buf, 512);
    552      1.2  thorpej 	if (i < 0)
    553      1.1    soren 		perror("write volhdr");
    554      1.1    soren }
    555      1.1    soren 
    556      1.2  thorpej int
    557      1.2  thorpej allocate_space(int size)
    558      1.1    soren {
    559      1.1    soren 	int n, blocks;
    560      1.1    soren 	int first;
    561      1.1    soren 
    562      1.1    soren 	blocks = (size + 511) / 512;
    563      1.1    soren 	first = 2;
    564      1.1    soren 	n = 0;
    565      1.1    soren 	while (n < 15) {
    566      1.1    soren 		if (volhdr->voldir[n].name[0]) {
    567  1.5.6.1    skrll 			if (first < (be32toh(volhdr->voldir[n].block) +
    568  1.5.6.1    skrll 			  (be32toh(volhdr->voldir[n].bytes) + 511) / 512) &&
    569  1.5.6.1    skrll 			    (first + blocks) > be32toh(volhdr->voldir[n].block)) {
    570  1.5.6.1    skrll 				first = be32toh(volhdr->voldir[n].block) +
    571  1.5.6.1    skrll 					(be32toh(volhdr->voldir[n].bytes) + 511) / 512;
    572      1.1    soren #if 0
    573  1.5.6.1    skrll 				printf("allocate: n=%d first=%d blocks=%d size=%d\n", n, first, blocks, size);
    574  1.5.6.1    skrll 				printf("%s %d %d\n", volhdr->voldir[n].name, volhdr->voldir[n].block, volhdr->voldir[n].bytes);
    575  1.5.6.1    skrll 				printf("first=%d block=%d last=%d end=%d\n", first, volhdr->voldir[n].block,
    576  1.5.6.1    skrll 				       first + blocks - 1, volhdr->voldir[n].block + (volhdr->voldir[n].bytes + 511) / 512);
    577      1.1    soren #endif
    578      1.1    soren 				n = 0;
    579      1.1    soren 				continue;
    580      1.1    soren 			}
    581      1.1    soren 		}
    582      1.1    soren 		++n;
    583      1.1    soren 	}
    584      1.1    soren 	if (first + blocks > lbl.d_secperunit)
    585      1.1    soren 		first = -1;
    586      1.1    soren 	/* XXX assumes volume header is partition 8 */
    587      1.1    soren 	/* XXX assumes volume header starts at 0? */
    588  1.5.6.1    skrll 	if (first + blocks >= be32toh(volhdr->partitions[8].blocks))
    589      1.1    soren 		first = -1;
    590  1.5.6.1    skrll 	return (first);
    591      1.1    soren }
    592      1.1    soren 
    593      1.2  thorpej void
    594      1.2  thorpej checksum_vol(void)
    595      1.1    soren {
    596      1.2  thorpej 	int32_t *l;
    597      1.2  thorpej 	int i;
    598      1.2  thorpej 
    599      1.1    soren 	volhdr->checksum = checksum = 0;
    600      1.2  thorpej 	l = (int32_t *)buf;
    601      1.2  thorpej 	for (i = 0; i < 512 / 4; ++i)
    602  1.5.6.1    skrll 		checksum += be32toh(l[i]);
    603  1.5.6.1    skrll 	volhdr->checksum = htobe32(-checksum);
    604      1.1    soren }
    605      1.1    soren 
    606      1.2  thorpej void
    607      1.2  thorpej usage(void)
    608      1.1    soren {
    609  1.5.6.1    skrll 	printf("Usage:	sgivol [-qf] [-i] [-h vhsize] device\n"
    610      1.5    rafal 	       "	sgivol [-qf] [-r vhfilename diskfilename] device\n"
    611      1.5    rafal 	       "	sgivol [-qf] [-w vhfilename diskfilename] device\n"
    612      1.5    rafal 	       "	sgivol [-qf] [-d vhfilename] device\n"
    613      1.1    soren 	       );
    614      1.1    soren 	exit(0);
    615      1.1    soren }
    616