免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5803 | 回复: 0
打印 上一主题 下一主题

读取FAT12磁盘镜像的文件。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-08-22 16:42 |只看该作者 |倒序浏览

                头文件
               
               
               
               
               
#ifndef __FAT_H__
#define __FAT_H__
struct fat32_struct{
    uint8_t jmp[3];
    uint8_t oem[8];
    uint8_t bpb[53];
    uint8_t bpbx[26];
    uint8_t boot[420];
    uint8_t magic[2];
}__attribute__((packed));
struct fat32_bpb{
    uint16_t bytes_per_sector;
    uint8_t  sectors_per_cluster;
    uint16_t reserved_sector;
    uint8_t  number_of_FAT;
    uint16_t root_entries;
    uint16_t small_sector;
    uint8_t  media_descriptor;
    uint16_t sectors_per_fat;
    uint16_t sectors_per_track;
    uint16_t number_of_head;
    uint32_t hidden_sectors;
    uint32_t large_sector;
    uint32_t sectors_per_fat32;
    uint16_t extended_flags;
    uint16_t filesystem_version;
    uint32_t root_cluster_number;
    uint16_t system_info_sector_number;
    uint16_t backup_sectors;
    uint16_t reserverd[6];
}__attribute__((packed));
struct fat32_bpbx{
    uint8_t driver_number;
    uint8_t reserver;
    uint8_t extended_boot_signature;
    uint32_t volume_serial_number;
    uint8_t  volume_label[11];
    uint8_t  filesystem_type[8];
}__attribute__((packed));
struct fat_struct{
    uint8_t jmp[3];
    uint8_t oem[8];
    uint8_t bpb[25];
    uint8_t bpbx[26];
    uint8_t boot[448];
    uint8_t magic[4];
}__attribute__((packed));
struct fat_bpb{
    uint16_t bytes_per_sector;
    uint8_t  sectors_per_cluster;
    uint16_t reserved_sector;
    uint8_t  number_of_FAT;
    uint16_t root_entries;
    uint16_t small_sector;
    uint8_t  media_desc;
    uint16_t sectors_per_fat;
    uint16_t sectors_per_track;
    uint16_t number_of_heads;
    uint32_t hidden_sectors;
    uint32_t large_sectors;
}__attribute__((packed));
struct fat_bpbx{
    uint8_t  physical_drive_number;
    uint8_t  reserverd;
    uint8_t  extended_boot_signature;
    uint32_t volume_serial_number;
    uint8_t  volume_label[11];
    uint8_t  filesystem_type[8];
}__attribute__((packed));
struct fat_entry{
    uint8_t name[8];
    uint8_t fext[3];
    uint8_t attribute;
    uint8_t reserverd[10];
    uint16_t mtime;
    uint16_t mdate;
    uint16_t cluster_entry;
    uint32_t length;
}__attribute__((packed));
#endif
源文件:
#include stdio.h>
#include string.h>
#include stdint.h>
#include stdlib.h>
#include assert.h>
#include "fat.h"
#define WRITE_FILE 1
struct fat_fsop{
    FILE *fp;
    struct fat_bpb bpb;
};
struct fat_file{
    size_t offset;
    size_t cluster;
    struct fat_fsop *fsop;
    struct fat_entry entry;
};
int fat_read_sector(struct fat_fsop *fsop, size_t sector, void *buff)
{
    struct fat_bpb *bpb = &fsop->bpb;
    assert(bpb->bytes_per_sector>=512);
    if (0!=fseek(fsop->fp, sector*bpb->bytes_per_sector, SEEK_SET)){
        printf("__fat_read_sector: %d\n", sector);
           return -1;
    }
    return fread(buff, bpb->bytes_per_sector, 1, fsop->fp);
}
int fat_read_cluster(struct fat_fsop *fsop, size_t cluster, void *buff)
{
    int i = 0;
    size_t cpcnt = 0;
    char *p = (char*)buff;
    struct fat_bpb *bpb = &fsop->bpb;
    size_t sector = bpb->reserved_sector;
    sector += bpb->sectors_per_fat*bpb->number_of_FAT;
    sector += (cluster-2)*bpb->sectors_per_cluster;
    sector += (bpb->root_entries*32)/(bpb->sectors_per_cluster*bpb->bytes_per_sector);
    assert(bpb->sectors_per_cluster>0);
    for (i=0; ibpb->sectors_per_cluster; i++){
        if (fat_read_sector(fsop, sector, p+cpcnt)==-1){
            printf("fat_read_sector: %d\n", sector);
            return -1;
        }
        cpcnt += bpb->bytes_per_sector;
        sector++;
    }
    return 0;
}
int fat_read_dir(struct fat_fsop *fsop, const char *path)
{
    struct fat_bpb *bpb = &fsop->bpb;
    return -1;
}
int dirent_trim(const char *buff, size_t count)
{
    const char *p = buff;
    const char *end = buff+count;
    while(pend&&*p&&*p!=' ')p++;
    return (p-buff);
}
#define IS_DIR(flag) ((flag)&0x10)
int fat_dirent_lookup(struct fat_entry *dirents, size_t dpcnt, const char *path, struct fat_entry *dirent)
{
    char name[13];
    size_t j, cpcnt, cpcntext;
    for (j=0; jdpcnt; j++){
        cpcnt = dirent_trim(dirents[j].name, 8);
        if (cpcnt > 0){
            strncpy(name, dirents[j].name, cpcnt);
            cpcntext = dirent_trim(dirents[j].fext, 3);
            cpcntext&&(name[cpcnt++]='.');
            strncpy(name+cpcnt, dirents[j].fext, cpcntext);
            name[cpcnt+cpcntext] = 0;
            if (!strcmp(path, name)){
                *dirent= dirents[j];
                return 0;
            }
        }
    }
    return -1;
}
int fat_lookup(struct fat_fsop *fsop, struct fat_entry *folder,
        const char *path, struct fat_entry *entry)
{
    struct fat_bpb *bpb = &fsop->bpb;
    size_t bytes_per_cluster = (bpb->bytes_per_sector*bpb->sectors_per_cluster);
    char *cluster_buffer = (char*)malloc(bytes_per_cluster);
    if (!IS_DIR(folder->attribute)){
        return -1;
    }
    size_t valid_cluster = folder->cluster_entry;
    size_t dpcnt  = bytes_per_cluster/32;
    struct fat_entry *dirents;
    dirents = (struct fat_entry*)cluster_buffer;
   
    while (valid_cluster  0xFF0){
        size_t cluster;
        if (-1==fat_read_cluster(fsop, valid_cluster, cluster_buffer)){
            free(cluster_buffer);
            return -1;
        }
        if (0==fat_dirent_lookup(dirents, dpcnt, path, entry)){
            free(cluster_buffer);
            return 0;
        }
      
        if (-1==fat_next_cluster(fsop, valid_cluster, &cluster)){
            free(cluster_buffer);
            return -1;
        }
        valid_cluster = cluster;
    }
    free(cluster_buffer);
    return -1;
}
int fat_namei(struct fat_fsop *fsop, const char *path, struct fat_entry *entry)
{
    int idx, count;
    struct fat_bpb *bpb = &fsop->bpb;
    idx  = bpb->reserved_sector;
    idx += bpb->sectors_per_fat*bpb->number_of_FAT;
    char *sector_buffer = (char*)malloc(bpb->bytes_per_sector);
    for (count=0; countbpb->root_entries;idx++){
        if (0>=fat_read_sector(fsop, idx, sector_buffer)){
            free(sector_buffer);
            return -1;
        }
        size_t dpcnt  = bpb->bytes_per_sector/32;
        if (dpcnt+count > bpb->root_entries)
            dpcnt = bpb->root_entries-count;
        struct fat_entry *dirents;
        dirents = (struct fat_entry*)sector_buffer;
        if (0==fat_dirent_lookup(dirents, dpcnt, path, entry)){
            free(sector_buffer);
            return 0;
        }
        count += dpcnt;
    }
    free(sector_buffer);
    return -1;
}
int fat_open_volume(struct fat_fsop *fsop, const char *path)
{
    FILE *fp = NULL;
    char volume[512];
    struct fat_struct *fs;
    fs = (struct fat_struct*)volume;
    struct fat_bpb *bpb;
    bpb = (struct fat_bpb*)fs->bpb;
    struct fat_bpbx *bpbx;
    bpbx = (struct fat_bpbx *)fs->bpbx;
    if (NULL==(fp=fopen(path, "rb"))){
        return -1;
    }
    if (!fread(volume, 512, 1, fp)){
        goto open_volume_fail;
    }
    if (memcmp(bpbx->filesystem_type, "FAT12   ", 8)){
        goto open_volume_fail;
    }
    if (bpb->root_entries&0xF){
        goto open_volume_fail;
    }
    fsop->bpb = *bpb;
    fsop->fp = fp;
    return 0;
open_volume_fail:
    fclose(fp);
    return -1;
}
#define IS_FILE(flag) (((flag)&0x18)==0)
int fat_open_file(struct fat_fsop *fsop, struct fat_entry *entry,
           struct fat_file *file)
{
    file->fsop = fsop;
    file->entry = *entry;
    file->offset = 0;
    file->cluster = entry->cluster_entry;
    return 0;
}
int fat_next_cluster(struct fat_fsop *fsop, size_t cluster, size_t *pcluster)
{
    int count;
    struct fat_bpb *bpb = &fsop->bpb;
    size_t fat_start = bpb->reserved_sector;
    size_t bitcnt = cluster*12;
    size_t sectorcnt = bitcnt/(bpb->bytes_per_sector*8);
    uint8_t *sector_buffer = (uint8_t*)malloc(bpb->bytes_per_sector*2);
    assert(sector_buffer != NULL);
    if (-1==fat_read_sector(fsop, fat_start+sectorcnt, sector_buffer)){
        free(sector_buffer);
        return -1;
    }
    size_t bitcnt_in_sector = bitcnt-(bpb->bytes_per_sector*8*sectorcnt);
    size_t bytecnt_in_sector = bitcnt_in_sector/8;
    if (bytecnt_in_sector+1 == bpb->bytes_per_sector){
           if (-1==fat_read_sector(fsop, fat_start+sectorcnt+1,
            sector_buffer+bpb->bytes_per_sector)){
            free(sector_buffer);
            return -1;
        }
    }
    uint8_t *fat_cluster = (sector_buffer+bytecnt_in_sector);
    uint32_t retval = fat_cluster[0]|(fat_cluster[1]8);
    free(sector_buffer);
    *pcluster = (bitcnt_in_sector&0x7)?(retval>>4):(retval&0xFFF);
    return 0;
}
int fat_pread_file(struct fat_file *file, void *buff,
           size_t count, size_t offset)
{
    struct fat_entry *dirent = &file->entry;
    if (!IS_DIR(file->entry.attribute)){
        if (offset > dirent->length)
            return -1;
        if (offset+count > dirent->length)
            count = dirent->length - offset;
    }
    if (count == 0)
        return 0;
    if (offset  file->offset){
        file->cluster = dirent->cluster_entry;
        file->offset = 0;
    }
    size_t i;
    struct fat_bpb *bpb = &file->fsop->bpb;
    size_t bytes_per_cluster = (bpb->bytes_per_sector*bpb->sectors_per_cluster);
    size_t cluster_count = (offset - file->offset)/bytes_per_cluster;
    while(cluster_count>0){
        size_t cluster;
        if (fat_next_cluster(file->fsop, file->cluster, &cluster)==-1){
            return -1;
        }
        if (cluster >= 0xFFF){
            return 0;
        }
        file->offset += bytes_per_cluster;
        file->cluster = cluster;
        cluster_count--;
    }
    char *cluster_buffer = (char*)malloc(bytes_per_cluster);
    assert(cluster_buffer);
    if (fat_read_cluster(file->fsop, file->cluster, cluster_buffer)){
        free(cluster_buffer);
        return -1;
    }
    size_t cluster_offset = offset-file->offset;
    size_t cpcnt = bytes_per_cluster>cluster_offset+count?
        count:bytes_per_cluster-cluster_offset;
    memcpy(buff, cluster_buffer+cluster_offset, cpcnt);
    free(cluster_buffer);
    offset += cpcnt;
    count  -= cpcnt;
    int hr = 0;
    while (offsetdirent->length && count>0){
        if ((hr=fat_pread_file(file, (char*)buff+cpcnt, count, offset))==-1){
            return -1;
        }
        if (hr == 0){
            break;
        }
        offset += hr;
        count -= hr;
        cpcnt += hr;
    }
    return cpcnt;
}
const char *paths[] = {
    "IO.SYS", "AUTOEXEC.BAT", "CONFIG.SYS", "SETRAMD.BAT", "README.TXT",
    "FINDRAMD.EXE", "RAMDRIVE.SYS", "ASPI4DOS.SYS", "BTCDROM.SYS", "ASPICD.SYS",
    "BTDOSM.SYS", "ASPI2DOS.SYS", "ASPI8DOS.SYS", "ASPI8U2.SYS", "FLASHPT.SYS",
    "EXTRACT.EXE", "FDISK.EXE", "DRVSPACE.BIN", "COMMAND.COM", "HIMEM.SYS",
    "OAKCDROM.SYS", "EBD.CAB", "MSDOS.SYS", "EBD.SYS", "HELLO", "TEST.TXT", NULL
};
void save2file(struct fat_file *file, const char *path)
{
    char buffer[4090];
    size_t offset = 0;
    int rcnt = fat_pread_file(file, buffer, sizeof(buffer), offset);
#ifdef WRITE_FILE
    char file_name[128];
    sprintf(file_name, "data/%s", path);
    FILE *fp = fopen(file_name, "wb");
#endif
    while (rcnt > 0){
        offset += rcnt;
#ifdef WRITE_FILE
        if (fp != NULL)
            fwrite(buffer, rcnt, 1, fp);
#endif
        rcnt = fat_pread_file(file, buffer, sizeof(buffer), offset);
    }
    printf("last read count: %d %d\n", rcnt, offset);
#ifdef WRITE_FILE
    if (fp != NULL)
        fclose(fp);
#endif
}
int main(int argc, char *argv[])
{
    int i;
    struct fat_fsop fsop;
    if (fat_open_volume(&fsop, "win98.img"))
        return -1;
    struct fat_file file;
    struct fat_entry entry;
    /* save hello/fstab to local disk */
    if (-1!=fat_namei(&fsop, "HELLO", &entry)){
        if (0==fat_open_file(&fsop, &entry, &file)){
            save2file(&file, "fstab");
        }
#if 1
        struct fat_entry dirent;
        if (0==fat_lookup(&fsop, &entry, "__.TXT", &dirent)){
            if (0==fat_open_file(&fsop, &dirent, &file)){
                save2file(&file, "fstab.txt");
            }
        }
#endif
    }
    for (i=0; paths; i++){
        if (fat_namei(&fsop, paths, &entry))
            continue;
        printf("%-13s first cluster: %6d length: %6d\n",
                paths, entry.cluster_entry, entry.length);
        if (fat_open_file(&fsop, &entry, &file)){
            printf("file %s open fail!\n", paths);
            continue;
        }
        save2file(&file, paths);
    }
    return 0;
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/69656/showart_2034540.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP