1 #ident "$Id: fatchain.c,v 1.1 2004/12/15 10:14:39 hpa Exp $"
2 /* ----------------------------------------------------------------------- *
4 * Copyright 2004 H. Peter Anvin - All Rights Reserved
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
9 * Boston MA 02111-1307, USA; either version 2 of the License, or
10 * (at your option) any later version; incorporated herein by reference.
12 * ----------------------------------------------------------------------- */
20 #include "libfatint.h"
24 * Convert a cluster number (or 0 for the root directory) to a
25 * sector number. Return -1 on failure.
27 libfat_sector_t libfat_clustertosector(const struct libfat_filesystem *fs,
31 cluster = fs->rootcluster;
35 else if ( cluster < 2 || cluster >= fs->endcluster )
38 return fs->data + ((libfat_sector_t)(cluster-2) << fs->clustshift);
42 * Get the next sector of either the root directory or a FAT chain.
43 * Returns 0 on end of file and -1 on error.
46 libfat_sector_t libfat_nextsector(struct libfat_filesystem *fs,
49 int32_t cluster, nextcluster;
51 libfat_sector_t fatsect;
53 uint32_t clustmask = fs->clustsize - 1;
57 if ( s < fs->rootdir )
62 return ( s < fs->data ) ? s : 0;
67 if ( ~rs & clustmask )
68 return s+1; /* Next sector in cluster */
70 cluster = 2 + (rs >> fs->clustshift);
72 if ( cluster >= fs->endcluster )
75 switch ( fs->fat_type ) {
78 fatoffset = cluster + (cluster >> 1);
79 fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
80 fsdata = libfat_get_sector(fs, fatsect);
83 nextcluster = fsdata[fatoffset & LIBFAT_SECTOR_MASK];
87 fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
88 fsdata = libfat_get_sector(fs, fatsect);
91 nextcluster |= fsdata[fatoffset & LIBFAT_SECTOR_MASK] << 8;
93 /* Extract the FAT entry */
97 nextcluster &= 0x0FFF;
99 if ( nextcluster >= 0x0FF8 )
104 fatoffset = cluster << 1;
105 fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
106 fsdata = libfat_get_sector(fs, fatsect);
109 nextcluster = read16((le16_t *)&fsdata[fatoffset & LIBFAT_SECTOR_MASK]);
111 if ( nextcluster >= 0x0FFF8 )
116 fatoffset = cluster << 2;
117 fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
118 fsdata = libfat_get_sector(fs, fatsect);
121 nextcluster = read32((le32_t *)&fsdata[fatoffset & LIBFAT_SECTOR_MASK]);
122 nextcluster &= 0x0FFFFFFF;
124 if ( nextcluster >= 0x0FFFFFF8 )
129 return -1; /* WTF? */
132 return libfat_clustertosector(fs, nextcluster);