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: releng/11.0/sys/geom/label/g_label_msdosfs.c 284582 2015-06-18 21:55:55Z trasz $");
   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 
   52         g_topology_assert_not();
   53         pp = cp->provider;
   54         sector0 = NULL;
   55         sector = NULL;
   56         bzero(label, size);
   57 
   58         /* Check if the sector size of the medium is a valid FAT sector size. */
   59         switch(pp->sectorsize) {
   60         case 512:
   61         case 1024:
   62         case 2048:
   63         case 4096:
   64                 break;
   65         default:
   66                 G_LABEL_DEBUG(1, "MSDOSFS: %s: sector size %d not compatible.",
   67                     pp->name, pp->sectorsize);
   68                 return;
   69         }
   70 
   71         /* Load 1st sector with boot sector and boot parameter block. */
   72         sector0 = (uint8_t *)g_read_data(cp, 0, pp->sectorsize, NULL);
   73         if (sector0 == NULL)
   74                 return;
   75 
   76         /* Check for the FAT boot sector signature. */
   77         if (sector0[510] != 0x55 || sector0[511] != 0xaa) {
   78                 G_LABEL_DEBUG(1, "MSDOSFS: %s: no FAT signature found.",
   79                     pp->name);
   80                 goto error;
   81         }
   82 
   83 
   84         /*
   85          * Test if this is really a FAT volume and determine the FAT type.
   86          */
   87 
   88         pfat_bsbpb = (FAT_BSBPB *)sector0;
   89         pfat32_bsbpb = (FAT32_BSBPB *)sector0;
   90 
   91         if (UINT16BYTES(pfat_bsbpb->BPB_FATSz16) != 0) {
   92                 /*
   93                  * If the BPB_FATSz16 field is not zero and the string "FAT" is
   94                  * at the right place, this should be a FAT12 or FAT16 volume.
   95                  */
   96                 if (strncmp(pfat_bsbpb->BS_FilSysType, "FAT", 3) != 0) {
   97                         G_LABEL_DEBUG(1,
   98                             "MSDOSFS: %s: FAT12/16 volume not valid.",
   99                             pp->name);
  100                         goto error;
  101                 }
  102                 G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT12/FAT16 volume detected.",
  103                     pp->name);
  104 
  105                 /* A volume with no name should have "NO NAME    " as label. */
  106                 if (strncmp(pfat_bsbpb->BS_VolLab, LABEL_NO_NAME,
  107                     sizeof(pfat_bsbpb->BS_VolLab)) == 0) {
  108                         G_LABEL_DEBUG(1,
  109                             "MSDOSFS: %s: FAT12/16 volume has no name.",
  110                             pp->name);
  111                         goto error;
  112                 }
  113                 strlcpy(label, pfat_bsbpb->BS_VolLab,
  114                     MIN(size, sizeof(pfat_bsbpb->BS_VolLab) + 1));
  115         } else if (UINT32BYTES(pfat32_bsbpb->BPB_FATSz32) != 0) {
  116                 uint32_t fat_FirstDataSector, fat_BytesPerSector, offset;
  117 
  118                 /*
  119                  * If the BPB_FATSz32 field is not zero and the string "FAT" is
  120                  * at the right place, this should be a FAT32 volume.
  121                  */
  122                 if (strncmp(pfat32_bsbpb->BS_FilSysType, "FAT", 3) != 0) {
  123                         G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT32 volume not valid.",
  124                             pp->name);
  125                         goto error;
  126                 }
  127                 G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT32 volume detected.",
  128                     pp->name);
  129 
  130                 /*
  131                  * If the volume label is not "NO NAME    " we're done.
  132                  */
  133                 if (strncmp(pfat32_bsbpb->BS_VolLab, LABEL_NO_NAME,
  134                     sizeof(pfat32_bsbpb->BS_VolLab)) != 0) {
  135                         strlcpy(label, pfat32_bsbpb->BS_VolLab,
  136                             MIN(size, sizeof(pfat32_bsbpb->BS_VolLab) + 1));
  137                         goto endofchecks;
  138                 }
  139 
  140                 /*
  141                  * If the volume label "NO NAME    " is in the boot sector, the
  142                  * label of FAT32 volumes may be stored as a special entry in
  143                  * the root directory.
  144                  */
  145                 fat_FirstDataSector =
  146                     UINT16BYTES(pfat32_bsbpb->BPB_RsvdSecCnt) +
  147                     (pfat32_bsbpb->BPB_NumFATs *
  148                      UINT32BYTES(pfat32_bsbpb->BPB_FATSz32));
  149                 fat_BytesPerSector = UINT16BYTES(pfat32_bsbpb->BPB_BytsPerSec);
  150 
  151                 G_LABEL_DEBUG(2,
  152                     "MSDOSFS: FAT_FirstDataSector=0x%x, FAT_BytesPerSector=%d",
  153                     fat_FirstDataSector, fat_BytesPerSector);
  154 
  155                 for (offset = fat_BytesPerSector * fat_FirstDataSector;;
  156                     offset += fat_BytesPerSector) {
  157                         sector = (uint8_t *)g_read_data(cp, offset,
  158                             fat_BytesPerSector, NULL);
  159                         if (sector == NULL)
  160                                 goto error;
  161 
  162                         pfat_entry = (FAT_DES *)sector;
  163                         do {
  164                                 /* No more entries available. */
  165                                 if (pfat_entry->DIR_Name[0] == 0) {
  166                                         G_LABEL_DEBUG(1, "MSDOSFS: %s: "
  167                                             "FAT32 volume has no name.",
  168                                             pp->name);
  169                                         goto error;
  170                                 }
  171 
  172                                 /* Skip empty or long name entries. */
  173                                 if (pfat_entry->DIR_Name[0] == 0xe5 ||
  174                                     (pfat_entry->DIR_Attr &
  175                                      FAT_DES_ATTR_LONG_NAME) ==
  176                                     FAT_DES_ATTR_LONG_NAME) {
  177                                         continue;
  178                                 }
  179 
  180                                 /*
  181                                  * The name of the entry is the volume label if
  182                                  * ATTR_VOLUME_ID is set.
  183                                  */
  184                                 if (pfat_entry->DIR_Attr &
  185                                     FAT_DES_ATTR_VOLUME_ID) {
  186                                         strlcpy(label, pfat_entry->DIR_Name,
  187                                             MIN(size,
  188                                             sizeof(pfat_entry->DIR_Name) + 1));
  189                                         goto endofchecks;
  190                                 }
  191                         } while((uint8_t *)(++pfat_entry) <
  192                             (uint8_t *)(sector + fat_BytesPerSector));
  193                         g_free(sector);
  194                 }
  195         } else {
  196                 G_LABEL_DEBUG(1, "MSDOSFS: %s: no FAT volume detected.",
  197                     pp->name);
  198                 goto error;
  199         }
  200 
  201 endofchecks:
  202         g_label_rtrim(label, size);
  203 
  204 error:
  205         if (sector0 != NULL)
  206                 g_free(sector0);
  207         if (sector != NULL)
  208                 g_free(sector);
  209 }
  210 
  211 struct g_label_desc g_label_msdosfs = {
  212         .ld_taste = g_label_msdosfs_taste,
  213         .ld_dir = G_LABEL_MSDOSFS_DIR,
  214         .ld_enabled = 1
  215 };
  216 
  217 G_LABEL_INIT(msdosfs, g_label_msdosfs, "Create device nodes for MSDOSFS volumes");

Cache object: 4b7d602484aaeb811da9e5d86f0e2169


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