-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmkfs_ffs.c
122 lines (107 loc) · 3.95 KB
/
mkfs_ffs.c
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
/*
mkfs.ffs binary implementation for Linux.
*/
#include <dirent.h>
#include <fuzzy/fs/ffs.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#define FILEENTRY_LOCATION(file_id) \
(FS_FFS_FIRST_BLOCK_SIZE + FS_FFS_FILEENTRY_SIZE * (file_id))
void write_first_block(FILE *out) {
union FFSMetaData block;
strncpy(block.content.signature, FS_FFS_SIGNATURE,
sizeof(block.content.signature));
rewind(out);
fwrite(block.bytes, 1, sizeof(block.bytes), out);
}
void write_file(int file_id, FILE *outfile, int *outfile_nextdata_block,
const char *filename, FILE *srcfile, int is_executable) {
fseek(srcfile, 0L, SEEK_END);
int file_size = ftell(srcfile);
rewind(srcfile);
union FFSFileEntry entry;
strncpy(entry.content.filename, filename, sizeof(entry.content.filename));
entry.content.filesize = file_size;
entry.content.start_block_id = (*outfile_nextdata_block);
entry.content.flags = 0;
if (is_executable) {
entry.content.flags |= FFS_FILE_FLAG_EXECUTABLE;
}
// Write file entry
fseek(outfile, FILEENTRY_LOCATION(file_id), SEEK_SET);
fwrite(entry.bytes, 1, sizeof(entry.bytes), outfile);
// Write file content
char buffer[512];
size_t bytes_read;
printf("Writting context at %d\n", ((*outfile_nextdata_block)));
fseek(outfile, (*outfile_nextdata_block) * FS_BLOCK_SIZE, SEEK_SET);
(*outfile_nextdata_block) +=
(file_size + FS_BLOCK_SIZE - 1) / FS_BLOCK_SIZE;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), srcfile)) > 0) {
fwrite(buffer, 1, bytes_read, outfile);
}
printf("Added '%s' file\n", filename);
}
void write_nofile(int file_id, FILE *out) {
union FFSFileEntry entry;
entry.content.start_block_id = 0;
fseek(out, FILEENTRY_LOCATION(file_id), SEEK_SET);
fwrite(entry.bytes, 1, sizeof(entry.bytes), out);
}
int create_partition(char *src_dir, char *out_filepath) {
printf("dir:%s partition: %s\n", src_dir, out_filepath);
FILE *src = opendir(src_dir);
FILE *out = fopen(out_filepath, "wb");
if (!out) {
fprintf(stderr, "can't open output file.");
return 1;
}
if (!src) {
fprintf(stderr, "can't open src directory.");
return 2;
}
// header
write_first_block(out);
// interate over files and write them in partition.
struct dirent *de;
int file_id = 0;
int outfile_nextdata_block = FS_FFS_BLOCK_DATA_START;
char buffer_filename[4096];
while ((de = readdir(src)) != NULL) {
strncpy(buffer_filename, src_dir, sizeof(buffer_filename));
strncat(buffer_filename, "/", sizeof(buffer_filename));
strncat(buffer_filename, de->d_name, sizeof(buffer_filename));
if (file_id >= FS_FFS_FILEENTRY_COUNT) {
fprintf("reached max supported files, ignoring file '%s'",
buffer_filename);
continue;
}
struct stat file_stat;
stat(buffer_filename, &file_stat);
if (!S_ISREG(file_stat.st_mode)) {
fprintf("skipping non-regular file '%s': %d", buffer_filename,
file_stat.st_mode);
continue;
}
int is_executable = file_stat.st_mode & S_IXUSR;
FILE *file_src = fopen(buffer_filename, "rb");
write_file(file_id++, out, &outfile_nextdata_block, de->d_name,
file_src, is_executable);
fclose(file_src);
}
while (file_id < FS_FFS_FILEENTRY_COUNT) {
write_nofile(file_id++, out);
}
fclose(out);
return 0;
}
int main(int argc, const char **argv) {
if (argc != 3) {
printf("Usage: %s <base_dir> <out_file>\n", argv[0]);
return 0;
}
char *src_dir = argv[1];
char *out_filepath = argv[2];
return create_partition(src_dir, out_filepath);
}