source: bootcd/isolinux/syslinux-6.03/libfat/fatchain.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 3.2 KB
Line 
1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
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, Inc., 53 Temple Place Ste 330,
8 *   Boston MA 02111-1307, USA; either version 2 of the License, or
9 *   (at your option) any later version; incorporated herein by reference.
10 *
11 * ----------------------------------------------------------------------- */
12
13/*
14 * fatchain.c
15 *
16 * Follow a FAT chain
17 */
18
19#include "libfatint.h"
20#include "ulint.h"
21
22/*
23 * Convert a cluster number (or 0 for the root directory) to a
24 * sector number.  Return -1 on failure.
25 */
26libfat_sector_t libfat_clustertosector(const struct libfat_filesystem *fs,
27                                       int32_t cluster)
28{
29    if (cluster == 0)
30        cluster = fs->rootcluster;
31
32    if (cluster == 0)
33        return fs->rootdir;
34    else if (cluster < 2 || cluster >= fs->endcluster)
35        return -1;
36    else
37        return fs->data + ((libfat_sector_t) (cluster - 2) << fs->clustshift);
38}
39
40/*
41 * Get the next sector of either the root directory or a FAT chain.
42 * Returns 0 on end of file and -1 on error.
43 */
44
45libfat_sector_t libfat_nextsector(struct libfat_filesystem * fs,
46                                  libfat_sector_t s)
47{
48    int32_t cluster, nextcluster;
49    uint32_t fatoffset;
50    libfat_sector_t fatsect;
51    uint8_t *fsdata;
52    uint32_t clustmask = fs->clustsize - 1;
53    libfat_sector_t rs;
54
55    if (s < fs->data) {
56        if (s < fs->rootdir)
57            return -1;
58
59        /* Root directory */
60        s++;
61        return (s < fs->data) ? s : 0;
62    }
63
64    rs = s - fs->data;
65
66    if (~rs & clustmask)
67        return s + 1;           /* Next sector in cluster */
68
69    cluster = 2 + (rs >> fs->clustshift);
70
71    if (cluster >= fs->endcluster)
72        return -1;
73
74    switch (fs->fat_type) {
75    case FAT12:
76        /* Get first byte */
77        fatoffset = cluster + (cluster >> 1);
78        fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
79        fsdata = libfat_get_sector(fs, fatsect);
80        if (!fsdata)
81            return -1;
82        nextcluster = fsdata[fatoffset & LIBFAT_SECTOR_MASK];
83
84        /* Get second byte */
85        fatoffset++;
86        fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
87        fsdata = libfat_get_sector(fs, fatsect);
88        if (!fsdata)
89            return -1;
90        nextcluster |= fsdata[fatoffset & LIBFAT_SECTOR_MASK] << 8;
91
92        /* Extract the FAT entry */
93        if (cluster & 1)
94            nextcluster >>= 4;
95        else
96            nextcluster &= 0x0FFF;
97
98        if (nextcluster >= 0x0FF8)
99            return 0;
100        break;
101
102    case FAT16:
103        fatoffset = cluster << 1;
104        fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
105        fsdata = libfat_get_sector(fs, fatsect);
106        if (!fsdata)
107            return -1;
108        nextcluster =
109            read16((le16_t *) & fsdata[fatoffset & LIBFAT_SECTOR_MASK]);
110
111        if (nextcluster >= 0x0FFF8)
112            return 0;
113        break;
114
115    case FAT28:
116        fatoffset = cluster << 2;
117        fatsect = fs->fat + (fatoffset >> LIBFAT_SECTOR_SHIFT);
118        fsdata = libfat_get_sector(fs, fatsect);
119        if (!fsdata)
120            return -1;
121        nextcluster =
122            read32((le32_t *) & fsdata[fatoffset & LIBFAT_SECTOR_MASK]);
123        nextcluster &= 0x0FFFFFFF;
124
125        if (nextcluster >= 0x0FFFFFF8)
126            return 0;
127        break;
128
129    default:
130        return -1;              /* WTF? */
131    }
132
133    return libfat_clustertosector(fs, nextcluster);
134}
Note: See TracBrowser for help on using the repository browser.