diff options
author | David E. O'Brien <obrien@FreeBSD.org> | 2000-01-18 03:25:05 +0000 |
---|---|---|
committer | David E. O'Brien <obrien@FreeBSD.org> | 2000-01-18 03:25:05 +0000 |
commit | 7ebe0ef9855dc2aa77464c464d742251b055c398 (patch) | |
tree | d62c62fee6b8536daefd3156819a7af6c9ba8b40 /sysutils/setcdboot/files | |
parent | 11fad87de952ad03b8570bc1aaebd97c03006d0d (diff) | |
download | ports-7ebe0ef9855dc2aa77464c464d742251b055c398.tar.gz ports-7ebe0ef9855dc2aa77464c464d742251b055c398.zip |
Notes
Diffstat (limited to 'sysutils/setcdboot/files')
-rw-r--r-- | sysutils/setcdboot/files/setcdboot.c | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/sysutils/setcdboot/files/setcdboot.c b/sysutils/setcdboot/files/setcdboot.c new file mode 100644 index 000000000000..5f51971f5eb5 --- /dev/null +++ b/sysutils/setcdboot/files/setcdboot.c @@ -0,0 +1,237 @@ +/* + * Copyright (C) 1996 Wolfgang Solfrank. + * Copyright (C) 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * Stand-alone ISO9660 file reading package. + * + * Note: This doesn't support Rock Ridge extensions, extended attributes, + * blocksizes other than 2048 bytes, multi-extent files, etc. + */ +#include <sys/param.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#include <fcntl.h> +#include <ctype.h> +#include <err.h> +#include <isofs/cd9660/iso.h> + +struct ptable_ent { + char namlen [ISODCL( 1, 1)]; /* 711 */ + char extlen [ISODCL( 2, 2)]; /* 711 */ + char block [ISODCL( 3, 6)]; /* 732 */ + char parent [ISODCL( 7, 8)]; /* 722 */ + char name [1]; +}; +#define PTFIXSZ 8 +#define PTSIZE(pp) roundup(PTFIXSZ + isonum_711((pp)->namlen), 2) + +#define cdb2off(bno) ((bno) * ISO_DEFAULT_BLOCK_SIZE) + +/* XXX these should be in the system headers */ +static __inline int +isonum_722(u_char *p) +{ + return (*p << 8)|p[1]; +} + +static __inline int +isonum_732( u_char *p) +{ + return (*p << 24)|(p[1] << 16)|(p[2] << 8)|p[3]; +} + +static int +dirmatch(const char *path, struct iso_directory_record *dp) +{ + char *cp; + int i; + + cp = dp->name; + for (i = isonum_711(dp->name_len); --i >= 0; path++, cp++) { + if (!*path || *path == '/') + break; + if (toupper(*path) == *cp) + continue; + return 0; + } + if (*path && *path != '/') + return 0; + /* + * Allow stripping of trailing dots and the version number. + * Note that this will find the first instead of the last version + * of a file. + */ + if (i >= 0 && (*cp == ';' || *cp == '.')) { + /* This is to prevent matching of numeric extensions */ + if (*cp == '.' && cp[1] != ';') + return 0; + while (--i >= 0) + if (*++cp != ';' && (*cp < '0' || *cp > '9')) + return 0; + } + return 1; +} + +static int +cd9660_findfile(int disk, const char *path, int *startp, int *lenp) +{ + void *buf; + struct iso_primary_descriptor *vd; + size_t buf_size, read, dsize, off; + daddr_t bno, boff; + struct iso_directory_record rec; + struct iso_directory_record *dp = 0; + int rc = 0; + + /* First find the volume descriptor */ + buf = malloc(buf_size = ISO_DEFAULT_BLOCK_SIZE); + vd = buf; + for (bno = 16;; bno++) { + read = pread(disk, buf, ISO_DEFAULT_BLOCK_SIZE, cdb2off(bno)); + if (read != ISO_DEFAULT_BLOCK_SIZE) { + rc = EIO; + goto out; + } + rc = EINVAL; + if (bcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0) + goto out; + if (isonum_711(vd->type) == ISO_VD_END) + goto out; + if (isonum_711(vd->type) == ISO_VD_PRIMARY) + break; + } + if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE) { + rc = EINVAL; + goto out; + } + + rec = *(struct iso_directory_record *) vd->root_directory_record; + if (*path == '/') path++; /* eat leading '/' */ + + while (*path) { + bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length); + dsize = isonum_733(rec.size); + off = 0; + boff = 0; + + while (off < dsize) { + if ((off % ISO_DEFAULT_BLOCK_SIZE) == 0) { + read = pread(disk, buf, + ISO_DEFAULT_BLOCK_SIZE, + cdb2off(bno + boff)); + if (read != ISO_DEFAULT_BLOCK_SIZE) { + rc = EIO; + goto out; + } + boff++; + dp = (struct iso_directory_record *) buf; + } + if (isonum_711(dp->length) == 0) { + /* skip to next block, if any */ + off = boff * ISO_DEFAULT_BLOCK_SIZE; + continue; + } + + if (dirmatch(path, dp)) + break; + + dp = (struct iso_directory_record *) + ((char *) dp + isonum_711(dp->length)); + off += isonum_711(dp->length); + } + if (off == dsize) { + rc = ENOENT; + goto out; + } + + rec = *dp; + while (*path && *path != '/') /* look for next component */ + path++; + if (*path) path++; /* skip '/' */ + } + + *startp = cdb2off(isonum_733(rec.extent) + + isonum_711(rec.ext_attr_length)); + *lenp = isonum_733(rec.size); + rc = 0; + + out: + free(buf); + return rc; +} + +int +main(int argc, char *argv[]) +{ + int disk, start, len, i; + char buf[512]; + unsigned long long *lp, sum; + + if (argc != 3) { + fprintf(stderr, "Usage: setcdboot <cd image> <boot path>\n"); + exit(1); + } + + disk = open(argv[1], O_RDWR); + if (disk < 0) + err(1, "Can't open %s", argv[1]); + if (cd9660_findfile(disk, argv[2], &start, &len)) + errx(1, "Can't find %s in image", argv[2]); + printf("start=%d, len=%d\n", start, len); + + /* + * Read the SRM boot sector and write location of bootstrap. + */ + if (pread(disk, buf, 512, 0) < 0) + errx(1, "Can't read boot sector"); + lp = (unsigned long long *) buf; + lp[60] = (len + 511) / 512; + lp[61] = start / 512; + lp[62] = 0; + + /* + * Checksum the boot sector and write it back. + */ + sum = 0; + for (i = 0; i < 63; i++) + sum += lp[i]; + lp[63] = sum; + + if (pwrite(disk, buf, 512, 0) < 0) + errx(1, "Can't write boot sector"); + + return 0; +} |