msdosfs.c revision 1.1
1/* $NetBSD: msdosfs.c,v 1.1 2018/01/09 03:31:15 christos Exp $ */ 2 3/*- 4 * Copyright (c) 2017 The NetBSD Foundation, Inc. 5 * Copyright (c) 2016 The DragonFly Project 6 * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org> 7 * Copyright (c) 2006 Tobias Reifenberger 8 * Copyright (c) 2014 The FreeBSD Foundation 9 * All rights reserved. 10 * 11 * This code is derived from software contributed to The NetBSD Foundation 12 * by Tomohiro Kusumi <kusumi.tomohiro@gmail.com>. 13 * 14 * This software was developed by Edward Tomasz Napierala under sponsorship 15 * from the FreeBSD Foundation. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38#include <sys/cdefs.h> 39__RCSID("$NetBSD: msdosfs.c,v 1.1 2018/01/09 03:31:15 christos Exp $"); 40 41#include <sys/param.h> 42#include <stdio.h> 43#include <stdlib.h> 44#include <string.h> 45 46#include "fstyp.h" 47#include "msdosfs.h" 48 49#define LABEL_NO_NAME "NO NAME " 50 51int 52fstyp_msdosfs(FILE *fp, char *label, size_t size) 53{ 54 FAT_BSBPB *pfat_bsbpb; 55 FAT32_BSBPB *pfat32_bsbpb; 56 FAT_DES *pfat_entry; 57 uint8_t *sector0, *sector; 58 59 sector0 = NULL; 60 sector = NULL; 61 62 /* Load 1st sector with boot sector and boot parameter block. */ 63 sector0 = read_buf(fp, 0, 512); 64 if (sector0 == NULL) 65 return 1; 66 67 /* Check for the FAT boot sector signature. */ 68 if (sector0[510] != 0x55 || sector0[511] != 0xaa) { 69 goto error; 70 } 71 72 /* 73 * Test if this is really a FAT volume and determine the FAT type. 74 */ 75 76 pfat_bsbpb = (FAT_BSBPB *)sector0; 77 pfat32_bsbpb = (FAT32_BSBPB *)sector0; 78 79 if (UINT16BYTES(pfat_bsbpb->BPB_FATSz16) != 0) { 80 /* 81 * If the BPB_FATSz16 field is not zero and the string "FAT" is 82 * at the right place, this should be a FAT12 or FAT16 volume. 83 */ 84 if (strncmp((char*)pfat_bsbpb->BS_FilSysType, "FAT", 3) != 0) { 85 goto error; 86 } 87 88 /* A volume with no name should have "NO NAME " as label. */ 89 if (strncmp((char*)pfat_bsbpb->BS_VolLab, LABEL_NO_NAME, 90 sizeof(pfat_bsbpb->BS_VolLab)) == 0) { 91 goto endofchecks; 92 } 93 strlcpy(label, (char*)pfat_bsbpb->BS_VolLab, 94 MIN(size, sizeof(pfat_bsbpb->BS_VolLab) + 1)); 95 } else if (UINT32BYTES(pfat32_bsbpb->BPB_FATSz32) != 0) { 96 uint32_t fat_FirstDataSector, fat_BytesPerSector, offset; 97 98 /* 99 * If the BPB_FATSz32 field is not zero and the string "FAT" is 100 * at the right place, this should be a FAT32 volume. 101 */ 102 if (strncmp((char*)pfat32_bsbpb->BS_FilSysType, "FAT", 3) != 0) 103 { 104 goto error; 105 } 106 107 /* 108 * If the volume label is not "NO NAME " we're done. 109 */ 110 if (strncmp((char*)pfat32_bsbpb->BS_VolLab, LABEL_NO_NAME, 111 sizeof(pfat32_bsbpb->BS_VolLab)) != 0) { 112 strlcpy(label, (char*)pfat32_bsbpb->BS_VolLab, 113 MIN(size, sizeof(pfat32_bsbpb->BS_VolLab) + 1)); 114 goto endofchecks; 115 } 116 117 /* 118 * If the volume label "NO NAME " is in the boot sector, the 119 * label of FAT32 volumes may be stored as a special entry in 120 * the root directory. 121 */ 122 fat_FirstDataSector = 123 UINT16BYTES(pfat32_bsbpb->BPB_RsvdSecCnt) + 124 (pfat32_bsbpb->BPB_NumFATs * 125 UINT32BYTES(pfat32_bsbpb->BPB_FATSz32)); 126 fat_BytesPerSector = UINT16BYTES(pfat32_bsbpb->BPB_BytsPerSec); 127 128 // fat_FirstDataSector, fat_BytesPerSector); 129 130 for (offset = fat_BytesPerSector * fat_FirstDataSector;; 131 offset += fat_BytesPerSector) { 132 sector = read_buf(fp, offset, fat_BytesPerSector); 133 if (sector == NULL) 134 goto error; 135 136 pfat_entry = (FAT_DES *)sector; 137 do { 138 /* No more entries available. */ 139 if (pfat_entry->DIR_Name[0] == 0) { 140 goto endofchecks; 141 } 142 143 /* Skip empty or long name entries. */ 144 if (pfat_entry->DIR_Name[0] == 0xe5 || 145 (pfat_entry->DIR_Attr & 146 FAT_DES_ATTR_LONG_NAME) == 147 FAT_DES_ATTR_LONG_NAME) { 148 continue; 149 } 150 151 /* 152 * The name of the entry is the volume label if 153 * ATTR_VOLUME_ID is set. 154 */ 155 if (pfat_entry->DIR_Attr & 156 FAT_DES_ATTR_VOLUME_ID) { 157 strlcpy(label, (char*)pfat_entry->DIR_Name, 158 MIN(size, 159 sizeof(pfat_entry->DIR_Name) + 1)); 160 goto endofchecks; 161 } 162 } while((uint8_t *)(++pfat_entry) < 163 (uint8_t *)(sector + fat_BytesPerSector)); 164 free(sector); 165 } 166 } else { 167 goto error; 168 } 169 170endofchecks: 171 rtrim(label, size); 172 173 free(sector0); 174 free(sector); 175 176 return (0); 177 178error: 179 free(sector0); 180 free(sector); 181 182 return (1); 183} 184