FAT16复制/导出命令行工具实现

时间:2015-03-29 18:19:00

标签: c++ c++11 filesystems fat

我正在使用命令行工具,它允许您将数据从加载的FAT16文件系统复制并导出到您自己的本机文件系统。例如,现在,我的程序是这样的:

./a.out Adisk16.raw FOO.TXT
FAT start at 00001000, root dir at 0003E000, data at 00042000
File found!
Copied 342 bytes

我希望它能像这样工作:

./a.out Adisk16.raw
:/> cpout FOO.TXT
FAT start at 00001000, root dir at 0003E000, data at 00042000
File found!
Copied 342 bytes
:/>

我的代码如下。任何人都可以帮我这个吗?

#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <errno.h>

typedef struct {
    unsigned char first_byte;
    unsigned char start_chs[3];
    unsigned char partition_type;
    unsigned char end_chs[3];
    unsigned long start_sector;
    unsigned long length_sectors;
} __attribute((packed)) PartitionTable;

typedef struct {
    unsigned char jmp[3];
    char oem[8];
    unsigned short sector_size;
    unsigned char sectors_per_cluster;
    unsigned short reserved_sectors;
    unsigned char number_of_fats;
    unsigned short root_dir_entries;
    unsigned short total_sectors_short; // if zero, later field is used
    unsigned char media_descriptor;
    unsigned short fat_size_sectors;
    unsigned short sectors_per_track;
    unsigned short number_of_heads;
    unsigned long hidden_sectors;
    unsigned long total_sectors_long;

    unsigned char drive_number;
    unsigned char current_head;
    unsigned char boot_signature;
    unsigned long volume_id;
    char volume_label[11];
    char fs_type[8];
    char boot_code[448];
    unsigned short boot_sector_signature;
} __attribute((packed)) Fat16BootSector;

typedef struct {
    unsigned char filename[8];
    unsigned char ext[3];
    unsigned char attributes;
    unsigned char reserved[10];
    unsigned short modify_time;
    unsigned short modify_date;
    unsigned short starting_cluster;
    unsigned long file_size;
} __attribute((packed)) Fat16Entry;

void fat_read_file(FILE * in, FILE * out,
                   unsigned long fat_start, 
                   unsigned long data_start, 
                   unsigned long cluster_size, 
                   unsigned short cluster, 
                   unsigned long file_size) {
    unsigned char buffer[4096];
    size_t bytes_read, bytes_to_read,
           file_left = file_size, cluster_left = cluster_size;

    // Go to first data cluster
    fseek(in, data_start + cluster_size * (cluster-2), SEEK_SET);

    // Read until we run out of file or clusters
    while(file_left > 0 && cluster != 0xFFFF) {
        bytes_to_read = sizeof(buffer);

        // don't read past the file or cluster end
        if(bytes_to_read > file_left)
            bytes_to_read = file_left;
        if(bytes_to_read > cluster_left)
            bytes_to_read = cluster_left;

        // read data from cluster, write to file
        bytes_read = fread(buffer, 1, bytes_to_read, in);
        fwrite(buffer, 1, bytes_read, out);
        printf("Copied %d bytes\n", bytes_read);

        // decrease byte counters for current cluster and whole file
        cluster_left -= bytes_read;
        file_left -= bytes_read;

        // if we have read the whole cluster, read next cluster # from FAT
        if(cluster_left == 0) {
            fseek(in, fat_start + cluster*2, SEEK_SET);
            fread(&cluster, 2, 1, in);

            printf("End of cluster reached, next cluster %d\n", cluster);

            fseek(in, data_start + cluster_size * (cluster-2), SEEK_SET);
            cluster_left = cluster_size; // reset cluster byte counter
        }
    }
}
void  parse(char *line, char **argv)
{
  while (*line != '\0') {//until the end of the line... 
    while (*line == ' ' || *line == '\t' || *line == '\n')//...while the character in memory is any of these...
      *line++ = '\0'; //...replace it with a 0.     
    *argv++ = line;//change the given argument to the changed line.           
          while (*line != '\0' && *line != '\t' && *line != '\n' && *line != ' ')//while the line is not at one of these symbols...

        line++;//...skip the argument            
     }
  *argv = '\0'; //mark the end of the argument list        
  printf("%s\n", line);      
}

int main(int args, char *argv[]) {
    FILE *in, *out;
    in = fopen(argv[1], "rb");
    int i, j;
    unsigned long fat_start, root_start, data_start;
    PartitionTable pt[4];
    Fat16BootSector bs;
    Fat16Entry entry;
char filename[9] = "        ", file_ext[4] = "   "; // initially pad with spaces

if(args < 3) {
printf("Usage: read_file <fs_image> <FILE.EXT>\n");
return 0;
}
if((in = fopen(argv[1], "rb")) == NULL) {
printf("Filesystem image file %s not found!\n", argv[1]);
return -1;
}
    // Copy filename and extension to space-padded search strings
for(i=0; i<8 && argv[2][i] != '.' && argv[2][i] != 0; i++)
filename[i] = argv[2][i];
for(j=1; j<=3 && argv[2][i+j] != 0; j++)
file_ext[j-1] = argv[2][i+j];
printf("Opened %s, looking for [%s.%s]\n", argv[1], filename, file_ext);





    fseek(in, 0x000, SEEK_SET);
    fread(&bs, sizeof(Fat16BootSector), 1, in);

    // Calculate start offsets of FAT, root directory and data
    fat_start = ftell(in) + (bs.reserved_sectors-1) * bs.sector_size;
    root_start = fat_start + bs.fat_size_sectors * bs.number_of_fats *
        bs.sector_size;
    data_start = root_start + bs.root_dir_entries * sizeof(Fat16Entry);

    printf("FAT start at %08X, root dir at %08X, data at %08X\n", 
           fat_start, root_start, data_start);

    fseek(in, root_start, SEEK_SET);

    for(i=0; i<bs.root_dir_entries; i++) {
        fread(&entry, sizeof(entry), 1, in);
if(memcmp(entry.filename, filename, 8) == 0 && 
  memcmp(entry.ext, file_ext, 3) == 0) {
            printf("File found!\n");
            break;
        }
    }

    if(i == bs.root_dir_entries) {
        printf("File not found!");
        return -1;
    }

    out = fopen(argv[2], "wb"); // write the file contents to disk
    fat_read_file(in, out, fat_start, data_start, bs.sectors_per_cluster * bs.sector_size, entry.starting_cluster, entry.file_size);
    fclose(out);

    fclose(in);

    return 0;
}

编辑:另外,如果有人能指出我如何将文件写入脂肪的教程,那就太棒了。

0 个答案:

没有答案