· 8 years ago · Aug 27, 2018, 11:42 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#define MAX_OPEN_FILES 4
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 open_files {
46 char *filename;
47 char *mode;
48 int sector;
49 int size;
50};
51struct open_files openFiles[MAX_OPEN_FILES];
52struct disk_info diskInfo;
53
54void strip_line(char* cmd){
55 cmd[strlen(cmd) - 1] = '\0';
56}
57
58char * whoami(){
59 char *u = getenv("USER");
60 return u;
61}
62
63size_t trimwhitespace(char *out, size_t len, const char *str)
64{
65 if(len == 0)
66 return 0;
67
68 const char *end;
69 size_t out_size;
70
71 // Trim leading space
72 while(isspace(*str)) str++;
73
74 if(*str == 0) // All spaces?
75 {
76 *out = 0;
77 return 1;
78 }
79
80 // Trim trailing space
81 end = str + strlen(str) - 1;
82 while(end > str && isspace(*end)) end--;
83 end++;
84
85 // Set output size to minimum of trimmed string length and buffer size minus 1
86 out_size = (end - str) < len-1 ? (end - str) : len-1;
87
88 // Copy trimmed string and add null terminator
89 memcpy(out, str, out_size);
90 out[out_size] = 0;
91
92 return out_size;
93}
94
95
96void update_disk_struct();
97
98char **split_string(const char* str, char *sep, int *size){
99 char *path = strdup(str);
100 // in the case of a really long string
101 // this may waste space, but wont cause leaks
102 char **split_args = malloc(strlen(path)*sizeof(char*));
103
104 char *save;
105 int x = 0;
106 char *token;
107 for(token = strtok_r(path, sep, &save); token != NULL;
108 token = strtok_r(NULL, sep, &save)){
109 split_args[x] = strdup(token);
110 x++;
111 }
112
113 *size = x;
114
115 free(path);
116 return split_args;
117}
118
119void free_splits(char **split_array, int count){
120 int i;
121 for (i = 0; i < count; i++) {
122 free(split_array[i]);
123 }
124
125 free(split_array);
126}
127
128void prompt(char *img){
129 printf("\n%s(%s)> ", whoami(), img);
130 //fflush(stdout);
131 return;
132}
133
134
135void get_input(char cmd[]) {
136 char str[80];
137 fgets(str, 80, stdin);
138 strip_line(str);
139 strcpy(cmd, str);
140 return;
141}
142
143int is_file_open(char* filename){
144 int i;
145 for(i = 0; i < MAX_OPEN_FILES; i++){
146 if(openFiles[i].filename != NULL){
147 if(strncmp(openFiles[i].filename, filename, strlen(filename)) == 0){
148 return 1;
149 }
150 }
151 }
152 return 0;
153}
154
155int file_size(char *filename){
156 int i;
157 for(i = 0; i < MAX_OPEN_FILES; i++){
158 if(openFiles[i].filename != NULL){
159 if(strncmp(openFiles[i].filename, filename, strlen(filename)) == 0){
160 return openFiles[i].size;
161 }
162 }
163 }
164 return -1;
165}
166
167int is_file_readable(char *filename){
168 int i;
169 for(i = 0; i < MAX_OPEN_FILES; i++){
170 if(openFiles[i].filename != NULL){
171 if(strncmp(openFiles[i].filename, filename, strlen(filename)) == 0){
172 if(strncmp(openFiles[i].mode, "w", 1) == 0){
173 return 0;
174 }else{
175 return 1;
176 }
177 }
178 }
179 }
180 return 0;
181
182}
183
184// TODO:
185// - Fail:
186// if filename cannot be found
187// if filename is already open
188// if filename is not a file (directory)
189void open_file(const char *cmd){
190 int size = 0;
191 char **local = split_string(cmd, " ", &size);
192
193 if(size != 3){
194 printf("You must enter a mode and a filename\n");
195 free_splits(local, size);
196 return;
197 }
198
199 char *mode = local[2];
200
201 if( strcmp(mode, "r") != 0 && strcmp(mode, "w") != 0 && strcmp(mode, "rw") != 0 && strcmp(mode, "wr") != 0 )
202 printf("Invalid mode.\n");
203
204 char *file = local[1];
205 int i;
206 if(!is_file_open(file)){
207 for(i = 0; i < MAX_OPEN_FILES; i++){
208 if(openFiles[i].filename == NULL){
209#ifdef DEBUG
210 printf("%d is empty\n", i);
211#endif
212 openFiles[i].filename = file;
213 openFiles[i].mode = mode;
214 openFiles[i].sector = find_sector(file, &openFiles[i].size);
215 printf("%s has been opened for %s\n", file, mode);
216#ifdef DEBUG
217 printf("sector: %d | size: %d \n", openFiles[i].sector, openFiles[i].size);
218#endif
219 break;
220 }
221 }
222 }else{
223 printf("File %s is already open.\n", file);
224 }
225
226 free_splits(local, size);
227}
228
229// TODO:
230// - Fail:
231// if filename cannot be found in the open file table
232void close_file(const char *cmd){
233 int size = 0;
234 char **local = split_string(cmd, " ", &size);
235 if(size != 2){
236 printf("You need to provide a filename\n");
237 free_splits(local, size);
238 return;
239 }
240 int i;
241 int wasClosed = 0;
242 for(i = 0; i < MAX_OPEN_FILES; i++){
243 if(openFiles[i].filename != NULL){
244 if(strncmp(openFiles[i].filename, local[1], strlen(local[1])) == 0){
245 wasClosed = 1;
246 printf("%s has been closed.\n", local[1]);
247 openFiles[i].filename = NULL;
248 openFiles[i].mode = NULL;
249 openFiles[i].size = 0;
250 openFiles[i].sector = 0;
251 }
252 }
253 }
254 if(wasClosed == 0)
255 printf("%s cannot be found in the open file table\n", local[1]);
256
257
258 ///char *file = local[1];
259
260 free_splits(local, size);
261
262}
263
264// TODO:
265// - Fail:
266// if file already exists
267void create_file(const char *cmd){
268 int size = 0;
269 char **local = split_string(cmd, " ", &size);
270
271 if(size != 2){
272 printf("You need to provide a filename\n");
273 free_splits(local, size);
274 return;
275 }
276
277 //char *file = local[1];
278
279 free_splits(local, size);
280}
281
282// TODO:
283// - Fail:
284// if filename is not int he open filetable
285// if startpos is greater than the size of the file
286// if filename is not open for reading
287// if filename is not a file (directory)
288void read_file(const char *cmd){
289 int size = 0, i;
290 char *file;
291 char **local = split_string(cmd, " ", &size);
292
293 if(size != 4){
294 printf("You need to provide a filename, start position and end position\n");
295 free_splits(local, size);
296 return;
297 }
298
299 if(!is_file_open(local[1]) || !is_file_readable(local[1])){
300 printf("File is not opened for reading\n");
301 free_splits(local, size);
302 return;
303 }
304 /*
305 if(size > 2){
306 int totalSize = 0;
307 for(i = 1; i < size; ++i){
308 printf("%s\n", local[i]);
309 totalSize += strlen(local[i]);
310 }
311 file = malloc(totalSize*sizeof(char));
312 int counter;
313 for(counter = 0; counter <= totalSize; ++counter){
314 file[counter] = cmd[strlen(local[0]) + counter + 1];
315 }
316 }else{
317 file = local[1];
318 }*/
319 file = local[1];
320
321 int startPos = atoi(local[2]);
322 int numBytes = atoi(local[3]);
323 int filesize = file_size(file);
324 if(filesize == -1 || startPos > filesize){
325 printf("Start position is greater than the size of the file\n");
326 free_splits(local, size);
327 return;
328 }
329
330 printf("Start: %d | numBytes: %d \n", startPos, numBytes);
331
332
333 int fileSize = 0;
334 int fileSector = find_sector(file, &fileSize);
335#ifdef DEBUG
336 printf("\t Byte offset:[%d], %d bytes\n", fileSector * diskInfo.bytesPerSector, fileSize);
337#endif
338 int y;
339 char x;
340 //seek to the file
341 diskInfo.dest = lseek(diskInfo.disk_id, fileSector * diskInfo.bytesPerSector, SEEK_SET);
342 //read in the file
343 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
344
345 //print the contents of the file
346 for(y = startPos; y < numBytes; y++)
347 {
348 memcpy(&x, &diskInfo.psector[y], 1);
349 printf("%c", x);
350 }
351 printf("\n");
352
353
354 free_splits(local, size);
355}
356
357// TODO:
358// - Fail:
359// if filename is not in the open file table
360// if filename is not open for writing
361// if filename is not a file (directory)
362void write_file(const char *cmd){
363 int size = 0;
364 char **local = split_string(cmd, " ", &size);
365
366 if(size != 2){
367 printf("You need to provide a filename\n");
368 free_splits(local, size);
369 return;
370 }
371
372 free_splits(local, size);
373}
374
375// TODO:
376// - Fail:
377// if filename is not found in the pwd
378// if filename is not a file (directory)
379void rm_file(const char *cmd){
380 int size = 0;
381 char **local = split_string(cmd, " ", &size);
382
383 if(size != 2){
384 printf("You need to provide a filename\n");
385 free_splits(local, size);
386 return;
387 }
388
389 free_splits(local, size);
390}
391
392void cd(const char *cmd){
393 int size = 0;
394 char **local = split_string(cmd, " ", &size);
395
396 if(size != 2){
397 printf("You need to provide a filename\n");
398 free_splits(local, size);
399 return;
400 }
401 int fileSize;
402 int sector = find_sector(local[1], &fileSize);
403 if(sector == (diskInfo.rootLoc-2))
404 sector+=2;
405 printf("%d\n", sector);
406
407 if(sector != -1)
408 diskInfo.currentSector = sector;
409 else
410 printf("Directory not found\n");
411
412 printf("%d\n", diskInfo.currentSector);
413
414 free_splits(local, size);
415}
416
417
418void copy_inode_info(char filename[], char * attrLongName, char *b1, char *b2, char *b3, char *b4, int * fileSize, int i){
419 memcpy(filename, &diskInfo.psector[32*i], 11);
420 memcpy(attrLongName, &diskInfo.psector[11 + 32*i], 1);
421 memcpy(b1, &diskInfo.psector[20 + 32*i], 1);
422 memcpy(b2, &diskInfo.psector[21 + 32*i], 1);
423 memcpy(b3, &diskInfo.psector[26 + 32*i], 1);
424 memcpy(b4, &diskInfo.psector[27 + 32*i], 1);
425 memcpy(fileSize, &diskInfo.psector[28 + 32*i], 4);
426
427}
428
429void ls_dir(int fileSector){
430 char filename[11];
431 char attrLongName;
432 int sectorNumber, firstClusterNumber, bOffset;
433 int i;
434 int fileSize;
435 int size = 0;
436 char b1, b2, b3, b4;
437
438 //seek to the specified directory
439 diskInfo.dest = lseek(diskInfo.disk_id, fileSector * diskInfo.bytesPerSector, SEEK_SET);
440 //read in the root directory
441 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
442
443
444 int lastSector = 0;
445
446 for(i = 1; i < 64; ++i){
447 copy_inode_info(filename, &attrLongName, &b1, &b2, &b3, &b4, &fileSize, i);
448 firstClusterNumber = (b1 << 16) | (b2 << 24) | (b4 << 8) | b3;
449 sectorNumber = ((firstClusterNumber - 2) * diskInfo.sectorsPerCluster + diskInfo.firstDataSector);
450 bOffset = sectorNumber * diskInfo.bytesPerSector;
451
452 if(filename[0] == 0x00){ break; }
453 if(filename[0] != 0xE5 && attrLongName != LONG_DIRECTORY && strncmp(filename, "mkdosfs", 7) != 0){
454 lastSector = sectorNumber;
455 printf("%s\t", filename, sectorNumber);
456#ifdef DEBUG
457 printf("\t Sector Number(b10): [%d] \n", sectorNumber);
458 printf("\t FAT Sector Loc: [%d] , Offset: [%d] \n", sectorNumber, bOffset);
459#endif
460 }
461 }
462}
463int next_cluster(const int firstClusterNumber){
464 //Is data continued onto another cluster?
465 int thisFatSectorNumber = diskInfo.reservedSectorCount + ((firstClusterNumber * 4) / diskInfo.bytesPerSector);
466 int thisFatEntryOffset = ((firstClusterNumber * 4) % diskInfo.bytesPerSector);
467 //Check to see if next cluster exists
468 int nextCluster;
469 diskInfo.dest = lseek(diskInfo.disk_id, thisFatSectorNumber * diskInfo.bytesPerSector, SEEK_SET);
470 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
471 memcpy(&nextCluster, &diskInfo.psector[thisFatEntryOffset], 4);
472 //printf("cluster number: %d\n", nextCluster);
473 if(nextCluster == 0xFFFFFFF || nextCluster == 0xFFFFFF8)
474 return -1;
475 return nextCluster;
476}
477
478int find_sector(const char * finding, int * fileSize){
479 char filename[11] = "";
480 char attrLongName;
481 int i;
482 char b1, b2, b3, b4;
483 size_t ret;
484
485 int sectorNumber, firstClusterNumber, bOffset;
486
487 diskInfo.dest = lseek(diskInfo.disk_id, diskInfo.currentSector*diskInfo.bytesPerSector, SEEK_SET);
488 //read in the root directory
489 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
490
491 int sectorOfFolder = -1;
492
493 for(i = 1; i < 64; ++i){
494 copy_inode_info(filename, &attrLongName, &b1, &b2, &b3, &b4, fileSize, i);
495 firstClusterNumber = (b1 << 16) | (b2 << 24) | (b4 << 8) | b3;
496 sectorNumber = ((firstClusterNumber - 2) * diskInfo.sectorsPerCluster + diskInfo.firstDataSector);
497 bOffset = sectorNumber * diskInfo.bytesPerSector;
498
499 if(filename[0] == 0x00){ break; }
500 if(filename[0] != 0xE5 && attrLongName != LONG_DIRECTORY){
501 if(attrLongName == SUB_DIRECTORY){
502 if(strncmp(filename, finding, strlen(finding)) == 0){
503 return sectorNumber;
504 }
505 }else{
506 if(strncmp(filename, finding, strlen(finding)) == 0){
507 return sectorNumber;
508 }
509 }
510
511 }
512 }
513 return -1;
514}
515
516int calcFirstCluster(int cluster){
517 return ((cluster - diskInfo.firstDataSector)/diskInfo.sectorsPerCluster) + 2;
518}
519
520void ls(const char *cmd){
521 int i;
522 char b1, b2, b3, b4;
523 size_t ret;
524
525 int size = 0;
526 int fileSize;
527 char **local = split_string(cmd, " ", &size);
528
529 /*if(size != 2){
530 printf("You need to provide a filename\n");
531 free_splits(local, size);
532 return;
533 }*/
534
535 diskInfo.dest = lseek(diskInfo.disk_id, diskInfo.currentSector*diskInfo.bytesPerSector, SEEK_SET);
536 //read in the root directory
537 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
538 int sectorOfFolder;
539 if(size != 2){
540 sectorOfFolder = diskInfo.currentSector;
541 }else{
542 sectorOfFolder = find_sector(local[1], &fileSize);
543 }
544
545#ifdef DEBUG
546 printf("[Scanning: %d %d] \n", sectorOfFolder, next_cluster(calcFirstCluster(sectorOfFolder)));
547#endif
548
549 ls_dir(sectorOfFolder);
550 int x = next_cluster(calcFirstCluster(sectorOfFolder));
551#ifdef DEBUG
552 printf("%d %X\n", x, x);
553#endif
554 while(x != -1){
555 //printf("%d %X\n", x, x);
556 ls_dir(x+2048);
557 x = next_cluster(x);
558 }
559
560
561 free_splits(local, size);
562}
563
564void mk_dir(const char *cmd){
565 int size = 0;
566 char **local = split_string(cmd, " ", &size);
567
568 if(size != 2){
569 printf("You need to provide a filename\n");
570 free_splits(local, size);
571 return;
572 }
573
574 free_splits(local, size);
575}
576
577void rm_dir(const char *cmd){
578 int size = 0;
579 char **local = split_string(cmd, " ", &size);
580
581 if(size != 2){
582 printf("You need to provide a filename\n");
583 free_splits(local, size);
584 return;
585 }
586
587 free_splits(local, size);
588}
589
590
591void size_file(const char *cmd){
592 int size = 0, i;
593 char **local = split_string(cmd, " ", &size);
594 char * file;
595 if(size < 2){
596 printf("You need to provide a filename\n");
597 free_splits(local, size);
598 return;
599 }
600 if(size > 2){
601 int totalSize = 0;
602 for(i = 1; i < size; ++i){
603 printf("%s\n", local[i]);
604 totalSize += strlen(local[i]);
605 }
606 file = malloc(totalSize*sizeof(char));
607 int counter;
608 for(counter = 0; counter <= totalSize; ++counter){
609 file[counter] = cmd[strlen(local[0]) + counter + 1];
610 }
611 }else{
612 file = local[1];
613 }
614
615
616 int fileSize = 0;
617 int sector = find_sector(file, &fileSize);
618 printf("Filesize of %s is %d\n", file, fileSize);
619
620 if(size > 2)
621 free(file);
622
623 free_splits(local, size);
624}
625
626void srm_file(const char *cmd){
627 int size = 0;
628 char **local = split_string(cmd, " ", &size);
629
630 if(size != 2){
631 printf("You need to provide a filename\n");
632 free_splits(local, size);
633 return;
634 }
635
636 free_splits(local, size);
637}
638
639void fsinfo(){
640 printf("Bytes Per Sector: %hd\n", diskInfo.bytesPerSector);
641 printf("Sectors Per Cluster: %d\n", diskInfo.sectorsPerCluster);
642 printf("Total sectors: %d\n", diskInfo.totalSectors);
643 printf("Number of FATs: %d\n", diskInfo.numFATs);
644 printf("Sectors per FAT: %d\n", diskInfo.sectorsPerTrack);
645 printf("Number of free sectors: NEEDED\n");
646
647 //printf("Size of FATs: %d\n", sizeFAT);
648 //printf("Root Cluster: %d\n", rootCluster);
649 //printf("Root Location: %d\n", rootLoc);
650
651
652 return;
653}
654
655int main(int argc, char *argv[]){
656 char cmd[80] = "";
657 prompt(argv[1]);
658 get_input(cmd);
659 diskInfo.disk_id = open(argv[1], O_RDWR);
660 update_disk_struct(diskInfo.disk_id);
661 diskInfo.currentSector = diskInfo.rootLoc;
662
663 while(1){
664 // needs to be open and closed after each command or wierd stuff happens
665 if(strncmp(cmd, fsinfo_cmd, 6) == 0){
666 fsinfo();
667 }else if(strncmp(cmd, open_cmd, 5) == 0){
668 open_file(cmd);
669 }else if(strncmp(cmd, close_cmd, 6) == 0){
670 close_file(cmd);
671 }else if(strncmp(cmd, create_cmd, 7) == 0){
672 create_file(cmd);
673 }else if(strncmp(cmd, read_cmd, 5) == 0){
674 read_file(cmd);
675 }else if(strncmp(cmd, write_cmd, 6) == 0){
676 write_file(cmd);
677 }else if(strncmp(cmd, rm_cmd, 3) == 0){
678 rm_file(cmd);
679 }else if(strncmp(cmd, cd_cmd, 3) == 0){
680 cd(cmd);
681 }else if(strncmp(cmd, ls_cmd, 2) == 0){
682 ls(cmd);
683 }else if(strncmp(cmd, mkdir_cmd, 6) == 0){
684 mk_dir(cmd);
685 }else if(strncmp(cmd, rmdir_cmd, 6) == 0){
686 rm_dir(cmd);
687 }else if(strncmp(cmd, size_cmd, 5) == 0){
688 size_file(cmd);
689 }else if(strncmp(cmd, srm_cmd, 4) == 0){
690 srm_file(cmd);
691 }else if(strncmp(cmd, "exit", 4) == 0){
692 close(diskInfo.disk_id);
693 exit(0);
694 }
695
696 update_disk_struct(diskInfo.disk_id);
697 prompt(argv[1]);
698 get_input(cmd);
699
700 }
701
702 return 0;
703}
704
705
706
707
708void update_disk_struct(){
709 //open file
710
711 //seek to boot sector
712 lseek(diskInfo.disk_id, 0, SEEK_SET);
713 //read in boot sector bytes
714 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
715
716 //copy over information from the appropriate offsets
717 memcpy(diskInfo.name,&diskInfo.psector[3],8);
718 memcpy(&diskInfo.bytesPerSector, &diskInfo.psector[11], 2);
719 memcpy(&diskInfo.sectorsPerCluster, &diskInfo.psector[13], 1);
720 memcpy(&diskInfo.reservedSectorCount, &diskInfo.psector[14], 2);
721 memcpy(&diskInfo.numFATs, &diskInfo.psector[16], 1);
722 memcpy(&diskInfo.sizeFAT, &diskInfo.psector[36], 4);
723 memcpy(&diskInfo.rootCluster, &diskInfo.psector[44], 4);
724
725 //calculate the location of the root directory
726 diskInfo.firstDataSector = diskInfo.reservedSectorCount + ((int)diskInfo.numFATs * diskInfo.sizeFAT);
727 diskInfo.rootLoc = ((diskInfo.rootCluster - 2) * (int)diskInfo.sectorsPerCluster) + diskInfo.firstDataSector;
728
729 return;
730}