1 /*
   2     libparted
   3     Copyright (C) 1998, 1999, 2000, 2002, 2004, 2007 Free Software Foundation, Inc.
   4 
   5     This program is free software; you can redistribute it and/or modify
   6     it under the terms of the GNU General Public License as published by
   7     the Free Software Foundation; either version 3 of the License, or
   8     (at your option) any later version.
   9 
  10     This program is distributed in the hope that it will be useful,
  11     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13     GNU General Public License for more details.
  14 
  15     You should have received a copy of the GNU General Public License
  16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17 */
  18 
  19 #include <config.h>
  20 #include "fat.h"
  21 
  22 #include <stdio.h>
  23 #include <stdlib.h>
  24 #include <string.h>
  25 #include <sys/types.h>
  26 #include <sys/stat.h>
  27 #include <fcntl.h>
  28 #include <errno.h>
  29 
  30 /* Reads in the boot sector (superblock), and does a minimum of sanity
  31  * checking.  The goals are:
  32  *      - to detect fat file systems, even if they are damaged [i.e. not
  33  * return an error / throw an exception]
  34  *      - to fail detection if there's not enough information for
  35  * fat_boot_sector_probe_type() to work (or possibly crash on a divide-by-zero)
  36  */
  37 int
  38 fat_boot_sector_read (FatBootSector* bs, const PedGeometry *geom)
  39 {
  40         PED_ASSERT (bs != NULL, return 0);
  41         PED_ASSERT (geom != NULL, return 0);
  42 
  43         if (!ped_geometry_read (geom, bs, 0, 1))
  44                 return 0;
  45 
  46         if (PED_LE16_TO_CPU (bs->boot_sign) != 0xAA55) {
  47                 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
  48                         _("File system has an invalid signature for a FAT "
  49                           "file system."));
  50                 return 0;
  51         }
  52 
  53         if (!bs->system_id[0]) {
  54                 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
  55                         _("File system has an invalid signature for a FAT "
  56                           "file system."));
  57                 return 0;
  58         }
  59 
  60         if (!bs->sector_size
  61             || PED_LE16_TO_CPU (bs->sector_size) % PED_SECTOR_SIZE_DEFAULT) {
  62                 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
  63                         _("File system has an invalid sector size for a FAT "
  64                           "file system."));
  65                 return 0;
  66         }
  67 
  68         if (!bs->cluster_size) {
  69                 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
  70                         _("File system has an invalid cluster size for a FAT "
  71                           "file system."));
  72                 return 0;
  73         }
  74 
  75         if (!bs->reserved) {
  76                 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
  77                         _("File system has an invalid number of reserved "
  78                           "sectors for a FAT file system."));
  79                 return 0;
  80         }
  81 
  82         if (bs->fats < 1 || bs->fats > 4) {
  83                 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
  84                         _("File system has an invalid number of FATs."));
  85                 return 0;
  86         }
  87 
  88         return 1;
  89 }
  90 
  91 /*
  92     Don't trust the FAT12, FAT16 or FAT32 label string.
  93  */
  94 FatType
  95 fat_boot_sector_probe_type (const FatBootSector* bs, const PedGeometry* geom)
  96 {
  97         PedSector       logical_sector_size;
  98         PedSector       first_cluster_sector;
  99         FatCluster      cluster_count;
 100 
 101         if (!PED_LE16_TO_CPU (bs->dir_entries))
 102                 return FAT_TYPE_FAT32;
 103 
 104         logical_sector_size = PED_LE16_TO_CPU (bs->sector_size) / 512;
 105 
 106         first_cluster_sector
 107                 = PED_LE16_TO_CPU (bs->reserved) * logical_sector_size
 108                   + 2 * PED_LE16_TO_CPU (bs->fat_length) * logical_sector_size
 109                   + PED_LE16_TO_CPU (bs->dir_entries)
 110                         / (512 / sizeof (FatDirEntry));
 111         cluster_count = (geom->length - first_cluster_sector)
 112                         / bs->cluster_size / logical_sector_size;
 113         if (cluster_count > MAX_FAT12_CLUSTERS)
 114                 return FAT_TYPE_FAT16;
 115         else
 116                 return FAT_TYPE_FAT12;
 117 }
 118 
 119 /* Analyses the boot sector, and sticks appropriate numbers in
 120    fs->type_specific.
 121 
 122    Note: you need to subtract (2 * cluster_sectors) off cluster offset,
 123    because the first cluster is number 2.  (0 and 1 are not real clusters,
 124    and referencing them is a bug)
 125  */
 126 int
 127 fat_boot_sector_analyse (FatBootSector* bs, PedFileSystem* fs)
 128 {
 129         FatSpecific*            fs_info = FAT_SPECIFIC (fs);
 130         int                     fat_entry_size;
 131 
 132         PED_ASSERT (bs != NULL, return 0);
 133         
 134         if (PED_LE16_TO_CPU (bs->sector_size) != 512) {
 135                 if (ped_exception_throw (
 136                         PED_EXCEPTION_BUG,
 137                         PED_EXCEPTION_IGNORE_CANCEL,
 138                         _("This file system has a logical sector size of %d.  "
 139                         "GNU Parted is known not to work properly with sector "
 140                         "sizes other than 512 bytes."),
 141                         (int) PED_LE16_TO_CPU (bs->sector_size))
 142                                 != PED_EXCEPTION_IGNORE)
 143                         return 0;
 144         }
 145 
 146         fs_info->logical_sector_size = PED_LE16_TO_CPU (bs->sector_size) / 512;
 147 
 148         fs_info->sectors_per_track = PED_LE16_TO_CPU (bs->secs_track);
 149         fs_info->heads = PED_LE16_TO_CPU (bs->heads);
 150         if (fs_info->sectors_per_track < 1 || fs_info->sectors_per_track > 63
 151             || fs_info->heads < 1 || fs_info->heads > 255) {
 152                 PedCHSGeometry* bios_geom = &fs->geom->dev->bios_geom;
 153                 int cyl_count = 0;
 154 
 155                 if (fs_info->heads > 0 && fs_info->sectors_per_track > 0)
 156                         cyl_count = fs->geom->dev->length / fs_info->heads
 157                                         / fs_info->sectors_per_track;
 158 
 159                 switch (ped_exception_throw (
 160                         PED_EXCEPTION_ERROR,
 161                         PED_EXCEPTION_FIX + PED_EXCEPTION_IGNORE
 162                         + PED_EXCEPTION_CANCEL,
 163                         _("The file system's CHS geometry is (%d, %d, %d), "
 164                           "which is invalid.  The partition table's CHS "
 165                           "geometry is (%d, %d, %d).  If you select Ignore, "
 166                           "the file system's CHS geometry will be left "
 167                           "unchanged.  If you select Fix, the file system's "
 168                           "CHS geometry will be set to match the partition "
 169                           "table's CHS geometry."),
 170                          cyl_count, fs_info->heads, fs_info->sectors_per_track,
 171                          bios_geom->cylinders, bios_geom->heads,
 172                          bios_geom->sectors)) {
 173 
 174                 case PED_EXCEPTION_FIX:
 175                         fs_info->sectors_per_track = bios_geom->sectors;
 176                         fs_info->heads = bios_geom->heads;
 177                         bs->secs_track
 178                                 = PED_CPU_TO_LE16 (fs_info->sectors_per_track);
 179                         bs->heads = PED_CPU_TO_LE16 (fs_info->heads);
 180                         if (!fat_boot_sector_write (bs, fs))
 181                                 return 0;
 182                         break;
 183 
 184                 case PED_EXCEPTION_CANCEL:
 185                         return 0;
 186 
 187                 case PED_EXCEPTION_IGNORE:
 188                         break;
 189 
 190                 default:
 191                         break;
 192                 }
 193         }
 194 
 195         if (bs->sectors)
 196                 fs_info->sector_count = PED_LE16_TO_CPU (bs->sectors)
 197                                                 * fs_info->logical_sector_size;
 198         else
 199                 fs_info->sector_count = PED_LE32_TO_CPU (bs->sector_count)
 200                                                 * fs_info->logical_sector_size;
 201 
 202         fs_info->fat_table_count = bs->fats;
 203         fs_info->root_dir_entry_count = PED_LE16_TO_CPU (bs->dir_entries);
 204         fs_info->fat_offset = PED_LE16_TO_CPU (bs->reserved)
 205                                         * fs_info->logical_sector_size;
 206         fs_info->cluster_sectors = bs->cluster_size
 207                                    * fs_info->logical_sector_size;
 208         fs_info->cluster_size = fs_info->cluster_sectors * 512;
 209 
 210         if (fs_info->logical_sector_size == 0) {
 211                 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
 212                         _("FAT boot sector says logical sector size is 0.  "
 213                           "This is weird. "));
 214                 return 0;
 215         }
 216         if (fs_info->fat_table_count == 0) {
 217                 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
 218                         _("FAT boot sector says there are no FAT tables.  This "
 219                           "is weird. "));
 220                 return 0;
 221         }
 222         if (fs_info->cluster_sectors == 0) {
 223                 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
 224                         _("FAT boot sector says clusters are 0 sectors.  This "
 225                           "is weird. "));
 226                 return 0;
 227         }
 228 
 229         fs_info->fat_type = fat_boot_sector_probe_type (bs, fs->geom);
 230         if (fs_info->fat_type == FAT_TYPE_FAT12) {
 231                 ped_exception_throw (
 232                         PED_EXCEPTION_NO_FEATURE,
 233                         PED_EXCEPTION_CANCEL,
 234                         _("File system is FAT12, which is unsupported."));
 235                 return 0;
 236         }
 237         if (fs_info->fat_type == FAT_TYPE_FAT16) {
 238                 fs_info->fat_sectors = PED_LE16_TO_CPU (bs->fat_length)
 239                                        * fs_info->logical_sector_size;
 240                 fs_info->serial_number
 241                         = PED_LE32_TO_CPU (bs->u.fat16.serial_number);
 242                 fs_info->root_cluster = 0;
 243                 fs_info->root_dir_offset
 244                         = fs_info->fat_offset
 245                           + fs_info->fat_sectors * fs_info->fat_table_count;
 246                 fs_info->root_dir_sector_count
 247                         = fs_info->root_dir_entry_count * sizeof (FatDirEntry)
 248                           / (512 * fs_info->logical_sector_size);
 249                 fs_info->cluster_offset
 250                         = fs_info->root_dir_offset
 251                           + fs_info->root_dir_sector_count;
 252         }
 253         if (fs_info->fat_type == FAT_TYPE_FAT32) {
 254                 fs_info->fat_sectors = PED_LE32_TO_CPU (bs->u.fat32.fat_length)
 255                                         * fs_info->logical_sector_size;
 256                 fs_info->serial_number
 257                         = PED_LE32_TO_CPU (bs->u.fat32.serial_number);
 258                 fs_info->info_sector_offset
 259                     = PED_LE16_TO_CPU (fs_info->boot_sector.u.fat32.info_sector)
 260                           * fs_info->logical_sector_size;
 261                 fs_info->boot_sector_backup_offset
 262                   = PED_LE16_TO_CPU (fs_info->boot_sector.u.fat32.backup_sector)
 263                           * fs_info->logical_sector_size;
 264                 fs_info->root_cluster
 265                         = PED_LE32_TO_CPU (bs->u.fat32.root_dir_cluster);
 266                 fs_info->root_dir_offset = 0;
 267                 fs_info->root_dir_sector_count = 0;
 268                 fs_info->cluster_offset
 269                         = fs_info->fat_offset
 270                           + fs_info->fat_sectors * fs_info->fat_table_count;
 271         }
 272 
 273         fs_info->cluster_count
 274                 = (fs_info->sector_count - fs_info->cluster_offset)
 275                   / fs_info->cluster_sectors;
 276 
 277         fat_entry_size = fat_table_entry_size (fs_info->fat_type);
 278         if (fs_info->cluster_count + 2
 279                         > fs_info->fat_sectors * 512 / fat_entry_size)
 280                 fs_info->cluster_count
 281                         = fs_info->fat_sectors * 512 / fat_entry_size - 2;
 282 
 283         fs_info->dir_entries_per_cluster
 284                 = fs_info->cluster_size / sizeof (FatDirEntry);
 285         return 1;
 286 }
 287 
 288 #ifndef DISCOVER_ONLY
 289 int
 290 fat_boot_sector_set_boot_code (FatBootSector* bs)
 291 {
 292         PED_ASSERT (bs != NULL, return 0);
 293 
 294         memset (bs, 0, 512);
 295         memcpy (bs->boot_jump, FAT_BOOT_JUMP, 3);
 296         memcpy (bs->u.fat32.boot_code, FAT_BOOT_CODE, FAT_BOOT_CODE_LENGTH);
 297         return 1;
 298 }
 299 
 300 int
 301 fat_boot_sector_generate (FatBootSector* bs, const PedFileSystem* fs)
 302 {
 303         FatSpecific*    fs_info = FAT_SPECIFIC (fs);
 304 
 305         PED_ASSERT (bs != NULL, return 0);
 306 
 307         memcpy (bs->system_id, "MSWIN4.1", 8);
 308         bs->sector_size = PED_CPU_TO_LE16 (fs_info->logical_sector_size * 512);
 309         bs->cluster_size = fs_info->cluster_sectors
 310                                 / fs_info->logical_sector_size;
 311         bs->reserved = PED_CPU_TO_LE16 (fs_info->fat_offset
 312                                         / fs_info->logical_sector_size);
 313         bs->fats = fs_info->fat_table_count;
 314 
 315         bs->dir_entries = (fs_info->fat_type == FAT_TYPE_FAT16)
 316                           ? PED_CPU_TO_LE16 (fs_info->root_dir_entry_count)
 317                           : 0;
 318 
 319         if (fs_info->sector_count / fs_info->logical_sector_size > 0xffff
 320                 || fs_info->fat_type == FAT_TYPE_FAT32) {
 321                 bs->sectors = 0;
 322                 bs->sector_count = PED_CPU_TO_LE32 (fs_info->sector_count
 323                                                 / fs_info->logical_sector_size);
 324         } else {
 325                 bs->sectors = PED_CPU_TO_LE16 (fs_info->sector_count
 326                                                / fs_info->logical_sector_size);
 327                 bs->sector_count = 0;
 328         }
 329 
 330         bs->media = 0xf8;
 331 
 332         bs->secs_track = PED_CPU_TO_LE16 (fs_info->sectors_per_track);
 333         bs->heads = PED_CPU_TO_LE16 (fs_info->heads);
 334         bs->hidden = PED_CPU_TO_LE32 (fs->geom->start);
 335 
 336         if (fs_info->fat_type == FAT_TYPE_FAT32) {
 337                 bs->fat_length = 0;
 338                 bs->u.fat32.fat_length = PED_CPU_TO_LE32 (fs_info->fat_sectors
 339                                                 / fs_info->logical_sector_size);
 340                 bs->u.fat32.flags = 0;       /* FIXME: what the hell are these? */
 341                 bs->u.fat32.version = 0;  /* must be 0, for Win98 bootstrap */
 342                 bs->u.fat32.root_dir_cluster
 343                         = PED_CPU_TO_LE32 (fs_info->root_cluster);
 344                 bs->u.fat32.info_sector
 345                         = PED_CPU_TO_LE16 (fs_info->info_sector_offset
 346                                            / fs_info->logical_sector_size);
 347                 bs->u.fat32.backup_sector
 348                         = PED_CPU_TO_LE16 (fs_info->boot_sector_backup_offset
 349                                            / fs_info->logical_sector_size);
 350 
 351                 bs->u.fat32.drive_num = 0x80;        /* _ALWAYS_ 0x80.  silly DOS */
 352 
 353                 memset (bs->u.fat32.empty_1, 0, 12);
 354 
 355                 bs->u.fat32.ext_signature = 0x29;
 356                 bs->u.fat32.serial_number
 357                         = PED_CPU_TO_LE32 (fs_info->serial_number);
 358                 memcpy (bs->u.fat32.volume_name, "NO NAME    ", 11);
 359                 memcpy (bs->u.fat32.fat_name, "FAT32   ", 8);
 360         } else {
 361                 bs->fat_length
 362                         = PED_CPU_TO_LE16 (fs_info->fat_sectors
 363                                            / fs_info->logical_sector_size);
 364 
 365                 bs->u.fat16.drive_num = 0x80;        /* _ALWAYS_ 0x80.  silly DOS */
 366 
 367                 bs->u.fat16.ext_signature = 0x29;
 368                 bs->u.fat16.serial_number
 369                         = PED_CPU_TO_LE32 (fs_info->serial_number);
 370                 memcpy (bs->u.fat16.volume_name, "NO NAME    ", 11);
 371                 memcpy (bs->u.fat16.fat_name, "FAT16   ", 8);
 372         }
 373 
 374         bs->boot_sign = PED_CPU_TO_LE16 (0xaa55);
 375 
 376         return 1;
 377 }
 378 
 379 int
 380 fat_boot_sector_write (const FatBootSector* bs, PedFileSystem* fs)
 381 {
 382         FatSpecific*    fs_info = FAT_SPECIFIC (fs);
 383 
 384         PED_ASSERT (bs != NULL, return 0);
 385 
 386         if (!ped_geometry_write (fs->geom, bs, 0, 1))
 387                 return 0;
 388         if (fs_info->fat_type == FAT_TYPE_FAT32) {
 389                 if (!ped_geometry_write (fs->geom, bs,
 390                                          fs_info->boot_sector_backup_offset, 1))
 391                         return 0;
 392         }
 393         return ped_geometry_sync (fs->geom);
 394 }
 395 
 396 int
 397 fat_info_sector_read (FatInfoSector* is, const PedFileSystem* fs)
 398 {
 399         FatSpecific*    fs_info = FAT_SPECIFIC (fs);
 400         int             status;
 401 
 402         PED_ASSERT (is != NULL, return 0);
 403         
 404         if (!ped_geometry_read (fs->geom, is, fs_info->info_sector_offset, 1))
 405                 return 0;
 406 
 407         if (PED_LE32_TO_CPU (is->signature_2) != FAT32_INFO_MAGIC2) {
 408                 status = ped_exception_throw (PED_EXCEPTION_WARNING,
 409                                 PED_EXCEPTION_IGNORE_CANCEL,
 410                                 _("The information sector has the wrong "
 411                                 "signature (%x).  Select cancel for now, "
 412                                 "and send in a bug report.  If you're "
 413                                 "desperate, it's probably safe to ignore."),
 414                                 PED_LE32_TO_CPU (is->signature_2));
 415                 if (status == PED_EXCEPTION_CANCEL) return 0;
 416         }
 417         return 1;
 418 }
 419 
 420 int
 421 fat_info_sector_generate (FatInfoSector* is, const PedFileSystem* fs)
 422 {
 423         FatSpecific*    fs_info = FAT_SPECIFIC (fs);
 424 
 425         PED_ASSERT (is != NULL, return 0);
 426         
 427         fat_table_count_stats (fs_info->fat);
 428 
 429         memset (is, 0, 512);
 430 
 431         is->signature_1 = PED_CPU_TO_LE32 (FAT32_INFO_MAGIC1);
 432         is->signature_2 = PED_CPU_TO_LE32 (FAT32_INFO_MAGIC2);
 433         is->free_clusters = PED_CPU_TO_LE32 (fs_info->fat->free_cluster_count);
 434         is->next_cluster = PED_CPU_TO_LE32 (fs_info->fat->last_alloc);
 435         is->signature_3 = PED_CPU_TO_LE16 (FAT32_INFO_MAGIC3);
 436 
 437         return 1;
 438 }
 439 
 440 int
 441 fat_info_sector_write (const FatInfoSector* is, PedFileSystem *fs)
 442 {
 443         FatSpecific*    fs_info = FAT_SPECIFIC (fs);
 444 
 445         PED_ASSERT (is != NULL, return 0);
 446         
 447         if (!ped_geometry_write (fs->geom, is, fs_info->info_sector_offset, 1))
 448                 return 0;
 449         return ped_geometry_sync (fs->geom);
 450 }
 451 #endif /* !DISCOVER_ONLY */
 452