· 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 diskInfo.dest = lseek(diskInfo.disk_id, diskInfo.currentSector*diskInfo.bytesPerSector, SEEK_SET);
362 //read in the root directory
363 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
364
365 int sectorOfFolder = -1;
366
367 for(i = 1; i < 64; ++i){
368 copy_inode_info(filename, &attrLongName, &b1, &b2, &b3, &b4, fileSize, i);
369 firstClusterNumber = (b1 << 16) | (b2 << 24) | (b4 << 8) | b3;
370 sectorNumber = ((firstClusterNumber - 2) * diskInfo.sectorsPerCluster + diskInfo.firstDataSector);
371 bOffset = sectorNumber * diskInfo.bytesPerSector;
372
373 if(filename[0] == 0x00){ break; }
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 }else{
380 if(strncmp(filename, finding, strlen(finding)) == 0){
381 return sectorNumber;
382 }
383 }
384
385 }
386 }
387 return -1;
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 int fileSize;
401 char **local = split_string(cmd, " ", &size);
402
403 /*if(size != 2){
404 printf("You need to provide a filename\n");
405 free_splits(local, size);
406 return;
407 }*/
408
409 diskInfo.dest = lseek(diskInfo.disk_id, diskInfo.currentSector*diskInfo.bytesPerSector, SEEK_SET);
410 //read in the root directory
411 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
412 int sectorOfFolder;
413 if(size != 2){
414 sectorOfFolder = diskInfo.currentSector;
415 }else{
416 sectorOfFolder = find_sector(local[1], &fileSize);
417 }
418
419#ifdef DEBUG
420 printf("[Scanning: %d %d] \n", sectorOfFolder, next_cluster(calcFirstCluster(sectorOfFolder)));
421#endif
422
423 ls_dir(sectorOfFolder);
424 int x = next_cluster(calcFirstCluster(sectorOfFolder));
425 printf("%d %X\n", x, x);
426 while(x != -1){
427 printf("%d %X\n", x, x);
428 x = next_cluster(x);
429 }
430
431
432 free_splits(local, size);
433}
434
435void mk_dir(const char *cmd){
436 int size = 0;
437 char **local = split_string(cmd, " ", &size);
438
439 if(size != 2){
440 printf("You need to provide a filename\n");
441 free_splits(local, size);
442 return;
443 }
444
445 free_splits(local, size);
446}
447
448void rm_dir(const char *cmd){
449 int size = 0;
450 char **local = split_string(cmd, " ", &size);
451
452 if(size != 2){
453 printf("You need to provide a filename\n");
454 free_splits(local, size);
455 return;
456 }
457
458 free_splits(local, size);
459}
460
461
462void size_file(const char *cmd){
463 int size = 0, i;
464 char **local = split_string(cmd, " ", &size);
465 char * file;
466 if(size < 2){
467 printf("You need to provide a filename\n");
468 free_splits(local, size);
469 return;
470 }
471 if(size > 2){
472 int totalSize = 0;
473 for(i = 1; i < size; ++i){
474 printf("%s\n", local[i]);
475 totalSize += strlen(local[i]);
476 }
477 file = malloc(totalSize*sizeof(char));
478 int counter;
479 for(counter = 0; counter <= totalSize; ++counter){
480 file[counter] = cmd[strlen(local[0]) + counter + 1];
481 }
482 }else{
483 file = local[1];
484 }
485
486
487 int fileSize = 0;
488 int sector = find_sector(file, &fileSize);
489 printf("Filesize of %s is %d\n", file, fileSize);
490
491 if(size > 2)
492 free(file);
493
494 free_splits(local, size);
495}
496
497void srm_file(const char *cmd){
498 int size = 0;
499 char **local = split_string(cmd, " ", &size);
500
501 if(size != 2){
502 printf("You need to provide a filename\n");
503 free_splits(local, size);
504 return;
505 }
506
507 free_splits(local, size);
508}
509
510void fsinfo(){
511 printf("Bytes Per Sector: %hd\n", diskInfo.bytesPerSector);
512 printf("Sectors Per Cluster: %d\n", diskInfo.sectorsPerCluster);
513 printf("Total sectors: %d\n", diskInfo.totalSectors);
514 printf("Number of FATs: %d\n", diskInfo.numFATs);
515 printf("Sectors per FAT: %d\n", diskInfo.sectorsPerTrack);
516 printf("Number of free sectors: NEEDED\n");
517
518 //printf("Size of FATs: %d\n", sizeFAT);
519 //printf("Root Cluster: %d\n", rootCluster);
520 //printf("Root Location: %d\n", rootLoc);
521
522
523 return;
524}
525
526int main(int argc, char *argv[]){
527 char cmd[80] = "";
528 prompt(argv[1]);
529 get_input(cmd);
530 diskInfo.disk_id = open(argv[1], O_RDWR);
531 update_disk_struct(diskInfo.disk_id);
532 diskInfo.currentSector = diskInfo.rootLoc;
533
534 while(1){
535 // needs to be open and closed after each command or wierd stuff happens
536 if(strncmp(cmd, fsinfo_cmd, 6) == 0){
537 fsinfo();
538 }else if(strncmp(cmd, open_cmd, 5) == 0){
539 open_file(cmd);
540 }else if(strncmp(cmd, close_cmd, 6) == 0){
541 close_file(cmd);
542 }else if(strncmp(cmd, create_cmd, 7) == 0){
543 create_file(cmd);
544 }else if(strncmp(cmd, read_cmd, 5) == 0){
545 read_file(cmd);
546 }else if(strncmp(cmd, write_cmd, 6) == 0){
547 write_file(cmd);
548 }else if(strncmp(cmd, rm_cmd, 3) == 0){
549 rm_file(cmd);
550 }else if(strncmp(cmd, cd_cmd, 3) == 0){
551 cd(cmd);
552 }else if(strncmp(cmd, ls_cmd, 3) == 0){
553 ls(cmd);
554 }else if(strncmp(cmd, mkdir_cmd, 6) == 0){
555 mk_dir(cmd);
556 }else if(strncmp(cmd, rmdir_cmd, 6) == 0){
557 rm_dir(cmd);
558 }else if(strncmp(cmd, size_cmd, 5) == 0){
559 size_file(cmd);
560 }else if(strncmp(cmd, srm_cmd, 4) == 0){
561 srm_file(cmd);
562 }else if(strncmp(cmd, "exit", 4) == 0){
563 close(diskInfo.disk_id);
564 exit(0);
565 }
566
567 update_disk_struct(diskInfo.disk_id);
568 prompt(argv[1]);
569 get_input(cmd);
570
571 }
572
573 return 0;
574}
575
576
577
578
579void update_disk_struct(){
580 //open file
581
582 //seek to boot sector
583 lseek(diskInfo.disk_id, 0, SEEK_SET);
584 //read in boot sector bytes
585 read(diskInfo.disk_id, diskInfo.psector, LCD_SSIZE);
586
587 //copy over information from the appropriate offsets
588 memcpy(diskInfo.name,&diskInfo.psector[3],8);
589 memcpy(&diskInfo.bytesPerSector, &diskInfo.psector[11], 2);
590 memcpy(&diskInfo.sectorsPerCluster, &diskInfo.psector[13], 1);
591 memcpy(&diskInfo.reservedSectorCount, &diskInfo.psector[14], 2);
592 memcpy(&diskInfo.numFATs, &diskInfo.psector[16], 1);
593 memcpy(&diskInfo.sizeFAT, &diskInfo.psector[36], 4);
594 memcpy(&diskInfo.rootCluster, &diskInfo.psector[44], 4);
595
596 //calculate the location of the root directory
597 diskInfo.firstDataSector = diskInfo.reservedSectorCount + ((int)diskInfo.numFATs * diskInfo.sizeFAT);
598 diskInfo.rootLoc = ((diskInfo.rootCluster - 2) * (int)diskInfo.sectorsPerCluster) + diskInfo.firstDataSector;
599
600 return;
601}