· 8 years ago · Aug 27, 2018, 12:08 AM
1#include <stdio.h>
2#include <stdlib.h>
3#include <fcntl.h>
4#include <string.h>
5#include <unistd.h>
6#include <signal.h>
7#include <unistd.h>
8#include <ctype.h>
9
10#define LCD_SSIZE 512
11#define LONG_DIRECTORY 0x0F
12#define SUB_DIRECTORY 0x10
13
14#define DEBUG 1
15
16#define LOG printf("[LOG]%s:%d\n",__FILE__,__LINE__);
17
18
19const char *fsinfo_cmd = "fsinfo";
20const char *open_cmd = "open ";
21const char *close_cmd = "close ";
22const char *create_cmd = "create ";
23const char *read_cmd = "read ";
24const char *write_cmd = "write ";
25const char *rm_cmd = "rm ";
26const char *cd_cmd = "cd ";
27const char *ls_cmd = "ls ";
28const char *mkdir_cmd = "mkdir ";
29const char *rmdir_cmd = "rmdir ";
30const char *size_cmd = "size ";
31const char *srm_cmd = "srm ";
32
33struct disk_info {
34 int disk_id;
35 int dest, len, did, sizeFAT, rootLoc, rootCluster, firstDataSector, i;
36 unsigned short bytesPerSector, reservedSectorCount, sectorsPerTrack;
37 unsigned int totalSectors;
38 char psector[LCD_SSIZE];
39 char name[8];
40 char filename[11];
41 char sectorsPerCluster, numFATs, attrLongName;
42 int currentSector;
43};
44
45struct disk_info diskInfo;
46void strip_line(char* cmd){
47 cmd[strlen(cmd) - 1] = '\0';
48}
49
50char * whoami(){
51 char *u = getenv("USER");
52 return u;
53}
54
55size_t trimwhitespace(char *out, size_t len, const char *str)
56{
57 if(len == 0)
58 return 0;
59
60 const char *end;
61 size_t out_size;
62
63 // Trim leading space
64 while(isspace(*str)) str++;
65
66 if(*str == 0) // All spaces?
67 {
68 *out = 0;
69 return 1;
70 }
71
72 // Trim trailing space
73 end = str + strlen(str) - 1;
74 while(end > str && isspace(*end)) end--;
75 end++;
76
77 // Set output size to minimum of trimmed string length and buffer size minus 1
78 out_size = (end - str) < len-1 ? (end - str) : len-1;
79
80 // Copy trimmed string and add null terminator
81 memcpy(out, str, out_size);
82 out[out_size] = 0;
83
84 return out_size;
85}
86
87
88void update_disk_struct();
89
90char **split_string(const char* str, char *sep, int *size){
91 char *path = strdup(str);
92 // in the case of a really long string
93 // this may waste space, but wont cause leaks
94 char **split_args = malloc(strlen(path)*sizeof(char*));
95
96 char *save;
97 int x = 0;
98 char *token;
99 for(token = strtok_r(path, sep, &save); token != NULL;
100 token = strtok_r(NULL, sep, &save)){
101 split_args[x] = strdup(token);
102 x++;
103 }
104
105 *size = x;
106
107 free(path);
108 return split_args;
109}
110
111void free_splits(char **split_array, int count){
112 int i;
113 for (i = 0; i < count; i++) {
114 free(split_array[i]);
115 }
116
117 free(split_array);
118}
119
120void prompt(char *img){
121 printf("\n%s(%s)> ", whoami(), img);
122 //fflush(stdout);
123 return;
124}
125
126
127void get_input(char cmd[]) {
128 char str[80];
129 fgets(str, 80, stdin);
130 strip_line(str);
131 strcpy(cmd, str);
132 return;
133}
134
135// TODO:
136// - Fail:
137// if filename cannot be found
138// if filename is already open
139// if filename is not a file (directory)
140void open_file(const char *cmd){
141 int size = 0;
142 char **local = split_string(cmd, " ", &size);
143
144 if(size != 3){
145 printf("You must enter a mode and a filename\n");
146 free_splits(local, size);
147 return;
148 }
149
150 char *mode = local[1];
151
152 if( strcmp(mode, "r") != 0 && strcmp(mode, "w") != 0 && strcmp(mode, "rw") != 0 && strcmp(mode, "wr") != 0 )
153 printf("Invalid mode.\n");
154
155 char *file = local[2];
156 printf("[DEBUG] mode: %s\n", mode);
157 printf("[DEBUG] file: %s\n", file);
158 free_splits(local, size);
159}
160
161// TODO:
162// - Fail:
163// if filename cannot be found in the open file table
164void close_file(const char *cmd){
165 int size = 0;
166 char **local = split_string(cmd, " ", &size);
167 if(size != 2){
168 printf("You need to provide a filename\n");
169 free_splits(local, size);
170 return;
171 }
172
173 ///char *file = local[1];
174
175 free_splits(local, size);
176
177}
178
179// TODO:
180// - Fail:
181// if file already exists
182void create_file(const char *cmd){
183 int size = 0;
184 char **local = split_string(cmd, " ", &size);
185
186 if(size != 2){
187 printf("You need to provide a filename\n");
188 free_splits(local, size);
189 return;
190 }
191
192 //char *file = local[1];
193
194 free_splits(local, size);
195}
196
197// TODO:
198// - Fail:
199// if filename is not int he open filetable
200// if startpos is greater than the size of the file
201// if filename is not open for reading
202// if filename is not a file (directory)
203void read_file(const char *cmd){
204 int size = 0;
205 char **local = split_string(cmd, " ", &size);
206
207 if(size != 2){
208 printf("You need to provide a filename\n");
209 free_splits(local, size);
210 return;
211 }
212
213
214 free_splits(local, size);
215}
216
217// TODO:
218// - Fail:
219// if filename is not in the open file table
220// if filename is not open for writing
221// if filename is not a file (directory)
222void write_file(const char *cmd){
223 int size = 0;
224 char **local = split_string(cmd, " ", &size);
225
226 if(size != 2){
227 printf("You need to provide a filename\n");
228 free_splits(local, size);
229 return;
230 }
231
232 free_splits(local, size);
233}
234
235// TODO:
236// - Fail:
237// if filename is not found in the pwd
238// if filename is not a file (directory)
239void rm_file(const char *cmd){
240 int size = 0;
241 char **local = split_string(cmd, " ", &size);
242
243 if(size != 2){
244 printf("You need to provide a filename\n");
245 free_splits(local, size);
246 return;
247 }
248
249 free_splits(local, size);
250}
251
252void cd(const char *cmd){
253 int size = 0;
254 char **local = split_string(cmd, " ", &size);
255
256 if(size != 2){
257 printf("You need to provide a filename\n");
258 free_splits(local, size);
259 return;
260 }
261
262 free_splits(local, size);
263}
264
265void print_file(int fileSector, int fileSize)
266{
267 printf("\t Byte offset:[%d], %d bytes\n", fileSector * diskInfo.bytesPerSector, fileSize);
268 int y;
269 char x;
270 //seek to the file
271 diskInfo.dest = lseek(diskInfo.disk_id, fileSector * diskInfo.bytesPerSector, SEEK_SET);
272 //read in the file
273 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
274
275 //print the contents of the file
276 for(y = 0; y < fileSize; y++)
277 {
278 memcpy(&x, &diskInfo.psector[y], 1);
279 printf("\t\t %c\n", x);
280 }
281 printf("\n");
282}
283
284
285
286void ls_dir(int fileSector){
287 char filename[11];
288 char attrLongName;
289 int sectorNumber, firstClusterNumber, bOffset;
290 int i;
291 int fileSize;
292 int size = 0;
293 char b1, b2, b3, b4;
294
295 //seek to the specified directory
296 diskInfo.dest = lseek(diskInfo.disk_id, fileSector * diskInfo.bytesPerSector, SEEK_SET);
297 //read in the root directory
298 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
299
300
301 int lastSector = 0;
302
303 for(i = 1; i < 64; ++i){
304 memcpy(&filename, &diskInfo.psector[32*i], 11);
305 memcpy(&attrLongName, &diskInfo.psector[11 + 32*i], 1);
306 memcpy(&b1, &diskInfo.psector[20 + 32*i], 1);
307 memcpy(&b2, &diskInfo.psector[21 + 32*i], 1);
308 memcpy(&b3, &diskInfo.psector[26 + 32*i], 1);
309 memcpy(&b4, &diskInfo.psector[27 + 32*i], 1);
310 memcpy(&fileSize, &diskInfo.psector[28 + 32*i], 4);
311 firstClusterNumber = (b1 << 16) | (b2 << 24) | (b4 << 8) | b3;
312 sectorNumber = ((firstClusterNumber - 2) * diskInfo.sectorsPerCluster + diskInfo.firstDataSector);
313 bOffset = sectorNumber * diskInfo.bytesPerSector;
314
315 if(filename[0] == 0x00){
316 break;
317 }
318 if(filename[0] != 0xE5 && attrLongName != LONG_DIRECTORY && sectorNumber != 133120){
319 lastSector = sectorNumber;
320 printf("%s [%d]\n", filename, sectorNumber);
321 printf("\t Sector Number(b10): [%d] \n", sectorNumber);
322 printf("\t FAT Sector Loc: [%d] , Offset: [%d] \n", sectorNumber, bOffset);
323 }
324
325 }
326
327}
328int next_cluster(const int firstClusterNumber){
329 //Is data continued onto another cluster?
330 int thisFatSectorNumber = diskInfo.reservedSectorCount + ((firstClusterNumber * 4) / diskInfo.bytesPerSector);
331 int thisFatEntryOffset = ((firstClusterNumber * 4) % diskInfo.bytesPerSector);
332 //Check to see if next cluster exists
333 int nextCluster;
334 diskInfo.dest = lseek(diskInfo.disk_id, thisFatSectorNumber * diskInfo.bytesPerSector, SEEK_SET);
335 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
336 memcpy(&nextCluster, &diskInfo.psector[thisFatEntryOffset], 4);
337 printf("cluster number: %d\n", nextCluster);
338 return nextCluster;
339}
340
341int find_sector(const char * finding){
342 char filename[11] = "";
343 char attrLongName;
344 int i;
345 char b1, b2, b3, b4;
346 size_t ret;
347
348 int sectorNumber, firstClusterNumber, bOffset;
349 int fileSize;
350
351 int size = 0;
352 diskInfo.dest = lseek(diskInfo.disk_id, diskInfo.currentSector*diskInfo.bytesPerSector, SEEK_SET);
353 //read in the root directory
354 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
355
356 int sectorOfFolder = -1;
357
358 for(i = 1; i < 64; ++i){
359 memcpy(&filename, &diskInfo.psector[32*i], 11);
360 memcpy(&attrLongName, &diskInfo.psector[11 + 32*i], 1);
361 memcpy(&b1, &diskInfo.psector[20 + 32*i], 1);
362 memcpy(&b2, &diskInfo.psector[21 + 32*i], 1);
363 memcpy(&b3, &diskInfo.psector[26 + 32*i], 1);
364 memcpy(&b4, &diskInfo.psector[27 + 32*i], 1);
365 memcpy(&fileSize, &diskInfo.psector[28 + 32*i], 4);
366 firstClusterNumber = (b1 << 16) | (b2 << 24) | (b4 << 8) | b3;
367 sectorNumber = ((firstClusterNumber - 2) * diskInfo.sectorsPerCluster + diskInfo.firstDataSector);
368 bOffset = sectorNumber * diskInfo.bytesPerSector;
369
370
371 if(filename[0] == 0x00){
372 break;
373 }
374 if(filename[0] != 0xE5 && attrLongName != LONG_DIRECTORY){
375 if(attrLongName == SUB_DIRECTORY){
376 if(strncmp(filename, finding, strlen(finding)) == 0){
377 return sectorNumber;
378 }
379
380 }
381 }
382 }
383
384 return -1;
385
386
387
388}
389
390int calcFirstCluster(int cluster){
391 return ((cluster - diskInfo.firstDataSector)/diskInfo.sectorsPerCluster) + 2;
392}
393
394void ls(const char *cmd){
395 int i;
396 char b1, b2, b3, b4;
397 size_t ret;
398
399 int size = 0;
400 char **local = split_string(cmd, " ", &size);
401
402 /*if(size != 2){
403 printf("You need to provide a filename\n");
404 free_splits(local, size);
405 return;
406 }*/
407
408 diskInfo.dest = lseek(diskInfo.disk_id, diskInfo.currentSector*diskInfo.bytesPerSector, SEEK_SET);
409 //read in the root directory
410 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
411 int sectorOfFolder;
412 if(size != 2){
413 sectorOfFolder = diskInfo.rootLoc;
414 }else{
415 sectorOfFolder = find_sector(local[1]);
416 }
417
418#ifdef DEBUG
419 printf("[Scanning: %d %d] \n", sectorOfFolder, next_cluster(sectorOfFolder));
420
421#endif
422
423 ls_dir(sectorOfFolder);
424 int x = next_cluster(calcFirstCluster(sectorOfFolder));
425 while(x != 268435455){
426 printf("%d\n", x);
427 x = next_cluster(x);
428 }
429
430
431 free_splits(local, size);
432}
433
434void mk_dir(const char *cmd){
435 int size = 0;
436 char **local = split_string(cmd, " ", &size);
437
438 if(size != 2){
439 printf("You need to provide a filename\n");
440 free_splits(local, size);
441 return;
442 }
443
444 free_splits(local, size);
445}
446
447void rm_dir(const char *cmd){
448 int size = 0;
449 char **local = split_string(cmd, " ", &size);
450
451 if(size != 2){
452 printf("You need to provide a filename\n");
453 free_splits(local, size);
454 return;
455 }
456
457 free_splits(local, size);
458}
459
460
461void size_file(const char *cmd){
462 int size = 0;
463 char **local = split_string(cmd, " ", &size);
464
465 if(size != 2){
466 printf("You need to provide a filename\n");
467 free_splits(local, size);
468 return;
469 }
470
471 free_splits(local, size);
472}
473
474void srm_file(const char *cmd){
475 int size = 0;
476 char **local = split_string(cmd, " ", &size);
477
478 if(size != 2){
479 printf("You need to provide a filename\n");
480 free_splits(local, size);
481 return;
482 }
483
484 free_splits(local, size);
485}
486
487
488int main(int argc, char *argv[]){
489 char cmd[80] = "";
490 prompt(argv[1]);
491 get_input(cmd);
492 diskInfo.disk_id = open(argv[1], O_RDWR);
493 update_disk_struct(diskInfo.disk_id);
494 diskInfo.currentSector = diskInfo.rootLoc;
495
496 while(1){
497 // needs to be open and closed after each command or wierd stuff happens
498 if(strncmp(cmd, fsinfo_cmd, 6) == 0){
499 fsinfo();
500 }else if(strncmp(cmd, open_cmd, 5) == 0){
501 open_file(cmd);
502 }else if(strncmp(cmd, close_cmd, 6) == 0){
503 close_file(cmd);
504 }else if(strncmp(cmd, create_cmd, 7) == 0){
505 create_file(cmd);
506 }else if(strncmp(cmd, read_cmd, 5) == 0){
507 read_file(cmd);
508 }else if(strncmp(cmd, write_cmd, 6) == 0){
509 write_file(cmd);
510 }else if(strncmp(cmd, rm_cmd, 3) == 0){
511 rm_file(cmd);
512 }else if(strncmp(cmd, cd_cmd, 3) == 0){
513 ls(cmd);
514 }else if(strncmp(cmd, ls_cmd, 3) == 0){
515 ls(cmd);
516 }else if(strncmp(cmd, mkdir_cmd, 6) == 0){
517 mk_dir(cmd);
518 }else if(strncmp(cmd, rmdir_cmd, 6) == 0){
519 rm_dir(cmd);
520 }else if(strncmp(cmd, size_cmd, 5) == 0){
521 size_file(cmd);
522 }else if(strncmp(cmd, srm_cmd, 4) == 0){
523 srm_file(cmd);
524 }else if(strncmp(cmd, "exit", 4) == 0){
525 close(diskInfo.disk_id);
526 exit(0);
527 }
528
529 update_disk_struct(diskInfo.disk_id);
530 prompt(argv[1]);
531 get_input(cmd);
532
533 }
534
535 return 0;
536}
537
538
539void fsinfo(){
540 printf("Bytes Per Sector: %hd\n", diskInfo.bytesPerSector);
541 printf("Sectors Per Cluster: %d\n", diskInfo.sectorsPerCluster);
542 printf("Total sectors: %d\n", diskInfo.totalSectors);
543 printf("Number of FATs: %d\n", diskInfo.numFATs);
544 printf("Sectors per FAT: %d\n", diskInfo.sectorsPerTrack);
545 printf("Number of free sectors: NEEDED\n");
546
547 //printf("Size of FATs: %d\n", sizeFAT);
548 //printf("Root Cluster: %d\n", rootCluster);
549 //printf("Root Location: %d\n", rootLoc);
550
551
552 return;
553}
554
555void update_disk_struct(){
556 //open file
557
558 //seek to boot sector
559 lseek(diskInfo.disk_id, 0, SEEK_SET);
560 //read in boot sector bytes
561 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
562
563 //copy over information from the appropriate offsets
564 memcpy(diskInfo.name,&diskInfo.psector[3],8);
565 memcpy(&diskInfo.bytesPerSector, &diskInfo.psector[11], 2);
566 memcpy(&diskInfo.sectorsPerCluster, &diskInfo.psector[13], 1);
567 memcpy(&diskInfo.reservedSectorCount, &diskInfo.psector[14], 2);
568 memcpy(&diskInfo.numFATs, &diskInfo.psector[16], 1);
569 memcpy(&diskInfo.sizeFAT, &diskInfo.psector[36], 4);
570 memcpy(&diskInfo.rootCluster, &diskInfo.psector[44], 4);
571
572 //calculate the location of the root directory
573 diskInfo.firstDataSector = diskInfo.reservedSectorCount + ((int)diskInfo.numFATs * diskInfo.sizeFAT);
574 diskInfo.rootLoc = ((diskInfo.rootCluster - 2) * (int)diskInfo.sectorsPerCluster) + diskInfo.firstDataSector;
575
576 return;
577}