1 /* $OpenBSD: udf_subr.c,v 1.26 2022/09/01 13:45:26 krw Exp $ */ 2 3 /* 4 * Copyright (c) 2006, Miodrag Vallat 5 * Copyright (c) 2006, Pedro Martelletto 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/buf.h> 32 #include <sys/kernel.h> 33 #include <sys/malloc.h> 34 #include <sys/mutex.h> 35 #include <sys/stat.h> 36 #include <sys/mount.h> 37 #include <sys/vnode.h> 38 #include <sys/lock.h> 39 #include <sys/dirent.h> 40 #include <sys/disklabel.h> 41 42 #include <crypto/siphash.h> 43 44 #include <isofs/udf/ecma167-udf.h> 45 #include <isofs/udf/udf.h> 46 #include <isofs/udf/udf_extern.h> 47 48 int udf_vat_read(struct umount *, uint32_t *); 49 50 /* 51 * Convert a CS0 dstring to a 16-bit Unicode string. 52 * Returns the length of the Unicode string, in unicode characters (not 53 * bytes!), or -1 if an error arises. 54 * Note that the transname destination buffer is expected to be large 55 * enough to hold the result, and will not be terminated in any way. 56 */ 57 int 58 udf_rawnametounicode(u_int len, char *cs0string, unicode_t *transname) 59 { 60 unicode_t *origname = transname; 61 62 if (len-- == 0) 63 return (-1); 64 65 switch (*cs0string++) { 66 case 8: /* bytes string */ 67 while (len-- != 0) 68 *transname++ = (unicode_t)*cs0string++; 69 break; 70 case 16: /* 16 bit unicode string */ 71 if (len & 1) 72 return (-1); 73 len >>= 1; 74 while (len-- != 0) { 75 unicode_t tmpchar; 76 77 tmpchar = (unicode_t)*cs0string++; 78 tmpchar = (tmpchar << 8) | (unicode_t)*cs0string++; 79 *transname++ = tmpchar; 80 } 81 break; 82 default: 83 return (-1); 84 } 85 86 return (transname - origname); 87 } 88 89 /* 90 * Do a lazy probe on the underlying media to check if it's a UDF volume, in 91 * which case we fake a disk label for it. 92 */ 93 int 94 udf_disklabelspoof(dev_t dev, void (*strat)(struct buf *), 95 struct disklabel *lp) 96 { 97 char vid[32]; 98 int i, bsize = 2048, error = EINVAL; 99 uint32_t sector = 256, mvds_start, mvds_end; 100 struct buf *bp; 101 struct anchor_vdp avdp; 102 struct pri_vol_desc *pvd; 103 104 /* 105 * Get a buffer to work with. 106 */ 107 bp = geteblk(bsize); 108 bp->b_dev = dev; 109 110 /* 111 * Look for an Anchor Volume Descriptor at sector 256. 112 */ 113 bp->b_blkno = sector * btodb(bsize); 114 bp->b_bcount = bsize; 115 CLR(bp->b_flags, B_READ | B_WRITE | B_DONE); 116 SET(bp->b_flags, B_BUSY | B_READ | B_RAW); 117 bp->b_resid = bp->b_blkno / lp->d_secpercyl; 118 119 (*strat)(bp); 120 if (biowait(bp)) 121 goto out; 122 123 if (udf_checktag((struct desc_tag *)bp->b_data, TAGID_ANCHOR)) 124 goto out; 125 126 bcopy(bp->b_data, &avdp, sizeof(avdp)); 127 mvds_start = letoh32(avdp.main_vds_ex.loc); 128 mvds_end = mvds_start + (letoh32(avdp.main_vds_ex.len) - 1) / bsize; 129 130 /* 131 * Then try to find a reference to a Primary Volume Descriptor. 132 */ 133 for (sector = mvds_start; sector < mvds_end; sector++) { 134 bp->b_blkno = sector * btodb(bsize); 135 bp->b_bcount = bsize; 136 CLR(bp->b_flags, B_READ | B_WRITE | B_DONE); 137 SET(bp->b_flags, B_BUSY | B_READ | B_RAW); 138 bp->b_resid = bp->b_blkno / lp->d_secpercyl; 139 140 (*strat)(bp); 141 if (biowait(bp)) 142 goto out; 143 144 pvd = (struct pri_vol_desc *)bp->b_data; 145 if (!udf_checktag(&pvd->tag, TAGID_PRI_VOL)) 146 break; 147 } 148 149 /* 150 * If we couldn't find a reference, bail out. 151 */ 152 if (sector == mvds_end) 153 goto out; 154 155 /* 156 * Okay, it's a UDF volume. Spoof a disk label for it. 157 */ 158 if (udf_transname(pvd->vol_id, vid, sizeof(pvd->vol_id) - 1, NULL)) 159 strlcpy(lp->d_typename, vid, sizeof(lp->d_typename)); 160 161 for (i = 0; i < MAXPARTITIONS; i++) { 162 DL_SETPSIZE(&lp->d_partitions[i], 0); 163 DL_SETPOFFSET(&lp->d_partitions[i], 0); 164 } 165 166 /* 167 * Fake two partitions, 'a' and 'c'. 168 */ 169 DL_SETPSIZE(&lp->d_partitions[0], DL_GETDSIZE(lp)); 170 lp->d_partitions[0].p_fstype = FS_UDF; 171 DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp)); 172 lp->d_partitions[RAW_PART].p_fstype = FS_UDF; 173 lp->d_npartitions = MAXPARTITIONS; 174 lp->d_version = 1; 175 176 lp->d_magic = DISKMAGIC; 177 lp->d_magic2 = DISKMAGIC; 178 lp->d_checksum = dkcksum(lp); 179 180 error = 0; 181 out: 182 bp->b_flags |= B_INVAL; 183 brelse(bp); 184 185 return (error); 186 } 187 188 /* Get a vnode for the Virtual Allocation Table (VAT) */ 189 int 190 udf_vat_get(struct umount *ump, uint32_t lb) 191 { 192 struct vnode *vp; 193 struct unode *up; 194 int error; 195 196 error = udf_vget(ump->um_mountp, lb - ump->um_start - 3, &vp); 197 if (error) 198 return (error); 199 200 up = VTOU(vp); 201 up->u_vatlen = (letoh64(up->u_fentry->inf_len) - 36) >> 2; 202 203 ump->um_vat = malloc(sizeof(struct unode), M_UDFMOUNT, M_WAITOK); 204 *ump->um_vat = *up; 205 206 ump->um_flags &= ~UDF_MNT_FIND_VAT; 207 ump->um_flags |= UDF_MNT_USES_VAT; 208 209 vput(vp); 210 211 return (0); 212 } 213 214 /* Look up a sector in the VAT */ 215 int 216 udf_vat_map(struct umount *ump, uint32_t *sector) 217 { 218 /* If there's no VAT, then it's easy */ 219 if (!(ump->um_flags & UDF_MNT_USES_VAT)) { 220 *sector += ump->um_start; 221 return (0); 222 } 223 224 /* Sanity check the given sector */ 225 if (*sector >= ump->um_vat->u_vatlen) 226 return (EINVAL); 227 228 return (udf_vat_read(ump, sector)); 229 } 230 231 /* Read from the VAT */ 232 int 233 udf_vat_read(struct umount *ump, uint32_t *sector) 234 { 235 struct buf *bp; 236 uint8_t *data; 237 int error, size; 238 239 size = 4; 240 241 /* 242 * Note that we rely on the buffer cache to keep frequently accessed 243 * buffers around to avoid reading them from the disk all the time. 244 */ 245 error = udf_readatoffset(ump->um_vat, &size, *sector << 2, &bp, &data); 246 if (error) { 247 if (bp != NULL) 248 brelse(bp); 249 250 return (error); 251 } 252 253 /* Make sure we read at least a whole entry */ 254 if (size < 4) { 255 if (bp != NULL) 256 brelse(bp); 257 258 return (EINVAL); 259 } 260 261 /* Map the sector */ 262 *sector = letoh32(*(uint32_t *)data) + ump->um_start; 263 264 brelse(bp); 265 266 return (0); 267 } 268