1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
#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;
}
|