· 8 years ago · Aug 27, 2018, 12:16 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 int fileSize;
262 int sector = find_sector(local[1], &fileSize);
263 printf("%d\n", sector);
264
265 if(sector != -1)
266 diskInfo.currentSector = sector;
267 else
268 printf("Directory not found\n");
269
270 printf("%d\n", diskInfo.currentSector);
271
272 free_splits(local, size);
273}
274
275void print_file(int fileSector, int fileSize)
276{
277 printf("\t Byte offset:[%d], %d bytes\n", fileSector * diskInfo.bytesPerSector, fileSize);
278 int y;
279 char x;
280 //seek to the file
281 diskInfo.dest = lseek(diskInfo.disk_id, fileSector * diskInfo.bytesPerSector, SEEK_SET);
282 //read in the file
283 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
284
285 //print the contents of the file
286 for(y = 0; y < fileSize; y++)
287 {
288 memcpy(&x, &diskInfo.psector[y], 1);
289 printf("\t\t %c\n", x);
290 }
291 printf("\n");
292}
293
294void copy_inode_info(char filename[], char * attrLongName, char *b1, char *b2, char *b3, char *b4, int * fileSize, int i){
295 memcpy(filename, &diskInfo.psector[32*i], 11);
296 memcpy(attrLongName, &diskInfo.psector[11 + 32*i], 1);
297 memcpy(b1, &diskInfo.psector[20 + 32*i], 1);
298 memcpy(b2, &diskInfo.psector[21 + 32*i], 1);
299 memcpy(b3, &diskInfo.psector[26 + 32*i], 1);
300 memcpy(b4, &diskInfo.psector[27 + 32*i], 1);
301 memcpy(fileSize, &diskInfo.psector[28 + 32*i], 4);
302
303}
304
305void ls_dir(int fileSector){
306 char filename[11];
307 char attrLongName;
308 int sectorNumber, firstClusterNumber, bOffset;
309 int i;
310 int fileSize;
311 int size = 0;
312 char b1, b2, b3, b4;
313
314 //seek to the specified directory
315 diskInfo.dest = lseek(diskInfo.disk_id, fileSector * diskInfo.bytesPerSector, SEEK_SET);
316 //read in the root directory
317 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
318
319
320 int lastSector = 0;
321
322 for(i = 1; i < 64; ++i){
323 copy_inode_info(filename, &attrLongName, &b1, &b2, &b3, &b4, &fileSize, i);
324 firstClusterNumber = (b1 << 16) | (b2 << 24) | (b4 << 8) | b3;
325 sectorNumber = ((firstClusterNumber - 2) * diskInfo.sectorsPerCluster + diskInfo.firstDataSector);
326 bOffset = sectorNumber * diskInfo.bytesPerSector;
327
328 if(filename[0] == 0x00){ break; }
329 if(filename[0] != 0xE5 && attrLongName != LONG_DIRECTORY){
330 lastSector = sectorNumber;
331 printf("%s [%d]\n", filename, sectorNumber);
332 printf("\t Sector Number(b10): [%d] \n", sectorNumber);
333 printf("\t FAT Sector Loc: [%d] , Offset: [%d] \n", sectorNumber, bOffset);
334 }
335 }
336}
337int next_cluster(const int firstClusterNumber){
338 //Is data continued onto another cluster?
339 int thisFatSectorNumber = diskInfo.reservedSectorCount + ((firstClusterNumber * 4) / diskInfo.bytesPerSector);
340 int thisFatEntryOffset = ((firstClusterNumber * 4) % diskInfo.bytesPerSector);
341 //Check to see if next cluster exists
342 int nextCluster;
343 diskInfo.dest = lseek(diskInfo.disk_id, thisFatSectorNumber * diskInfo.bytesPerSector, SEEK_SET);
344 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
345 memcpy(&nextCluster, &diskInfo.psector[thisFatEntryOffset], 4);
346 //printf("cluster number: %d\n", nextCluster);
347 if(nextCluster == 0xFFFFFFF)
348 return -1;
349 return nextCluster;
350}
351
352int find_sector(const char * finding, int * fileSize){
353 char filename[11] = "";
354 char attrLongName;
355 int i;
356 char b1, b2, b3, b4;
357 size_t ret;
358
359 int sectorNumber, firstClusterNumber, bOffset;
360
361 int size = 0;
362 diskInfo.dest = lseek(diskInfo.disk_id, diskInfo.currentSector*diskInfo.bytesPerSector, SEEK_SET);
363 //read in the root directory
364 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
365
366 int sectorOfFolder = -1;
367
368 for(i = 1; i < 64; ++i){
369 copy_inode_info(filename, &attrLongName, &b1, &b2, &b3, &b4, fileSize, i);
370 firstClusterNumber = (b1 << 16) | (b2 << 24) | (b4 << 8) | b3;
371 sectorNumber = ((firstClusterNumber - 2) * diskInfo.sectorsPerCluster + diskInfo.firstDataSector);
372 bOffset = sectorNumber * diskInfo.bytesPerSector;
373
374 if(filename[0] == 0x00){ break; }
375 if(filename[0] != 0xE5 && attrLongName != LONG_DIRECTORY){
376 if(attrLongName == SUB_DIRECTORY){
377 if(strncmp(filename, finding, strlen(finding)) == 0){
378 return sectorNumber;
379 }
380 }else{
381 if(strncmp(filename, finding, strlen(finding)) == 0){
382 return sectorNumber;
383 }
384 }
385
386 }
387 }
388 return -1;
389}
390
391int calcFirstCluster(int cluster){
392 return ((cluster - diskInfo.firstDataSector)/diskInfo.sectorsPerCluster) + 2;
393}
394
395void ls(const char *cmd){
396 int i;
397 char b1, b2, b3, b4;
398 size_t ret;
399
400 int size = 0;
401 int fileSize;
402 char **local = split_string(cmd, " ", &size);
403
404 /*if(size != 2){
405 printf("You need to provide a filename\n");
406 free_splits(local, size);
407 return;
408 }*/
409
410 diskInfo.dest = lseek(diskInfo.disk_id, diskInfo.currentSector*diskInfo.bytesPerSector, SEEK_SET);
411 //read in the root directory
412 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
413 int sectorOfFolder;
414 if(size != 2){
415 sectorOfFolder = diskInfo.currentSector;
416 }else{
417 sectorOfFolder = find_sector(local[1], &fileSize);
418 }
419
420#ifdef DEBUG
421 printf("[Scanning: %d %d] \n", sectorOfFolder, next_cluster(calcFirstCluster(sectorOfFolder)));
422#endif
423
424 ls_dir(sectorOfFolder);
425 int x = next_cluster(calcFirstCluster(sectorOfFolder));
426 printf("%d %X\n", x, x);
427 while(x != -1){
428 printf("%d %X\n", x, x);
429 x = next_cluster(x);
430 }
431
432
433 free_splits(local, size);
434}
435
436void mk_dir(const char *cmd){
437 int size = 0;
438 char **local = split_string(cmd, " ", &size);
439
440 if(size != 2){
441 printf("You need to provide a filename\n");
442 free_splits(local, size);
443 return;
444 }
445
446 free_splits(local, size);
447}
448
449void rm_dir(const char *cmd){
450 int size = 0;
451 char **local = split_string(cmd, " ", &size);
452
453 if(size != 2){
454 printf("You need to provide a filename\n");
455 free_splits(local, size);
456 return;
457 }
458
459 free_splits(local, size);
460}
461
462
463void size_file(const char *cmd){
464 int size = 0, i;
465 char **local = split_string(cmd, " ", &size);
466 char * file;
467 if(size < 2){
468 printf("You need to provide a filename\n");
469 free_splits(local, size);
470 return;
471 }
472 if(size > 2){
473 int totalSize = 0;
474 for(i = 1; i < size; ++i){
475 printf("%s\n", local[i]);
476 totalSize += strlen(local[i]);
477 }
478 file = malloc(totalSize*sizeof(char));
479 int counter;
480 for(counter = 0; counter <= totalSize; ++counter){
481 file[counter] = cmd[strlen(local[0]) + counter + 1];
482 }
483 }else{
484 file = local[1];
485 }
486
487
488 int fileSize = 0;
489 int sector = find_sector(file, &fileSize);
490 printf("Filesize of %s is %d\n", file, fileSize);
491
492 if(size > 2)
493 free(file);
494
495 free_splits(local, size);
496}
497
498void srm_file(const char *cmd){
499 int size = 0;
500 char **local = split_string(cmd, " ", &size);
501
502 if(size != 2){
503 printf("You need to provide a filename\n");
504 free_splits(local, size);
505 return;
506 }
507
508 free_splits(local, size);
509}
510
511void fsinfo(){
512 printf("Bytes Per Sector: %hd\n", diskInfo.bytesPerSector);
513 printf("Sectors Per Cluster: %d\n", diskInfo.sectorsPerCluster);
514 printf("Total sectors: %d\n", diskInfo.totalSectors);
515 printf("Number of FATs: %d\n", diskInfo.numFATs);
516 printf("Sectors per FAT: %d\n", diskInfo.sectorsPerTrack);
517 printf("Number of free sectors: NEEDED\n");
518
519 //printf("Size of FATs: %d\n", sizeFAT);
520 //printf("Root Cluster: %d\n", rootCluster);
521 //printf("Root Location: %d\n", rootLoc);
522
523
524 return;
525}
526
527int main(int argc, char *argv[]){
528 char cmd[80] = "";
529 prompt(argv[1]);
530 get_input(cmd);
531 diskInfo.disk_id = open(argv[1], O_RDWR);
532 update_disk_struct(diskInfo.disk_id);
533 diskInfo.currentSector = diskInfo.rootLoc;
534
535 while(1){
536 // needs to be open and closed after each command or wierd stuff happens
537 if(strncmp(cmd, fsinfo_cmd, 6) == 0){
538 fsinfo();
539 }else if(strncmp(cmd, open_cmd, 5) == 0){
540 open_file(cmd);
541 }else if(strncmp(cmd, close_cmd, 6) == 0){
542 close_file(cmd);
543 }else if(strncmp(cmd, create_cmd, 7) == 0){
544 create_file(cmd);
545 }else if(strncmp(cmd, read_cmd, 5) == 0){
546 read_file(cmd);
547 }else if(strncmp(cmd, write_cmd, 6) == 0){
548 write_file(cmd);
549 }else if(strncmp(cmd, rm_cmd, 3) == 0){
550 rm_file(cmd);
551 }else if(strncmp(cmd, cd_cmd, 3) == 0){
552 cd(cmd);
553 }else if(strncmp(cmd, ls_cmd, 3) == 0){
554 ls(cmd);
555 }else if(strncmp(cmd, mkdir_cmd, 6) == 0){
556 mk_dir(cmd);
557 }else if(strncmp(cmd, rmdir_cmd, 6) == 0){
558 rm_dir(cmd);
559 }else if(strncmp(cmd, size_cmd, 5) == 0){
560 size_file(cmd);
561 }else if(strncmp(cmd, srm_cmd, 4) == 0){
562 srm_file(cmd);
563 }else if(strncmp(cmd, "exit", 4) == 0){
564 close(diskInfo.disk_id);
565 exit(0);
566 }
567
568 update_disk_struct(diskInfo.disk_id);
569 prompt(argv[1]);
570 get_input(cmd);
571
572 }
573
574 return 0;
575}
576
577
578
579
580void update_disk_struct(){
581 //open file
582
583 //seek to boot sector
584 lseek(diskInfo.disk_id, 0, SEEK_SET);
585 //read in boot sector bytes
586 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
587
588 //copy over information from the appropriate offsets
589 memcpy(diskInfo.name,&diskInfo.psector[3],8);
590 memcpy(&diskInfo.bytesPerSector, &diskInfo.psector[11], 2);
591 memcpy(&diskInfo.sectorsPerCluster, &diskInfo.psector[13], 1);
592 memcpy(&diskInfo.reservedSectorCount, &diskInfo.psector[14], 2);
593 memcpy(&diskInfo.numFATs, &diskInfo.psector[16], 1);
594 memcpy(&diskInfo.sizeFAT, &diskInfo.psector[36], 4);
595 memcpy(&diskInfo.rootCluster, &diskInfo.psector[44], 4);
596
597 //calculate the location of the root directory
598 diskInfo.firstDataSector = diskInfo.reservedSectorCount + ((int)diskInfo.numFATs * diskInfo.sizeFAT);
599 diskInfo.rootLoc = ((diskInfo.rootCluster - 2) * (int)diskInfo.sectorsPerCluster) + diskInfo.firstDataSector;
600
601 return;
602}