fat.c revision 2603474ff9be2418900581da1af5cccc9f13cae1
/*
* volume_id - reads filesystem label and uuid
*
* Copyright (C) 2004-2007 Kay Sievers <kay.sievers@vrfy.org>
* Copyright (C) 2007 Ryan Lortie <desrt@desrt.ca>
*
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 of the License.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "libvolume_id.h"
#include "libvolume_id-private.h"
#include "util.h"
#define FAT12_MAX 0xff5
#define FAT16_MAX 0xfff5
#define FAT_ATTR_VOLUME_ID 0x08
#define FAT_ATTR_DIR 0x10
#define FAT_ATTR_LONG_NAME 0x0f
#define FAT_ATTR_MASK 0x3f
#define FAT_ENTRY_FREE 0xe5
#define VFAT_LFN_SEQ_MASK 0x3f
#define VFAT_LFN_SEQ_LAST 0x40
#define VFAT_LFN_SEQ_MAX 20
#define VFAT_LOWERCASE_NAME 0x10
#define VFAT_LOWERCASE_EXT 0x08
struct vfat_super_block {
union {
struct fat_super_block {
struct fat32_super_block {
} PACKED;
struct fat32_fsinfo {
} PACKED;
struct vfat_dir_entry {
} PACKED;
struct vfat_lfn_entry {
} PACKED;
{
int i;
for (i = 0; i < 11; i++)
return cksum;
}
struct vfat_dir_entry *dir,
struct vfat_dir_entry *entry)
{
if (expected_seq > VFAT_LFN_SEQ_MAX)
break;
break;
break;
break;
break;
/* extra paranoia -- should never happen */
break;
break;
}
}
return fnlen;
}
{
int i;
/* check if maybe we have LFN entries */
if (len > 0)
goto out;
/* else, read the normal 8.3 name */
for (i = 0; i < 11; i++) {
else
}
len = 11;
out:
return len;
}
/* fills filename, returns string length */
{
unsigned int i;
for (i = 0; i < count; i++) {
/* end marker */
dbg("end of dir\n");
break;
}
/* empty entry */
continue;
/* long name */
continue;
/* labels do not have file data */
continue;
dbg("found ATTR_VOLUME_ID id in root dir\n");
}
dbg("skip dir entry\n");
}
return 0;
}
{
struct vfat_super_block *vs;
struct vfat_dir_entry *dir;
struct fat32_fsinfo *fsinfo;
int maxloop;
return -1;
/* check signature */
return -1;
return -1;
/* believe only that's fat, don't trust the version */
goto magic;
goto magic;
goto magic;
goto magic;
goto magic;
/* some old floppies don't have a magic, expect the boot jump address to match */
return -1;
/* reserverd sector count */
return -1;
/* fat count */
return -1;
/* media check */
return -1;
/* cluster size check */
if (vs->sectors_per_cluster == 0 ||
return -1;
/* sector size check */
return -1;
if (sect_count == 0)
if (fat_length)
else if (fat32_length)
else
return -1;
/* must be FAT32 */
if (!fat_length && fat32_length)
goto fat32;
/* cluster_count tells us the format */
if (cluster_count < FAT12_MAX)
else if (cluster_count < FAT16_MAX)
else
goto fat32;
/* the label may be an attribute in the root directory */
goto found;
return -1;
}
goto found;
/* FAT32 should have a valid signature in the fsinfo block */
return -1;
return -1;
return -1 ;
return -1;
/* FAT32 root dir is a cluster chain like any other directory */
next = root_cluster;
maxloop = 100;
while (--maxloop) {
int count;
/* get cluster */
goto found;
if (fnlen > 0)
break;
/* get FAT entry */
goto found;
/* set next cluster */
break;
}
if (maxloop == 0)
dbg("reached maximum follow count of root cluster chain, give up\n");
return -1;
}
return 0;
}