| File: | src/usr.sbin/makefs/msdos/msdosfs_vfsops.c |
| Warning: | line 110, column 2 Value stored to 'bsize' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: msdosfs_vfsops.c,v 1.13 2021/10/06 00:40:41 deraadt Exp $ */ |
| 2 | |
| 3 | /*- |
| 4 | * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. |
| 5 | * Copyright (C) 1994, 1995, 1997 TooLs GmbH. |
| 6 | * All rights reserved. |
| 7 | * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). |
| 8 | * |
| 9 | * Redistribution and use in source and binary forms, with or without |
| 10 | * modification, are permitted provided that the following conditions |
| 11 | * are met: |
| 12 | * 1. Redistributions of source code must retain the above copyright |
| 13 | * notice, this list of conditions and the following disclaimer. |
| 14 | * 2. Redistributions in binary form must reproduce the above copyright |
| 15 | * notice, this list of conditions and the following disclaimer in the |
| 16 | * documentation and/or other materials provided with the distribution. |
| 17 | * 3. All advertising materials mentioning features or use of this software |
| 18 | * must display the following acknowledgement: |
| 19 | * This product includes software developed by TooLs GmbH. |
| 20 | * 4. The name of TooLs GmbH may not be used to endorse or promote products |
| 21 | * derived from this software without specific prior written permission. |
| 22 | * |
| 23 | * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR |
| 24 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| 26 | * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 28 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| 29 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 30 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| 31 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| 32 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 33 | */ |
| 34 | /* |
| 35 | * Written by Paul Popelka (paulp@uts.amdahl.com) |
| 36 | * |
| 37 | * You can do anything you want with this software, just don't say you wrote |
| 38 | * it, and don't remove this notice. |
| 39 | * |
| 40 | * This software is provided "as is". |
| 41 | * |
| 42 | * The author supplies this software to be publicly redistributed on the |
| 43 | * understanding that the author is not responsible for the correct |
| 44 | * functioning of this software in any circumstances and is not liable for |
| 45 | * any damages caused by this software. |
| 46 | * |
| 47 | * October 1992 |
| 48 | */ |
| 49 | |
| 50 | |
| 51 | #include <sys/param.h> /* MAXBSIZE */ |
| 52 | #include <sys/types.h> |
| 53 | |
| 54 | #include "ffs/buf.h" |
| 55 | |
| 56 | #include <msdosfs/bpb.h> |
| 57 | #include <msdosfs/bootsect.h> |
| 58 | #include "msdos/direntry.h" |
| 59 | #include "msdos/denode.h" |
| 60 | #include "msdos/msdosfsmount.h" |
| 61 | #include "msdos/fat.h" |
| 62 | |
| 63 | #include <stdio.h> |
| 64 | #include <errno(*__errno()).h> |
| 65 | #include <stdlib.h> |
| 66 | #include <string.h> |
| 67 | #include <util.h> |
| 68 | |
| 69 | #include "makefs.h" |
| 70 | #include "msdos.h" |
| 71 | #include "msdos/mkfs_msdos.h" |
| 72 | |
| 73 | #ifdef MSDOSFS_DEBUG |
| 74 | #define DPRINTF(a) printf a |
| 75 | #else |
| 76 | #define DPRINTF(a) |
| 77 | #endif |
| 78 | |
| 79 | struct msdosfsmount * |
| 80 | msdosfs_mount(struct mkfsvnode *devvp, int flags) |
| 81 | { |
| 82 | struct msdosfsmount *pmp = NULL((void*)0); |
| 83 | struct mkfsbuf *bp; |
| 84 | union bootsector *bsp; |
| 85 | struct byte_bpb33 *b33; |
| 86 | struct byte_bpb50 *b50; |
| 87 | struct byte_bpb710 *b710; |
| 88 | uint8_t SecPerClust; |
| 89 | int ronly = 0, error; |
| 90 | int bsize; |
| 91 | unsigned secsize = 512; |
| 92 | |
| 93 | DPRINTF(("%s(bread 0)\n", __func__)); |
| 94 | if ((error = bread(devvp, 0, secsize, 0, &bp)) != 0) |
| 95 | goto error_exit; |
| 96 | |
| 97 | bsp = (union bootsector *)bp->b_data; |
| 98 | b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB; |
| 99 | b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB; |
| 100 | b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB; |
| 101 | |
| 102 | if (bsp->bs50.bsBootSectSig0 != BOOTSIG00x55 |
| 103 | || bsp->bs50.bsBootSectSig1 != BOOTSIG10xaa) { |
| 104 | DPRINTF(("bootsig0 %d bootsig1 %d\n", |
| 105 | bsp->bs50.bsBootSectSig0, |
| 106 | bsp->bs50.bsBootSectSig1)); |
| 107 | error = EINVAL22; |
| 108 | goto error_exit; |
| 109 | } |
| 110 | bsize = 0; |
Value stored to 'bsize' is never read | |
| 111 | |
| 112 | pmp = ecalloc(1, sizeof *pmp); |
| 113 | /* |
| 114 | * Compute several useful quantities from the bpb in the |
| 115 | * bootsector. Copy in the dos 5 variant of the bpb then fix up |
| 116 | * the fields that are different between dos 5 and dos 3.3. |
| 117 | */ |
| 118 | SecPerClust = b50->bpbSecPerClust; |
| 119 | pmp->pm_BytesPerSecpm_bpb.bpbBytesPerSec = getushort(b50->bpbBytesPerSec)*((u_int16_t *)(b50->bpbBytesPerSec)); |
| 120 | pmp->pm_ResSectorspm_bpb.bpbResSectors = getushort(b50->bpbResSectors)*((u_int16_t *)(b50->bpbResSectors)); |
| 121 | pmp->pm_FATspm_bpb.bpbFATs = b50->bpbFATs; |
| 122 | pmp->pm_RootDirEntspm_bpb.bpbRootDirEnts = getushort(b50->bpbRootDirEnts)*((u_int16_t *)(b50->bpbRootDirEnts)); |
| 123 | pmp->pm_Sectorspm_bpb.bpbSectors = getushort(b50->bpbSectors)*((u_int16_t *)(b50->bpbSectors)); |
| 124 | pmp->pm_FATsecs = getushort(b50->bpbFATsecs)*((u_int16_t *)(b50->bpbFATsecs)); |
| 125 | pmp->pm_SecPerTrackpm_bpb.bpbSecPerTrack = getushort(b50->bpbSecPerTrack)*((u_int16_t *)(b50->bpbSecPerTrack)); |
| 126 | pmp->pm_Headspm_bpb.bpbHeads = getushort(b50->bpbHeads)*((u_int16_t *)(b50->bpbHeads)); |
| 127 | pmp->pm_Mediapm_bpb.bpbMedia = b50->bpbMedia; |
| 128 | pmp->pm_minuteswest = 0; |
| 129 | |
| 130 | DPRINTF(("%s(BytesPerSec=%u, ResSectors=%u, FATs=%d, RootDirEnts=%u, " |
| 131 | "Sectors=%u, FATsecs=%lu, SecPerTrack=%u, Heads=%u, Media=%u)\n", |
| 132 | __func__, pmp->pm_BytesPerSec, pmp->pm_ResSectors, pmp->pm_FATs, |
| 133 | pmp->pm_RootDirEnts, pmp->pm_Sectors, pmp->pm_FATsecs, |
| 134 | pmp->pm_SecPerTrack, pmp->pm_Heads, pmp->pm_Media)); |
| 135 | /* XXX - We should probably check more values here */ |
| 136 | if (!pmp->pm_BytesPerSecpm_bpb.bpbBytesPerSec || !SecPerClust |
| 137 | || pmp->pm_SecPerTrackpm_bpb.bpbSecPerTrack > 63) { |
| 138 | DPRINTF(("bytespersec %d secperclust %d " |
| 139 | "secpertrack %d\n", |
| 140 | pmp->pm_BytesPerSec, SecPerClust, |
| 141 | pmp->pm_SecPerTrack)); |
| 142 | error = EINVAL22; |
| 143 | goto error_exit; |
| 144 | } |
| 145 | |
| 146 | pmp->pm_flags = flags & MSDOSFSMNT_MNTOPT(1|2|4 |16); |
| 147 | if (pmp->pm_flags & MSDOSFSMNT_NOWIN954) |
| 148 | pmp->pm_flags |= MSDOSFSMNT_SHORTNAME1; |
| 149 | |
| 150 | if (pmp->pm_Sectorspm_bpb.bpbSectors == 0) { |
| 151 | pmp->pm_HiddenSectspm_bpb.bpbHiddenSecs = getulong(b50->bpbHiddenSecs)*((u_int32_t *)(b50->bpbHiddenSecs)); |
| 152 | pmp->pm_HugeSectorspm_bpb.bpbHugeSectors = getulong(b50->bpbHugeSectors)*((u_int32_t *)(b50->bpbHugeSectors)); |
| 153 | } else { |
| 154 | pmp->pm_HiddenSectspm_bpb.bpbHiddenSecs = getushort(b33->bpbHiddenSecs)*((u_int16_t *)(b33->bpbHiddenSecs)); |
| 155 | pmp->pm_HugeSectorspm_bpb.bpbHugeSectors = pmp->pm_Sectorspm_bpb.bpbSectors; |
| 156 | } |
| 157 | |
| 158 | if (pmp->pm_RootDirEntspm_bpb.bpbRootDirEnts == 0) { |
| 159 | unsigned short vers = getushort(b710->bpbFSVers)*((u_int16_t *)(b710->bpbFSVers)); |
| 160 | /* |
| 161 | * Some say that bsBootSectSig[23] must be zero, but |
| 162 | * Windows does not require this and some digital cameras |
| 163 | * do not set these to zero. Therefore, do not insist. |
| 164 | */ |
| 165 | if (pmp->pm_Sectorspm_bpb.bpbSectors || pmp->pm_FATsecs || vers) { |
| 166 | DPRINTF(("sectors %d fatsecs %lu vers %d\n", |
| 167 | pmp->pm_Sectors, pmp->pm_FATsecs, vers)); |
| 168 | error = EINVAL22; |
| 169 | goto error_exit; |
| 170 | } |
| 171 | pmp->pm_fatmask = FAT32_MASK0x0fffffff; |
| 172 | pmp->pm_fatmult = 4; |
| 173 | pmp->pm_fatdiv = 1; |
| 174 | pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs)*((u_int32_t *)(b710->bpbBigFATsecs)); |
| 175 | |
| 176 | /* mirrorring is enabled if the FATMIRROR bit is not set */ |
| 177 | if ((getushort(b710->bpbExtFlags)*((u_int16_t *)(b710->bpbExtFlags)) & FATMIRROR0x80) == 0) |
| 178 | pmp->pm_flags |= MSDOSFS_FATMIRROR0x20000000; |
| 179 | else |
| 180 | pmp->pm_curfat = getushort(b710->bpbExtFlags)*((u_int16_t *)(b710->bpbExtFlags)) & FATNUM0xf; |
| 181 | } else |
| 182 | pmp->pm_flags |= MSDOSFS_FATMIRROR0x20000000; |
| 183 | |
| 184 | /* Check that fs has nonzero FAT size */ |
| 185 | if (pmp->pm_FATsecs == 0) { |
| 186 | DPRINTF(("FATsecs is 0\n")); |
| 187 | error = EINVAL22; |
| 188 | goto error_exit; |
| 189 | } |
| 190 | |
| 191 | pmp->pm_fatblk = pmp->pm_ResSectorspm_bpb.bpbResSectors; |
| 192 | if (FAT32(pmp)(pmp->pm_fatmask == 0x0fffffff)) { |
| 193 | pmp->pm_rootdirblk = getulong(b710->bpbRootClust)*((u_int32_t *)(b710->bpbRootClust)); |
| 194 | pmp->pm_firstcluster = pmp->pm_fatblk |
| 195 | + (pmp->pm_FATspm_bpb.bpbFATs * pmp->pm_FATsecs); |
| 196 | pmp->pm_fsinfo = getushort(b710->bpbFSInfo)*((u_int16_t *)(b710->bpbFSInfo)); |
| 197 | } else { |
| 198 | pmp->pm_rootdirblk = pmp->pm_fatblk + |
| 199 | (pmp->pm_FATspm_bpb.bpbFATs * pmp->pm_FATsecs); |
| 200 | pmp->pm_rootdirsize = (pmp->pm_RootDirEntspm_bpb.bpbRootDirEnts * sizeof(struct direntry) |
| 201 | + pmp->pm_BytesPerSecpm_bpb.bpbBytesPerSec - 1) |
| 202 | / pmp->pm_BytesPerSecpm_bpb.bpbBytesPerSec;/* in sectors */ |
| 203 | pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize; |
| 204 | } |
| 205 | |
| 206 | pmp->pm_nmbrofclusters = (pmp->pm_HugeSectorspm_bpb.bpbHugeSectors - pmp->pm_firstcluster) / |
| 207 | SecPerClust; |
| 208 | pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1; |
| 209 | pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSecpm_bpb.bpbBytesPerSec; |
| 210 | |
| 211 | if (pmp->pm_fatmask == 0) { |
| 212 | if (pmp->pm_maxcluster |
| 213 | <= ((CLUST_RSRVD0xfffffff6 - CLUST_FIRST2) & FAT12_MASK0x00000fff)) { |
| 214 | /* |
| 215 | * This will usually be a floppy disk. This size makes |
| 216 | * sure that one FAT entry will not be split across |
| 217 | * multiple blocks. |
| 218 | */ |
| 219 | pmp->pm_fatmask = FAT12_MASK0x00000fff; |
| 220 | pmp->pm_fatmult = 3; |
| 221 | pmp->pm_fatdiv = 2; |
| 222 | } else { |
| 223 | pmp->pm_fatmask = FAT16_MASK0x0000ffff; |
| 224 | pmp->pm_fatmult = 2; |
| 225 | pmp->pm_fatdiv = 1; |
| 226 | } |
| 227 | } |
| 228 | if (FAT12(pmp)(pmp->pm_fatmask == 0x00000fff)) |
| 229 | pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSecpm_bpb.bpbBytesPerSec; |
| 230 | else |
| 231 | pmp->pm_fatblocksize = MAXBSIZE(64 * 1024); |
| 232 | |
| 233 | pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSecpm_bpb.bpbBytesPerSec; |
| 234 | pmp->pm_bnshift = ffs(pmp->pm_BytesPerSecpm_bpb.bpbBytesPerSec) - 1; |
| 235 | |
| 236 | /* |
| 237 | * Compute mask and shift value for isolating cluster relative byte |
| 238 | * offsets and cluster numbers from a file offset. |
| 239 | */ |
| 240 | pmp->pm_bpcluster = SecPerClust * pmp->pm_BytesPerSecpm_bpb.bpbBytesPerSec; |
| 241 | pmp->pm_crbomask = pmp->pm_bpcluster - 1; |
| 242 | pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1; |
| 243 | |
| 244 | DPRINTF(("%s(fatmask=%lu, fatmult=%u, fatdiv=%u, fatblocksize=%lu, " |
| 245 | "fatblocksec=%lu, bnshift=%lu, pbcluster=%lu, crbomask=%lu, " |
| 246 | "cnshift=%lu)\n", |
| 247 | __func__, pmp->pm_fatmask, pmp->pm_fatmult, pmp->pm_fatdiv, |
| 248 | pmp->pm_fatblocksize, pmp->pm_fatblocksec, pmp->pm_bnshift, |
| 249 | pmp->pm_bpcluster, pmp->pm_crbomask, pmp->pm_cnshift)); |
| 250 | /* |
| 251 | * Check for valid cluster size |
| 252 | * must be a power of 2 |
| 253 | */ |
| 254 | if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) { |
| 255 | DPRINTF(("bpcluster %lu cnshift %lu\n", |
| 256 | pmp->pm_bpcluster, pmp->pm_cnshift)); |
| 257 | error = EINVAL22; |
| 258 | goto error_exit; |
| 259 | } |
| 260 | |
| 261 | /* |
| 262 | * Release the bootsector buffer. |
| 263 | */ |
| 264 | brelse(bp, BC_AGE0); |
| 265 | bp = NULL((void*)0); |
| 266 | |
| 267 | /* |
| 268 | * Check FSInfo. |
| 269 | */ |
| 270 | if (pmp->pm_fsinfo) { |
| 271 | struct fsinfo *fp; |
| 272 | |
| 273 | /* |
| 274 | * XXX If the fsinfo block is stored on media with |
| 275 | * 2KB or larger sectors, is the fsinfo structure |
| 276 | * padded at the end or in the middle? |
| 277 | */ |
| 278 | DPRINTF(("%s(bread %lu)\n", __func__, |
| 279 | (unsigned long)de_bn2kb(pmp, pmp->pm_fsinfo))); |
| 280 | if ((error = bread(devvp, de_bn2kb(pmp, pmp->pm_fsinfo)((pmp->pm_fsinfo) << ((pmp)->pm_bnshift - 9)), |
| 281 | pmp->pm_BytesPerSecpm_bpb.bpbBytesPerSec, 0, &bp)) != 0) |
| 282 | goto error_exit; |
| 283 | fp = (struct fsinfo *)bp->b_data; |
| 284 | if (!memcmp(fp->fsisig1, "RRaA", 4) |
| 285 | && !memcmp(fp->fsisig2, "rrAa", 4) |
| 286 | && !memcmp(fp->fsisig3, "\0\0\125\252", 4) |
| 287 | && !memcmp(fp->fsisig4, "\0\0\125\252", 4)) |
| 288 | pmp->pm_nxtfree = getulong(fp->fsinxtfree)*((u_int32_t *)(fp->fsinxtfree)); |
| 289 | else |
| 290 | pmp->pm_fsinfo = 0; |
| 291 | brelse(bp, 0); |
| 292 | bp = NULL((void*)0); |
| 293 | } |
| 294 | |
| 295 | /* |
| 296 | * Check and validate (or perhaps invalidate?) the fsinfo structure? |
| 297 | * XXX |
| 298 | */ |
| 299 | if (pmp->pm_fsinfo) { |
| 300 | if ((pmp->pm_nxtfree == 0xffffffffUL) || |
| 301 | (pmp->pm_nxtfree > pmp->pm_maxcluster)) |
| 302 | pmp->pm_fsinfo = 0; |
| 303 | } |
| 304 | |
| 305 | /* |
| 306 | * Allocate memory for the bitmap of allocated clusters, and then |
| 307 | * fill it in. |
| 308 | */ |
| 309 | pmp->pm_inusemap = ecalloc(sizeof(*pmp->pm_inusemap), |
| 310 | ((pmp->pm_maxcluster + N_INUSEBITS(8 * sizeof(u_int))) / N_INUSEBITS(8 * sizeof(u_int)))); |
| 311 | /* |
| 312 | * fillinusemap() needs pm_devvp. |
| 313 | */ |
| 314 | pmp->pm_dev = 0; |
| 315 | pmp->pm_devvp = devvp; |
| 316 | |
| 317 | /* |
| 318 | * Have the inuse map filled in. |
| 319 | */ |
| 320 | if ((error = fillinusemap(pmp)) != 0) { |
| 321 | DPRINTF(("fillinusemap %d\n", error)); |
| 322 | goto error_exit; |
| 323 | } |
| 324 | |
| 325 | /* |
| 326 | * Finish up. |
| 327 | */ |
| 328 | if (ronly) |
| 329 | pmp->pm_flags |= MSDOSFSMNT_RONLY0x80000000; |
| 330 | else |
| 331 | pmp->pm_fmod = 1; |
| 332 | |
| 333 | return pmp; |
| 334 | |
| 335 | error_exit: |
| 336 | if (bp) |
| 337 | brelse(bp, BC_AGE0); |
| 338 | if (pmp) { |
| 339 | if (pmp->pm_inusemap) |
| 340 | free(pmp->pm_inusemap); |
| 341 | free(pmp); |
| 342 | } |
| 343 | errno(*__errno()) = error; |
| 344 | return NULL((void*)0); |
| 345 | } |
| 346 | |
| 347 | int |
| 348 | msdosfs_root(struct msdosfsmount *pmp, struct mkfsvnode *vp) { |
| 349 | struct denode *ndep; |
| 350 | int error; |
| 351 | |
| 352 | *vp = *pmp->pm_devvp; |
| 353 | if ((error = deget(pmp, MSDOSFSROOT0, MSDOSFSROOT_OFS0x1fffffff, &ndep)) != 0) { |
| 354 | errno(*__errno()) = error; |
| 355 | return -1; |
| 356 | } |
| 357 | vp->v_data = ndep; |
| 358 | return 0; |
| 359 | } |