1 1.2 tsutsui /* $NetBSD: cd9660.c,v 1.2 2024/05/24 09:59:42 tsutsui Exp $ */ 2 1.1 tsutsui 3 1.1 tsutsui /*- 4 1.1 tsutsui * Copyright (c) 2005 Izumi Tsutsui. All rights reserved. 5 1.1 tsutsui * 6 1.1 tsutsui * Redistribution and use in source and binary forms, with or without 7 1.1 tsutsui * modification, are permitted provided that the following conditions 8 1.1 tsutsui * are met: 9 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright 10 1.1 tsutsui * notice, this list of conditions and the following disclaimer. 11 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the 13 1.1 tsutsui * documentation and/or other materials provided with the distribution. 14 1.1 tsutsui * 15 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 1.1 tsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 1.1 tsutsui * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 1.1 tsutsui * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 1.1 tsutsui * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 1.1 tsutsui * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 1.1 tsutsui * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 1.1 tsutsui * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 1.1 tsutsui * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 1.1 tsutsui * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 1.1 tsutsui */ 26 1.1 tsutsui 27 1.1 tsutsui #if HAVE_NBTOOL_CONFIG_H 28 1.1 tsutsui #include "nbtool_config.h" 29 1.1 tsutsui #endif 30 1.1 tsutsui 31 1.1 tsutsui #include <sys/cdefs.h> 32 1.1 tsutsui #if defined(__RCSID) && !defined(__lint) 33 1.2 tsutsui __RCSID("$NetBSD: cd9660.c,v 1.2 2024/05/24 09:59:42 tsutsui Exp $"); 34 1.1 tsutsui #endif /* !__lint */ 35 1.1 tsutsui 36 1.1 tsutsui #include <sys/param.h> 37 1.1 tsutsui 38 1.1 tsutsui #if !HAVE_NBTOOL_CONFIG_H 39 1.1 tsutsui #include <sys/mount.h> 40 1.1 tsutsui #endif 41 1.2 tsutsui #if !HAVE_NBTOOL_CONFIG_H || HAVE_SYS_ENDIAN_H 42 1.2 tsutsui #include <sys/endian.h> 43 1.2 tsutsui #endif 44 1.1 tsutsui 45 1.1 tsutsui #include <assert.h> 46 1.1 tsutsui #include <err.h> 47 1.1 tsutsui #include <errno.h> 48 1.1 tsutsui #include <fcntl.h> 49 1.1 tsutsui #include <stdarg.h> 50 1.1 tsutsui #include <stdio.h> 51 1.1 tsutsui #include <stdlib.h> 52 1.1 tsutsui #include <string.h> 53 1.1 tsutsui #include <unistd.h> 54 1.1 tsutsui #include <dirent.h> 55 1.1 tsutsui 56 1.1 tsutsui #include <fs/cd9660/iso.h> 57 1.1 tsutsui #include <fs/cd9660/cd9660_extern.h> 58 1.1 tsutsui 59 1.1 tsutsui #include "installboot.h" 60 1.1 tsutsui 61 1.1 tsutsui #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) 62 1.1 tsutsui #define MAXLEN 16 63 1.1 tsutsui 64 1.1 tsutsui 65 1.1 tsutsui int 66 1.1 tsutsui cd9660_match(ib_params *params) 67 1.1 tsutsui { 68 1.1 tsutsui int rv, blocksize; 69 1.1 tsutsui struct iso_primary_descriptor ipd; 70 1.1 tsutsui 71 1.1 tsutsui assert(params != NULL); 72 1.1 tsutsui assert(params->fstype != NULL); 73 1.1 tsutsui assert(params->fsfd != -1); 74 1.1 tsutsui 75 1.1 tsutsui rv = pread(params->fsfd, &ipd, sizeof(ipd), 76 1.1 tsutsui ISO_DEFAULT_BLOCK_SIZE * 16); 77 1.1 tsutsui if (rv == -1) { 78 1.1 tsutsui warn("Reading primary descriptor in `%s'", params->filesystem); 79 1.1 tsutsui return 0; 80 1.1 tsutsui } else if (rv != sizeof(ipd)) { 81 1.1 tsutsui warnx("Reading primary descriptor in `%s': short read", 82 1.1 tsutsui params->filesystem); 83 1.1 tsutsui return 0; 84 1.1 tsutsui } 85 1.1 tsutsui 86 1.1 tsutsui if (ipd.type[0] != ISO_VD_PRIMARY || 87 1.1 tsutsui strncmp(ipd.id, ISO_STANDARD_ID, sizeof(ipd.id)) != 0 || 88 1.1 tsutsui ipd.version[0] != 1) { 89 1.1 tsutsui warnx("Filesystem `%s' is not ISO9660 format", 90 1.1 tsutsui params->filesystem); 91 1.1 tsutsui return 0; 92 1.1 tsutsui } 93 1.1 tsutsui 94 1.1 tsutsui blocksize = isonum_723((u_char *)ipd.logical_block_size); 95 1.1 tsutsui if (blocksize != ISO_DEFAULT_BLOCK_SIZE) { 96 1.1 tsutsui warnx("Invalid blocksize %d in `%s'", 97 1.1 tsutsui blocksize, params->filesystem); 98 1.1 tsutsui return 0; 99 1.1 tsutsui } 100 1.1 tsutsui 101 1.1 tsutsui params->fstype->blocksize = blocksize; 102 1.1 tsutsui params->fstype->needswap = 0; 103 1.1 tsutsui 104 1.1 tsutsui return 1; 105 1.1 tsutsui } 106 1.1 tsutsui 107 1.1 tsutsui int 108 1.1 tsutsui cd9660_findstage2(ib_params *params, uint32_t *maxblk, ib_block *blocks) 109 1.1 tsutsui { 110 1.1 tsutsui uint8_t buf[ISO_DEFAULT_BLOCK_SIZE]; 111 1.1 tsutsui char name[ISO_MAXNAMLEN]; 112 1.1 tsutsui char *stage2; 113 1.1 tsutsui off_t loc; 114 1.1 tsutsui int rv, blocksize, found; 115 1.1 tsutsui u_int i; 116 1.1 tsutsui struct iso_primary_descriptor ipd; 117 1.1 tsutsui struct iso_directory_record *idr; 118 1.1 tsutsui 119 1.1 tsutsui assert(params != NULL); 120 1.1 tsutsui assert(params->stage2 != NULL); 121 1.1 tsutsui assert(maxblk != NULL); 122 1.1 tsutsui assert(blocks != NULL); 123 1.1 tsutsui 124 1.1 tsutsui #if 0 125 1.1 tsutsui if (params->flags & IB_STAGE2START) 126 1.1 tsutsui return hardcode_stage2(params, maxblk, blocks); 127 1.1 tsutsui #endif 128 1.1 tsutsui 129 1.1 tsutsui /* The secondary bootstrap must be clearly in /. */ 130 1.1 tsutsui strlcpy(name, params->stage2, ISO_MAXNAMLEN); 131 1.1 tsutsui stage2 = name; 132 1.1 tsutsui if (stage2[0] == '/') 133 1.1 tsutsui stage2++; 134 1.1 tsutsui if (strchr(stage2, '/') != NULL) { 135 1.1 tsutsui warnx("The secondary bootstrap `%s' must be in / " 136 1.1 tsutsui "on filesystem `%s'", params->stage2, params->filesystem); 137 1.1 tsutsui return 0; 138 1.1 tsutsui } 139 1.1 tsutsui if (strchr(stage2, '.') == NULL) { 140 1.1 tsutsui /* 141 1.1 tsutsui * XXX should fix isofncmp()? 142 1.1 tsutsui */ 143 1.1 tsutsui strlcat(name, ".", ISO_MAXNAMLEN); 144 1.1 tsutsui } 145 1.1 tsutsui 146 1.1 tsutsui rv = pread(params->fsfd, &ipd, sizeof(ipd), 147 1.1 tsutsui ISO_DEFAULT_BLOCK_SIZE * 16); 148 1.1 tsutsui if (rv == -1) { 149 1.1 tsutsui warn("Reading primary descriptor in `%s'", params->filesystem); 150 1.1 tsutsui return 0; 151 1.1 tsutsui } else if (rv != sizeof(ipd)) { 152 1.1 tsutsui warnx("Reading primary descriptor in `%s': short read", 153 1.1 tsutsui params->filesystem); 154 1.1 tsutsui return 0; 155 1.1 tsutsui } 156 1.1 tsutsui blocksize = isonum_723((u_char *)ipd.logical_block_size); 157 1.1 tsutsui 158 1.1 tsutsui idr = (void *)ipd.root_directory_record; 159 1.1 tsutsui loc = (off_t)isonum_733(idr->extent) * blocksize; 160 1.1 tsutsui rv = pread(params->fsfd, buf, blocksize, loc); 161 1.1 tsutsui if (rv == -1) { 162 1.1 tsutsui warn("Reading root directory record in `%s'", 163 1.1 tsutsui params->filesystem); 164 1.1 tsutsui return 0; 165 1.1 tsutsui } else if (rv != sizeof(ipd)) { 166 1.1 tsutsui warnx("Reading root directory record in `%s': short read", 167 1.1 tsutsui params->filesystem); 168 1.1 tsutsui return 0; 169 1.1 tsutsui } 170 1.1 tsutsui 171 1.1 tsutsui found = 0; 172 1.1 tsutsui for (i = 0; i < blocksize - sizeof(struct iso_directory_record); 173 1.1 tsutsui i += (u_char)idr->length[0]) { 174 1.1 tsutsui idr = (void *)&buf[i]; 175 1.1 tsutsui 176 1.1 tsutsui #ifdef DEBUG 177 1.1 tsutsui printf("i = %d, idr->length[0] = %3d\n", 178 1.1 tsutsui i, (u_char)idr->length[0]); 179 1.1 tsutsui #endif 180 1.1 tsutsui /* check end of entries */ 181 1.1 tsutsui if (idr->length[0] == 0) { 182 1.1 tsutsui #ifdef DEBUG 183 1.1 tsutsui printf("end of entries\n"); 184 1.1 tsutsui #endif 185 1.1 tsutsui break; 186 1.1 tsutsui } 187 1.1 tsutsui 188 1.1 tsutsui if (idr->flags[0] & 2) { 189 1.1 tsutsui /* skip directory entries */ 190 1.1 tsutsui #ifdef DEBUG 191 1.1 tsutsui printf("skip directory entry\n"); 192 1.1 tsutsui #endif 193 1.1 tsutsui continue; 194 1.1 tsutsui } 195 1.1 tsutsui if (idr->name_len[0] == 1 && 196 1.1 tsutsui (idr->name[0] == 0 || idr->name[0] == 1)) { 197 1.1 tsutsui /* skip "." and ".." */ 198 1.1 tsutsui #ifdef DEBUG 199 1.1 tsutsui printf("skip dot dot\n"); 200 1.1 tsutsui #endif 201 1.1 tsutsui continue; 202 1.1 tsutsui } 203 1.1 tsutsui #ifdef DEBUG 204 1.1 tsutsui { 205 1.1 tsutsui int j; 206 1.1 tsutsui 207 1.1 tsutsui printf("filename:"); 208 1.1 tsutsui for (j = 0; j < isonum_711(idr->name_len); j++) 209 1.1 tsutsui printf("%c", idr->name[j]); 210 1.1 tsutsui printf("\n"); 211 1.1 tsutsui } 212 1.1 tsutsui #endif 213 1.1 tsutsui if (isofncmp((u_char *)stage2, strlen(stage2), 214 1.1 tsutsui (u_char *)idr->name, 215 1.1 tsutsui isonum_711((u_char *)idr->name_len), 0) == 0) { 216 1.1 tsutsui found = 1; 217 1.1 tsutsui /* ISO filesystem always has contiguous file blocks */ 218 1.1 tsutsui blocks[0].block = (int64_t)isonum_733(idr->extent); 219 1.1 tsutsui blocks[0].blocksize = 220 1.1 tsutsui roundup(isonum_733(idr->size), blocksize); 221 1.1 tsutsui *maxblk = 1; 222 1.1 tsutsui #ifdef DEBUG 223 1.1 tsutsui printf("block = %ld, blocksize = %ld\n", 224 1.1 tsutsui (long)blocks[0].block, blocks[0].blocksize); 225 1.1 tsutsui #endif 226 1.1 tsutsui break; 227 1.1 tsutsui } 228 1.1 tsutsui } 229 1.1 tsutsui 230 1.1 tsutsui if (found == 0) { 231 1.1 tsutsui warnx("Can't find secondary bootstrap `%s' in filesystem `%s'", 232 1.1 tsutsui params->stage2, params->filesystem); 233 1.1 tsutsui return 0; 234 1.1 tsutsui } 235 1.1 tsutsui 236 1.1 tsutsui return 1; 237 1.1 tsutsui } 238