The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/geom/label/g_label_msdosfs.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
    5  * Copyright (c) 2006 Tobias Reifenberger
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/kernel.h>
   36 #include <sys/malloc.h>
   37 
   38 #include <geom/geom.h>
   39 #include <geom/geom_dbg.h>
   40 #include <geom/label/g_label.h>
   41 #include <geom/label/g_label_msdosfs.h>
   42 
   43 #define LABEL_NO_NAME           "NO NAME    "
   44 
   45 static void
   46 g_label_msdosfs_taste(struct g_consumer *cp, char *label, size_t size)
   47 {
   48         struct g_provider *pp;
   49         FAT_BSBPB *pfat_bsbpb;
   50         FAT32_BSBPB *pfat32_bsbpb;
   51         FAT_DES *pfat_entry;
   52         uint8_t *sector0, *sector;
   53         size_t copysize;
   54 
   55         g_topology_assert_not();
   56         pp = cp->provider;
   57         sector0 = NULL;
   58         sector = NULL;
   59         bzero(label, size);
   60 
   61         /* Check if the sector size of the medium is a valid FAT sector size. */
   62         switch(pp->sectorsize) {
   63         case 512:
   64         case 1024:
   65         case 2048:
   66         case 4096:
   67                 break;
   68         default:
   69                 G_LABEL_DEBUG(1, "MSDOSFS: %s: sector size %d not compatible.",
   70                     pp->name, pp->sectorsize);
   71                 return;
   72         }
   73 
   74         /* Load 1st sector with boot sector and boot parameter block. */
   75         sector0 = (uint8_t *)g_read_data(cp, 0, pp->sectorsize, NULL);
   76         if (sector0 == NULL)
   77                 return;
   78 
   79         /* Check for the FAT boot sector signature. */
   80         if (sector0[510] != 0x55 || sector0[511] != 0xaa) {
   81                 G_LABEL_DEBUG(1, "MSDOSFS: %s: no FAT signature found.",
   82                     pp->name);
   83                 goto error;
   84         }
   85 
   86         /*
   87          * Test if this is really a FAT volume and determine the FAT type.
   88          */
   89 
   90         pfat_bsbpb = (FAT_BSBPB *)sector0;
   91         pfat32_bsbpb = (FAT32_BSBPB *)sector0;
   92 
   93         if (UINT16BYTES(pfat_bsbpb->BPB_FATSz16) != 0) {
   94                 /*
   95                  * If the BPB_FATSz16 field is not zero and the string "FAT" is
   96                  * at the right place, this should be a FAT12 or FAT16 volume.
   97                  */
   98                 if (strncmp(pfat_bsbpb->BS_FilSysType, "FAT", 3) != 0) {
   99                         G_LABEL_DEBUG(1,
  100                             "MSDOSFS: %s: FAT12/16 volume not valid.",
  101                             pp->name);
  102                         goto error;
  103                 }
  104                 G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT12/FAT16 volume detected.",
  105                     pp->name);
  106 
  107                 /* A volume with no name should have "NO NAME    " as label. */
  108                 if (strncmp(pfat_bsbpb->BS_VolLab, LABEL_NO_NAME,
  109                     sizeof(pfat_bsbpb->BS_VolLab)) == 0) {
  110                         G_LABEL_DEBUG(1,
  111                             "MSDOSFS: %s: FAT12/16 volume has no name.",
  112                             pp->name);
  113                         goto error;
  114                 }
  115                 copysize = MIN(size - 1, sizeof(pfat_bsbpb->BS_VolLab));
  116                 memcpy(label, pfat_bsbpb->BS_VolLab, copysize);
  117                 label[copysize] = '\0';
  118         } else if (UINT32BYTES(pfat32_bsbpb->BPB_FATSz32) != 0) {
  119                 uint32_t fat_FirstDataSector, fat_BytesPerSector, offset;
  120 
  121                 /*
  122                  * If the BPB_FATSz32 field is not zero and the string "FAT" is
  123                  * at the right place, this should be a FAT32 volume.
  124                  */
  125                 if (strncmp(pfat32_bsbpb->BS_FilSysType, "FAT", 3) != 0) {
  126                         G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT32 volume not valid.",
  127                             pp->name);
  128                         goto error;
  129                 }
  130                 G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT32 volume detected.",
  131                     pp->name);
  132 
  133                 /*
  134                  * If the volume label is not "NO NAME    " we're done.
  135                  */
  136                 if (strncmp(pfat32_bsbpb->BS_VolLab, LABEL_NO_NAME,
  137                     sizeof(pfat32_bsbpb->BS_VolLab)) != 0) {
  138                         copysize = MIN(size - 1,
  139                             sizeof(pfat32_bsbpb->BS_VolLab));
  140                         memcpy(label, pfat32_bsbpb->BS_VolLab, copysize);
  141                         label[copysize] = '\0';
  142                         goto endofchecks;
  143                 }
  144 
  145                 /*
  146                  * If the volume label "NO NAME    " is in the boot sector, the
  147                  * label of FAT32 volumes may be stored as a special entry in
  148                  * the root directory.
  149                  */
  150                 fat_FirstDataSector =
  151                     UINT16BYTES(pfat32_bsbpb->BPB_RsvdSecCnt) +
  152                     (pfat32_bsbpb->BPB_NumFATs *
  153                      UINT32BYTES(pfat32_bsbpb->BPB_FATSz32));
  154                 fat_BytesPerSector = UINT16BYTES(pfat32_bsbpb->BPB_BytsPerSec);
  155 
  156                 G_LABEL_DEBUG(2,
  157                     "MSDOSFS: FAT_FirstDataSector=0x%x, FAT_BytesPerSector=%d",
  158                     fat_FirstDataSector, fat_BytesPerSector);
  159                 if (fat_BytesPerSector == 0 ||
  160                     fat_BytesPerSector % pp->sectorsize != 0) {
  161                         G_LABEL_DEBUG(1, "MSDOSFS: %s: corrupted BPB",
  162                             pp->name);
  163                         goto error;
  164                 }
  165 
  166                 for (offset = fat_BytesPerSector * fat_FirstDataSector;;
  167                     offset += fat_BytesPerSector) {
  168                         sector = (uint8_t *)g_read_data(cp, offset,
  169                             fat_BytesPerSector, NULL);
  170                         if (sector == NULL)
  171                                 goto error;
  172 
  173                         pfat_entry = (FAT_DES *)sector;
  174                         do {
  175                                 /* No more entries available. */
  176                                 if (pfat_entry->DIR_Name[0] == 0) {
  177                                         G_LABEL_DEBUG(1, "MSDOSFS: %s: "
  178                                             "FAT32 volume has no name.",
  179                                             pp->name);
  180                                         goto error;
  181                                 }
  182 
  183                                 /* Skip empty or long name entries. */
  184                                 if (pfat_entry->DIR_Name[0] == 0xe5 ||
  185                                     (pfat_entry->DIR_Attr &
  186                                      FAT_DES_ATTR_LONG_NAME) ==
  187                                     FAT_DES_ATTR_LONG_NAME) {
  188                                         continue;
  189                                 }
  190 
  191                                 /*
  192                                  * The name of the entry is the volume label if
  193                                  * ATTR_VOLUME_ID is set.
  194                                  */
  195                                 if (pfat_entry->DIR_Attr &
  196                                     FAT_DES_ATTR_VOLUME_ID) {
  197                                         copysize = MIN(size - 1,
  198                                             sizeof(pfat_entry->DIR_Name));
  199                                         memcpy(label, pfat_entry->DIR_Name,
  200                                             copysize);
  201                                         label[copysize] = '\0';
  202                                         goto endofchecks;
  203                                 }
  204                         } while((uint8_t *)(++pfat_entry) <
  205                             (uint8_t *)(sector + fat_BytesPerSector));
  206                         g_free(sector);
  207                 }
  208         } else {
  209                 G_LABEL_DEBUG(1, "MSDOSFS: %s: no FAT volume detected.",
  210                     pp->name);
  211                 goto error;
  212         }
  213 
  214 endofchecks:
  215         g_label_rtrim(label, size);
  216 
  217 error:
  218         g_free(sector0);
  219         g_free(sector);
  220 }
  221 
  222 struct g_label_desc g_label_msdosfs = {
  223         .ld_taste = g_label_msdosfs_taste,
  224         .ld_dirprefix = "msdosfs/",
  225         .ld_enabled = 1
  226 };
  227 
  228 G_LABEL_INIT(msdosfs, g_label_msdosfs, "Create device nodes for MSDOSFS volumes");

Cache object: 8ed61e3e5edb0cfb4f972b3b1d5155d0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.