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

Cache object: ab70a3a6ecde1b3b704fe5b94553aa1d


[ 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.