-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathformat.c
More file actions
331 lines (285 loc) · 13.3 KB
/
Copy pathformat.c
File metadata and controls
331 lines (285 loc) · 13.3 KB
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <assert.h>
#include "filesystem.h"
#define DEFAULT_SIZE_MB 1
#define MB_TO_BYTES(mb) ((mb) * 1024 * 1024)
#define BLOCK_SIZE 512
#define N_DBLOCKS 10
#define N_IBLOCKS 4
#define INODES_PER_BLOCK (BLOCK_SIZE / sizeof(struct inode))
#define FILETYPE 0
#define DIRECTORYTYPE 1
#define SUPERUSER 0
void create_disk_image(const char* file_name, int size_mb) {
FILE* file = fopen(file_name, "r+");
if (!file) {
perror("Failed to open file");
exit(EXIT_FAILURE);
}
// Initialize superblock
struct Superblock sb = {BLOCK_SIZE,0, 8, 6, 11};
fwrite(&sb, sizeof(sb), 1, file);
// Initialize inode-1 to store the user info
struct inode user_inode = {-1, FILETYPE, RWx, -1, 1, SUPERUSER, 3*sizeof(struct User), time(NULL), {0}, {0}, 0};
if (fwrite(&user_inode, sizeof(user_inode), 1, file) != 1) {
printf("Error when writing userinode.\n");
}
if (fseek(file, (sb.inode_offset + 1)*BLOCK_SIZE, SEEK_SET) != 0) {
perror("Error positioning file pointer to data region");
fclose(file);
exit(EXIT_FAILURE);
}
// Initialize the root directory inode
struct inode root_inode = {0,DIRECTORYTYPE, RWx, -1, 1, SUPERUSER, 4 * sizeof(struct dirent), time(NULL), {1}, {0}, 0};
if (fwrite(&root_inode, sizeof(root_inode), 1, file) != 1) {
printf("Error when writing rootinode.\n");
}
// Initialize a file inode with fake content
char file_content[] = "Hello, this is some text in the file.\n";
int file_size = strlen(file_content);
struct inode file_inode = {1,FILETYPE, RWx, -1, 1, SUPERUSER, file_size, time(NULL), {2}, {0}, 0};
if (fwrite(&file_inode, sizeof(file_inode), 1, file) != 1) {
printf("Error when writing fileinode.\n");
}
struct inode layerone_inode = {2,DIRECTORYTYPE, NONE, 0, 1, SUPERUSER, 3*sizeof(struct dirent), time(NULL), {3}, {0}, 0};
if (fwrite(&layerone_inode, sizeof(layerone_inode), 1, file) != 1) {
printf("Error when writing layeroneinode.\n");
}
struct inode layertwo_inode = {3,DIRECTORYTYPE, NONE, 2, 1, SUPERUSER, 4*sizeof(struct dirent), time(NULL), {4}, {0}, 0};
if (fwrite(&layertwo_inode, sizeof(layertwo_inode), 1, file) != 1) {
printf("Error when writing layertwoinode.\n");
}
char path[] = "layerone/layertwo/more.txt";
int path_size = sizeof(path);
struct inode layertwo_path_inode = {4,FILETYPE, RWx, 3, 1, SUPERUSER, path_size, time(NULL), {5}, {0}, 0};
if (fwrite(&layertwo_path_inode, sizeof(layertwo_path_inode), 1, file) != 1) {
printf("Error when writing layertwo_path_inode.\n");
}
char more[] = "Once upon a time in a quiet village beside a whispering river, there lived an old baker known \
for his extraordinary pastries. Every morning, the baker would wake up before dawn to prepare his dough \
and mix spices brought from distant lands. One peculiar morning, a mischievous wind carried away his \
recipe book through the open window. Determined not to disappoint his loyal customers, the baker decided \
to recreate his recipes from memory. With a sprinkle of creativity and a dash of hope, he concocted a \
new pastry. This delightful creation was unlike any other and brought more joy and curious visitors to \
the village than ever before. The baker not only found his lost recipes later that day tucked away in \
his garden by the playful wind, but he also discovered the true magic ingredient: a pinch of unexpected adventure.\
Once upon a time in a quiet village beside a whispering river, there lived an old baker known \
for his extraordinary pastries. Every morning, the baker would wake up before dawn to prepare his dough \
and mix spices brought from distant lands. One peculiar morning, a mischievous wind carried away his \
recipe book through the open window. Determined not to disappoint his loyal customers, the baker decided \
to recreate his recipes from memory. With a sprinkle of creativity and a dash of hope, he concocted a \
new pastry. This delightful creation was unlike any other and brought more joy and curious visitors to \
the village than ever before. The baker not only found his lost recipes later that day tucked away in \
his garden by the playful wind, but he also discovered the true magic ingredient: a pinch of unexpected adventure.\
Once upon a time in a quiet village beside a whispering river, there lived an old baker known \
for his extraordinary pastries. Every morning, the baker would wake up before dawn to prepare his dough \
and mix spices brought from distant lands. One peculiar morning, a mischievous wind carried away his \
recipe book through the open window. Determined not to disappoint his loyal customers, the baker decided \
to recreate his recipes from memory. With a sprinkle of creativity and a dash of hope, he concocted a \
new pastry. This delightful creation was unlike any other and brought more joy and curious visitors to \
the village than ever before.\n";
int more_size = sizeof(more);
struct inode layertwo_more_inode = {5,FILETYPE, RWx, 3, 1, SUPERUSER, more_size, time(NULL), {6, 7,8,9,10}, {0}, 0};
if (fwrite(&layertwo_more_inode, sizeof(layertwo_more_inode), 1, file) != 1) {
printf("Error when writing layertwo_more_inode.\n");
}
// Initialize remaining inodes and link them as free inodes
struct inode empty_inode = {0, 0, 0, -1, 0, 0, 0, 0, {0}, {0}, 0};
for (int i = 6; i < 8 * INODES_PER_BLOCK; ++i) {
empty_inode.index = i;
if (i < 8 * INODES_PER_BLOCK - 1) {
empty_inode.parent = i + 1;
} else {
empty_inode.parent = -1;
}
if (fwrite(&empty_inode, sizeof(struct inode), 1, file) != 1) {
printf("Error when writing free inode.\n");
}
}
int data_block_offset = (sb.data_offset + 1) * BLOCK_SIZE;
if (fseek(file, data_block_offset, SEEK_SET) != 0) {
perror("Error positioning file pointer to data region");
fclose(file);
exit(EXIT_FAILURE);
}
struct User superUser = {
.username = "chen",
.uid = 0,
.password = "09080223"
};
struct User normalUser = {
.username = "dianna",
.uid = 1,
.password = "12345678"
};
struct User endUser = {
.username = "null",
.uid = -1,
.password = "null"
};
fwrite(&superUser, sizeof(struct User), 1, file);
fwrite(&normalUser, sizeof(struct User), 1, file);
fwrite(&endUser, sizeof(struct User), 1, file);
if (fseek(file, data_block_offset + BLOCK_SIZE, SEEK_SET) != 0) {
perror("Error positioning file pointer to data region");
fclose(file);
exit(EXIT_FAILURE);
}
// Write root directory data block with directory entries
struct dirent root_entries[4] = {{0, 1, -1, "."}, {0, 1, -1, ".."}, {1, 0, -1, "file.txt"},{2, 1, -1, "layerone"}};
fwrite(root_entries, sizeof(root_entries), 1, file);
// Write file content block
char block[BLOCK_SIZE] = {0};
memcpy(block, file_content, file_size);
if (fseek(file, data_block_offset + 2*BLOCK_SIZE, SEEK_SET) != 0) {
perror("Error positioning file pointer to data region");
fclose(file);
exit(EXIT_FAILURE);
}
fwrite(block, BLOCK_SIZE, 1, file);
// Write layerone directory data block with directory entries
if (fseek(file, data_block_offset + 3*BLOCK_SIZE, SEEK_SET) != 0) {
perror("Error positioning file pointer to data region");
fclose(file);
exit(EXIT_FAILURE);
}
struct dirent layerone_entries[3] = {{2, DIRECTORYTYPE, -1, "."}, {0, DIRECTORYTYPE, -1, ".."}, {3, DIRECTORYTYPE, -1, "layertwo"}};
fwrite(layerone_entries, sizeof(layerone_entries), 1, file);
// Write layertwo directory data block with directory entries
if (fseek(file, data_block_offset + 4*BLOCK_SIZE, SEEK_SET) != 0) {
perror("Error positioning file pointer to data region");
fclose(file);
exit(EXIT_FAILURE);
}
struct dirent layertwo_entries[4] = {{3, DIRECTORYTYPE, -1, "."}, {2, DIRECTORYTYPE, -1, ".."}, {5, FILETYPE, -1, "more.txt"}, {4, FILETYPE, -1, "path.txt"}};
fwrite(layertwo_entries, sizeof(layertwo_entries), 1, file);
// Write layertwo path file content block
//write path.txt
if (fseek(file, data_block_offset + 5*BLOCK_SIZE, SEEK_SET) != 0) {
perror("Error positioning file pointer to data region");
fclose(file);
exit(EXIT_FAILURE);
}
memcpy(block, path, path_size);
fwrite(block, BLOCK_SIZE, 1, file);
// Write layertwo more file content block
if (fseek(file, data_block_offset + 6*BLOCK_SIZE, SEEK_SET) != 0) {
perror("Error positioning file pointer to data region");
fclose(file);
exit(EXIT_FAILURE);
}
fwrite(more, more_size, 1, file);
// Initialize free data blocks
if (fseek(file, data_block_offset + sb.free_block* BLOCK_SIZE, SEEK_SET) != 0) {
perror("Error positioning file pointer to data region");
fclose(file);
exit(EXIT_FAILURE);
}
int total_blocks = size_mb * 1024 * 1024 / BLOCK_SIZE;
int free_blocks = total_blocks - (sb.data_offset + sb.free_block); // Adjust for root and file block
for (int i = 0; i < free_blocks; ++i) {
int next_free_block;
if (i < free_blocks - 1) {
next_free_block = i + sb.free_block + 1;
} else {
next_free_block = -1;
}
memset(block, 0, BLOCK_SIZE); // Clear the block
memcpy(block, &next_free_block, sizeof(int));
fwrite(block, BLOCK_SIZE, 1, file);
}
fclose(file);
printf("Disk image '%s' created with size %dMB, %d free blocks initialized.\n", file_name, size_mb, free_blocks);
}
void print_disk_contents(const char* file_name) {
FILE *file = fopen(file_name, "rb");
if (!file) {
perror("Failed to open file");
exit(EXIT_FAILURE);
}
struct Superblock sb;
if (fread(&sb, sizeof(sb), 1, file) != 1) {
perror("Failed to read superblock");
fclose(file);
exit(EXIT_FAILURE);
}
printf("Superblock:\n");
printf(" Size: %d\n Inode Offset: %d\n Data Offset: %d\n Free Inode: %d\n Free Block: %d\n",
sb.size, sb.inode_offset, sb.data_offset, sb.free_inode, sb.free_block);
struct inode in;
printf("User inode:\n");
if (fread(&in, sizeof(struct inode), 1, file) != 1) {
printf(" reading user inode failed.\n");
}
printf("Inode %d: Type %d, Parent:%d, uid: %d, Permissions %d, Size %d, Mtime %d\n",
in.index, in.type, in.parent, in.uid, in.permissions, in.size, in.mtime);
printf("\nInodes:\n");
fseek(file, (sb.inode_offset+1) * BLOCK_SIZE, SEEK_SET);
for (int i = 0; i < 8 * INODES_PER_BLOCK; ++i) {
if (fread(&in, sizeof(struct inode), 1, file) != 1 || in.mtime == 0) {
printf("Finish.\n");
break; // Stop if we fail to read an inode
}
printf("Inode %d: Type %d, Parent:%d, uid: %d, Permissions %d, Size %d, Mtime %d\n",
in.index, in.type, in.parent, in.uid, in.permissions, in.size, in.mtime);
}
// Assuming directory entries are located right at the data offset
printf("\nDirectory Entries:\n");
fseek(file, (sb.data_offset+1) * BLOCK_SIZE, SEEK_SET);
struct dirent de;
struct User user;
if (fread(&user, sizeof(struct User), 1, file) == 1) {
printf("User: username: %s, userid: %d, password: %s\n", user.username, user.uid, user.password);
}
if (fread(&user, sizeof(struct User), 1, file) == 1) {
printf("User: username: %s, userid: %d, password: %s\n", user.username, user.uid, user.password);
}
fseek(file, (sb.data_offset+2) * BLOCK_SIZE, SEEK_SET);
while (fread(&de, sizeof(struct dirent), 1, file) == 1) {
if (strlen(de.name) > 0) { // Only print valid entries
printf(" Entry: %s, Inode: %d, Type: %d\n", de.name, de.inode, de.type);
}
}
// print freeblocks
printf("\nFree Blocks:\n");
int start = (sb.data_offset + sb.free_block + 1) * BLOCK_SIZE;
fseek(file, start, SEEK_SET);
int free_block;
int count =0;
while (fread(&free_block, sizeof(int), 1, file) == 1 && count < 10) {
printf(" Free Block: block %d, next free block is %d\n", count + sb.free_block, free_block);
start = start + BLOCK_SIZE;
fseek(file, start, SEEK_SET);
count ++;
}
printf("Test the more file\n");
fseek(file, (sb.data_offset + 8) * BLOCK_SIZE, SEEK_SET);
char more[3000];
fread(more, 3000, 1, file);
printf("more: %s\n", more);
fclose(file);
}
int main(int argc, char* argv[]) {
if (argc < 2) {
fprintf(stderr, "Usage: %s <filename> [-s size_mb]\n", argv[0]);
exit(EXIT_FAILURE);
}
int size_mb = DEFAULT_SIZE_MB;
char* file_name = argv[1];
int option;
while ((option = getopt(argc, argv, "s:")) != -1) {
if (option == 's') {
size_mb = atoi(optarg);
} else {
fprintf(stderr, "Usage: %s <filename> [-s size_mb]\n", argv[0]);
exit(EXIT_FAILURE);
}
}
create_disk_image(file_name, size_mb);
//print_disk_contents(file_name);
return 0;
}