diff options
-rw-r--r-- | sys/arch/sgi/stand/sgivol/sgivol.c | 267 |
1 files changed, 121 insertions, 146 deletions
diff --git a/sys/arch/sgi/stand/sgivol/sgivol.c b/sys/arch/sgi/stand/sgivol/sgivol.c index 4d4604741c0..d2d2f640ee0 100644 --- a/sys/arch/sgi/stand/sgivol/sgivol.c +++ b/sys/arch/sgi/stand/sgivol/sgivol.c @@ -1,3 +1,4 @@ +/* $OpenBSD: sgivol.c,v 1.3 2004/11/08 21:24:46 miod Exp $ */ /* $NetBSD: sgivol.c,v 1.8 2003/11/08 04:59:00 sekiya Exp $ */ /*- @@ -36,19 +37,21 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/disklabel.h> - +#include <unistd.h> +#include <err.h> #include <errno.h> +#include <fcntl.h> #include <stdio.h> #include <stdlib.h> -#include <unistd.h> #include <string.h> -#include <fcntl.h> #include <util.h> + +#include <sys/disklabel.h> #include <sys/endian.h> +#include <sys/ioctl.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/types.h> /* * Some IRIX man pages refer to the size being a multiple of whole cylinders. @@ -83,7 +86,9 @@ struct local_devparms { u_int16_t dp_xgap2; u_int16_t dp_xrgate; u_int16_t dp_xwcont; -} __attribute__((__packed__)); +} __packed; + +#define SGI_SIZE_VOLDIR 15 struct local_sgilabel { #define SGILABEL_MAGIC 0xbe5a941 @@ -96,7 +101,7 @@ struct local_sgilabel { char name[8]; int32_t block; int32_t bytes; - } voldir[15]; + } voldir[SGI_SIZE_VOLDIR]; struct { int32_t blocks; int32_t first; @@ -104,7 +109,7 @@ struct local_sgilabel { } partitions[MAXPARTITIONS]; int32_t checksum; int32_t _pad; -} __attribute__((__packed__)); +} __packed; #define SGI_PTYPE_VOLHDR 0 #define SGI_PTYPE_RAW 3 @@ -136,7 +141,7 @@ const char *ufilename = ""; struct disklabel lbl; -unsigned char buf[512]; +unsigned char buf[DEV_BSIZE]; const char *sgi_types[] = { "Volume Header", @@ -155,8 +160,6 @@ const char *sgi_types[] = { "XVM" }; -int main(int, char *[]); - void display_vol(void); void init_volhdr(void); void read_file(void); @@ -172,6 +175,8 @@ int main(int argc, char *argv[]) { int ch; + char *endp; + while ((ch = getopt(argc, argv, "irwpdqfh:")) != -1) { switch (ch) { /* -i, -r, -w, -d and -p override each other */ @@ -188,7 +193,10 @@ main(int argc, char *argv[]) opt_r = opt_w = opt_d = opt_p = 0; break; case 'h': - volhdr_size = atoi(optarg); + volhdr_size = strtol(optarg, &endp, 0); + if (*endp != '\0' || errno != 0) + errx(1, "incorrect volume header size: %s", + optarg); break; case 'r': ++opt_r; @@ -205,12 +213,7 @@ main(int argc, char *argv[]) case 'p': ++opt_p; opt_i = opt_r = opt_w = opt_d = 0; - partno = atoi(argv[0]); - partfirst = atoi(argv[1]); - partblocks = atoi(argv[2]); - parttype = atoi(argv[3]); break; - case '?': default: usage(); } @@ -237,10 +240,19 @@ main(int argc, char *argv[]) if (opt_p) { if (argc != 5) usage(); - partno = atoi(argv[0]); - partfirst = atoi(argv[1]); - partblocks = atoi(argv[2]); - parttype = atoi(argv[3]); + partno = strtol(argv[0], &endp, 0); + if (*endp != '\0' || errno != 0 || + partno < 0 || partno > SGI_SIZE_VOLDIR) + errx(1, "invalid partition number: %s", argv[0]); + partfirst = strtol(argv[1], &endp, 0); + if (*endp != '\0' || errno != 0) + errx(1, "invalid partition start: %s", argv[1]); + partblocks = strtol(argv[2], &endp, 0); + if (*endp != '\0' || errno != 0) + errx(1, "invalid partition size: %s", argv[2]); + parttype = strtol(argv[3], &endp, 0); + if (*endp != '\0' || errno != 0) + errx(1, "invalid partition type: %s", argv[3]); argc -= 4; argv += 4; } @@ -249,33 +261,24 @@ main(int argc, char *argv[]) fd = open(argv[0], (opt_i | opt_w | opt_d | opt_p) ? O_RDWR : O_RDONLY); if (fd < 0) { - sprintf(buf, "/dev/r%s%c", argv[0], 'a' + getrawpartition()); - fd = open(buf, (opt_i | opt_w | opt_d | opt_p) - ? O_RDWR : O_RDONLY); - if (fd < 0) { - printf("Error opening device %s: %s\n", - argv[0], strerror(errno)); - exit(1); - } - } - if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { - perror("read volhdr"); - exit(1); - } - if (ioctl(fd, DIOCGDINFO, &lbl) < 0) { - perror("DIOCGDINFO"); - exit(1); - } - volhdr = (struct local_sgilabel *) buf; + snprintf(buf, sizeof(buf), "/dev/r%s%c", + argv[0], 'a' + getrawpartition()); + if ((fd = open(buf, + (opt_i | opt_w | opt_d | opt_p) ? O_RDWR : O_RDONLY)) < 0) + err(1, "open %s", buf); + } + if (read(fd, buf, sizeof(buf)) != sizeof(buf)) + err(1, "read volhdr"); + if (ioctl(fd, DIOCGDINFO, &lbl) == -1) + err(1, "ioctl DIOCGDINFO"); + volhdr = (struct local_sgilabel *)buf; if (opt_i) { init_volhdr(); exit(0); } - if (betoh32(volhdr->magic) != SGILABEL_MAGIC) { - printf("No Volume Header found, magic=%x. Use -i first.\n", - betoh32(volhdr->magic)); - exit(2); - } + if (betoh32(volhdr->magic) != SGILABEL_MAGIC) + errx(2, "no Volume Header found, magic=%x. Use -i first.", + betoh32(volhdr->magic)); if (opt_r) { read_file(); exit(0); @@ -296,7 +299,7 @@ main(int argc, char *argv[]) if (!opt_q) display_vol(); - return 0; + exit (0); } void @@ -308,7 +311,7 @@ display_vol(void) printf("disklabel shows %d sectors\n", lbl.d_secperunit); l = (int32_t *)buf; checksum = 0; - for (i = 0; i < 512 / 4; ++i) + for (i = 0; i < sizeof(buf) / sizeof(int32_t); ++i) checksum += betoh32(l[i]); printf("checksum: %08x%s\n", checksum, checksum == 0 ? "" : " *ERROR*"); printf("root part: %d\n", betoh32(volhdr->root)); @@ -316,20 +319,27 @@ display_vol(void) printf("bootfile: %s\n", volhdr->bootfile); /* volhdr->devparams[0..47] */ printf("\nVolume header files:\n"); - for (i = 0; i < 15; ++i) - if (volhdr->voldir[i].name[0]) + for (i = 0; i < SGI_SIZE_VOLDIR; ++i) { + if (volhdr->voldir[i].name[0] != '\0') { printf("%-8s offset %4d blocks, length %8d bytes (%d blocks)\n", - volhdr->voldir[i].name, betoh32(volhdr->voldir[i].block), - betoh32(volhdr->voldir[i].bytes), (betoh32(volhdr->voldir[i].bytes) + 511) / 512); + volhdr->voldir[i].name, + betoh32(volhdr->voldir[i].block), + betoh32(volhdr->voldir[i].bytes), + howmany(betoh32(volhdr->voldir[i].bytes), + DEV_BSIZE)); + } + } printf("\nSGI partitions:\n"); for (i = 0; i < MAXPARTITIONS; ++i) { - if (betoh32(volhdr->partitions[i].blocks)) { + if (betoh32(volhdr->partitions[i].blocks) != 0) { printf("%2d:%c blocks %8d first %8d type %2d (%s)\n", - i, i + 'a', betoh32(volhdr->partitions[i].blocks), - betoh32(volhdr->partitions[i].first), - betoh32(volhdr->partitions[i].type), - betoh32(volhdr->partitions[i].type) > 13 ? "???" : - sgi_types[betoh32(volhdr->partitions[i].type)]); + i, i + 'a', betoh32(volhdr->partitions[i].blocks), + betoh32(volhdr->partitions[i].first), + betoh32(volhdr->partitions[i].type), + betoh32(volhdr->partitions[i].type) > + (sizeof(sgi_types) / sizeof(sgi_types[0])) ? + "???" : + sgi_types[betoh32(volhdr->partitions[i].type)]); } } } @@ -341,7 +351,7 @@ init_volhdr(void) volhdr->magic = htobe32(SGILABEL_MAGIC); volhdr->root = htobe16(0); volhdr->swap = htobe16(1); - strcpy(volhdr->bootfile, "/bsd"); + strlcpy(volhdr->bootfile, "/bsd", sizeof(volhdr->bootfile)); volhdr->dp.dp_skew = lbl.d_trackskew; volhdr->dp.dp_gap1 = 1; /* XXX */ volhdr->dp.dp_gap2 = 1; /* XXX */ @@ -372,28 +382,21 @@ read_file(void) if (!opt_q) printf("Reading file %s\n", vfilename); - for (i = 0; i < 15; ++i) { + for (i = 0; i < SGI_SIZE_VOLDIR; ++i) { if (strncmp(vfilename, volhdr->voldir[i].name, strlen(volhdr->voldir[i].name)) == 0) break; } - if (i >= 15) { - printf("file %s not found\n", vfilename); - exit(1); - } + if (i >= SGI_SIZE_VOLDIR) + errx(1, "%s: file not found", vfilename); /* XXX assumes volume header starts at 0? */ - lseek(fd, betoh32(volhdr->voldir[i].block) * 512, SEEK_SET); - fp = fopen(ufilename, "w"); - if (fp == NULL) { - perror("open write"); - exit(1); - } + lseek(fd, betoh32(volhdr->voldir[i].block) * DEV_BSIZE, SEEK_SET); + if ((fp = fopen(ufilename, "w")) == NULL) + err(1, "open %s", ufilename); i = betoh32(volhdr->voldir[i].bytes); while (i > 0) { - if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { - perror("read file"); - exit(1); - } + if (read(fd, buf, sizeof(buf)) != sizeof(buf)) + err(1, "read file"); fwrite(buf, 1, i > sizeof(buf) ? sizeof(buf) : i, fp); i -= i > sizeof(buf) ? sizeof(buf) : i; } @@ -405,21 +408,20 @@ write_file(void) { FILE *fp; int slot; - size_t namelen; int block, i; struct stat st; - char fbuf[512]; + char fbuf[DEV_BSIZE]; if (!opt_q) printf("Writing file %s\n", ufilename); - if (stat(ufilename, &st) < 0) { - perror("stat"); - exit(1); - } + if (stat(ufilename, &st) != 0) + err(1, "stat %s", ufilename); + if (st.st_size == 0) + errx(1, "%s: file is empty", vfilename); if (!opt_q) printf("File %s has %lld bytes\n", ufilename, st.st_size); slot = -1; - for (i = 0; i < 15; ++i) { + for (i = 0; i < SGI_SIZE_VOLDIR; ++i) { if (volhdr->voldir[i].name[0] == '\0' && slot < 0) slot = i; if (strcmp(vfilename, volhdr->voldir[i].name) == 0) { @@ -427,10 +429,8 @@ write_file(void) break; } } - if (slot == -1) { - printf("No directory space for file %s\n", vfilename); - exit(1); - } + if (slot == -1) + errx(1, "no more directory entries available"); /* -w can overwrite, -a won't overwrite */ if (betoh32(volhdr->voldir[slot].block) > 0) { if (!opt_q) @@ -439,34 +439,20 @@ write_file(void) volhdr->voldir[slot].name[0] = 0; volhdr->voldir[slot].block = volhdr->voldir[slot].bytes = 0; } - if (st.st_size == 0) { - printf("bad file size\n"); - exit(1); - } /* XXX assumes volume header starts at 0? */ block = allocate_space((int)st.st_size); - if (block < 0) { - printf("No space for file\n"); - exit(1); - } + if (block < 0) + errx(1, "no more space available"); /* * Make sure the name in the volume header is max. 8 chars, * NOT including NUL. */ - namelen = strlen(vfilename); - if (namelen > sizeof(volhdr->voldir[slot].name)) { - printf("Warning: '%s' is too long for volume header, ", + if (strlen(vfilename) > sizeof(volhdr->voldir[slot].name)) + warnx("%s: filename is too long and will be truncated", vfilename); - namelen = sizeof(volhdr->voldir[slot].name); - printf("truncating to '%-8s'\n", vfilename); - } - - /* Populate it w/ NULs */ - memset(volhdr->voldir[slot].name, 0, + strncpy(volhdr->voldir[slot].name, vfilename, sizeof(volhdr->voldir[slot].name)); - /* Then copy the name */ - memcpy(volhdr->voldir[slot].name, vfilename, namelen); volhdr->voldir[slot].block = htobe32(block); volhdr->voldir[slot].bytes = htobe32(st.st_size); @@ -474,20 +460,15 @@ write_file(void) write_volhdr(); /* write the file itself */ - i = lseek(fd, block * 512, SEEK_SET); - if (i < 0) { - perror("lseek write"); - exit(1); - } + if (lseek(fd, block * DEV_BSIZE, SEEK_SET) == -1) + err(1, "lseek write"); i = st.st_size; fp = fopen(ufilename, "r"); while (i > 0) { - fread(fbuf, 1, i > 512 ? 512 : i, fp); - if (write(fd, fbuf, 512) != 512) { - perror("write file"); - exit(1); - } - i -= i > 512 ? 512 : i; + fread(fbuf, 1, i > sizeof(fbuf) ? sizeof(fbuf) : i, fp); + if (write(fd, fbuf, sizeof(fbuf)) != sizeof(fbuf)) + err(1, "write file"); + i -= i > sizeof(fbuf) ? sizeof(fbuf) : i; } } @@ -496,15 +477,13 @@ delete_file(void) { int i; - for (i = 0; i < 15; ++i) { + for (i = 0; i < SGI_SIZE_VOLDIR; ++i) { if (strcmp(vfilename, volhdr->voldir[i].name) == 0) { break; } } - if (i >= 15) { - printf("File %s not found\n", vfilename); - exit(1); - } + if (i >= SGI_SIZE_VOLDIR) + errx(1, "%s: file not found", vfilename); /* XXX: we don't compact the file space, so get fragmentation */ volhdr->voldir[i].name[0] = '\0'; @@ -517,11 +496,7 @@ modify_partition(void) { if (!opt_q) printf("Modify partition %d start %d length %d\n", - partno, partfirst, partblocks); - if (partno < 0 || partno > 15) { - printf("Invalid partition number: %d\n", partno); - exit(1); - } + partno, partfirst, partblocks); volhdr->partitions[partno].blocks = htobe32(partblocks); volhdr->partitions[partno].first = htobe32(partfirst); volhdr->partitions[partno].type = htobe32(parttype); @@ -543,14 +518,10 @@ write_volhdr(void) if (i != 'Y' && i != 'y') exit(1); } - i = lseek(fd, 0, SEEK_SET); - if (i < 0) { - perror("lseek 0"); - exit(1); - } - i = write(fd, buf, 512); - if (i < 0) - perror("write volhdr"); + if (lseek(fd, 0, SEEK_SET) == -1) + err(1, "lseek 0"); + if (write(fd, buf, sizeof(buf)) != sizeof(buf)) + err(1, "write volhdr"); } int @@ -559,21 +530,22 @@ allocate_space(int size) int n, blocks; int first; - blocks = (size + 511) / 512; + blocks = howmany(size, DEV_BSIZE); first = 2; - n = 0; - while (n < 15) { + for (n = 0; n < SGI_SIZE_VOLDIR;) { if (volhdr->voldir[n].name[0]) { if (first < (betoh32(volhdr->voldir[n].block) + - (betoh32(volhdr->voldir[n].bytes) + 511) / 512) && + howmany(betoh32(volhdr->voldir[n].bytes), + DEV_BSIZE)) && (first + blocks) > betoh32(volhdr->voldir[n].block)) { first = betoh32(volhdr->voldir[n].block) + - (betoh32(volhdr->voldir[n].bytes) + 511) / 512; + howmany(betoh32(volhdr->voldir[n].bytes), + DEV_BSIZE); #if 0 printf("allocate: n=%d first=%d blocks=%d size=%d\n", n, first, blocks, size); printf("%s %d %d\n", volhdr->voldir[n].name, volhdr->voldir[n].block, volhdr->voldir[n].bytes); printf("first=%d block=%d last=%d end=%d\n", first, volhdr->voldir[n].block, - first + blocks - 1, volhdr->voldir[n].block + (volhdr->voldir[n].bytes + 511) / 512); + first + blocks - 1, volhdr->voldir[n].block + howmany(volhdr->voldir[n].bytes, DEV_BSIZE)); #endif n = 0; continue; @@ -598,7 +570,7 @@ checksum_vol(void) volhdr->checksum = checksum = 0; l = (int32_t *)buf; - for (i = 0; i < 512 / 4; ++i) + for (i = 0; i < sizeof(buf) / sizeof(int32_t); ++i) checksum += betoh32(l[i]); volhdr->checksum = htobe32(-checksum); } @@ -606,10 +578,13 @@ checksum_vol(void) void usage(void) { - printf("Usage: sgivol [-qf] [-i] [-h vhsize] device\n" - " sgivol [-qf] [-r vhfilename diskfilename] device\n" - " sgivol [-qf] [-w vhfilename diskfilename] device\n" - " sgivol [-qf] [-d vhfilename] device\n" - ); - exit(0); + extern char *__progname; + + fprintf(stderr, + "usage: %s [-qf] [-i] [-h vhsize] device\n" + " %s [-qf] [-r vhfilename diskfilename] device\n" + " %s [-qf] [-w vhfilename diskfilename] device\n" + " %s [-qf] [-d vhfilename] device\n", + __progname, __progname, __progname, __progname); + exit(1); } |