· 8 years ago · Apr 22, 2018, 09:14 PM
1/*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
4
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7*/
8
9#define FUSE_USE_VERSION 26
10
11#include <fuse.h>
12#include <stdio.h>
13#include <string.h>
14#include <errno.h>
15#include <fcntl.h>
16
17//size of a disk block
18#define BLOCK_SIZE 512
19
20static const char DOT[] = ".";
21static const char DISK[] = ".disk";
22static const char MODE[] = "r+b";
23static const char EMPTY = '\0';
24
25//we'll use 8.3 filenames
26#define MAX_FILENAME 8
27#define MAX_EXTENSION 3
28
29//How many files can there be in one directory?
30#define MAX_FILES_IN_DIR (BLOCK_SIZE - sizeof(int)) / ((MAX_FILENAME + 1) + (MAX_EXTENSION + 1) + sizeof(size_t) + sizeof(long))
31
32#define MAX_FAT_SIZE (BLOCK_SIZE / sizeof(short))
33//The attribute packed means to not align these things
34struct cs1550_directory_entry
35{
36 int nFiles; //How many files are in this directory.
37 //Needs to be less than MAX_FILES_IN_DIR
38
39 struct cs1550_file_directory
40 {
41 char fname[MAX_FILENAME + 1]; //filename (plus space for nul)
42 char fext[MAX_EXTENSION + 1]; //extension (plus space for nul)
43 size_t fsize; //file size
44 long nStartBlock; //where the first block is on disk
45 } __attribute__((packed)) files[MAX_FILES_IN_DIR]; //There is an array of these
46
47 //This is some space to get this to be exactly the size of the disk block.
48 //Don't use it for anything.
49 char padding[BLOCK_SIZE - MAX_FILES_IN_DIR * sizeof(struct cs1550_file_directory) - sizeof(int)];
50} ;
51
52typedef struct cs1550_root_directory cs1550_root_directory;
53
54struct fat_table {
55 short db[MAX_FAT_SIZE];
56};
57
58#define MAX_DIRS_IN_ROOT (BLOCK_SIZE - sizeof(int)) / ((MAX_FILENAME + 1) + sizeof(long))
59
60struct cs1550_root_directory
61{
62 int nDirectories; //How many subdirectories are in the root
63 //Needs to be less than MAX_DIRS_IN_ROOT
64 struct cs1550_directory
65 {
66 char dname[MAX_FILENAME + 1]; //directory name (plus space for nul)
67 long nStartBlock; //where the directory block is on disk
68 } __attribute__((packed)) directories[MAX_DIRS_IN_ROOT]; //There is an array of these
69
70 //This is some space to get this to be exactly the size of the disk block.
71 //Don't use it for anything.
72 char padding[BLOCK_SIZE - MAX_DIRS_IN_ROOT * sizeof(struct cs1550_directory) - sizeof(int)];
73} ;
74
75
76typedef struct cs1550_directory_entry cs1550_directory_entry;
77
78//How much data can one block hold?
79#define MAX_DATA_IN_BLOCK (BLOCK_SIZE - sizeof(long))
80
81struct cs1550_disk_block
82{
83 //The next disk block, if needed. This is the next pointer in the linked
84 //allocation list
85 long nNextBlock;
86
87 //And all the rest of the space in the block can be used for actual data
88 //storage.
89 char data[MAX_DATA_IN_BLOCK];
90};
91
92typedef struct cs1550_disk_block cs1550_disk_block;
93
94static int checkExists(char* val) {
95 return val && val[0];
96}
97static int getStartLocation(struct cs1550_directory dir) {
98 return dir.nStartBlock * BLOCK_SIZE;
99}
100static int checkDName(const char *dName)
101{
102 if(strcmp(dName, "") == 0){
103 return 0;
104 }
105 return 1;
106}
107
108static void clear(char *val)
109{
110 strcpy(val, "");
111}
112static struct cs1550_directory getDirectory(char *destination, cs1550_root_directory rootDir);
113
114static struct cs1550_directory getDirectory(char *destination, cs1550_root_directory rootDir) {
115 struct cs1550_directory dir;
116 int i = 0;
117 for(i = 0; i < MAX_DIRS_IN_ROOT; i++){
118 dir = rootDir.directories[i];
119 if(strcmp(destination, rootDir.directories[i].dname) == 0) {
120 return (struct cs1550_directory) rootDir.directories[i];
121 }
122 }
123
124 return dir;
125}
126
127static void getFile(cs1550_directory_entry *entry, char* filename, char* extension, struct cs1550_file_directory* file) {
128
129 int i = 0;
130 while(i < MAX_FILES_IN_DIR) {
131 if(strcmp(entry->files[i].fname, filename) == 0
132 && strcmp(entry->files[i].fext, extension) == 0)
133 {
134 *file = entry->files[i];
135 break;
136 }
137 i++;
138 }
139}
140
141static char* formatFile(struct cs1550_file_directory file) {
142
143
144 // We do not want to tamper with the original file, so we need to make a new one
145 static char file_to_display[MAX_FILENAME + 1];
146 strcpy(file_to_display, file.fname);
147
148
149 if(strcmp(file.fext, "") != 0) strcat(file_to_display, DOT);
150
151 // We must add the file extension
152 strcat(file_to_display, file.fext);
153 if(strcmp(file.fname, "") != 0)
154
155
156 return file_to_display;
157}
158
159static void prepareDirectory(struct cs1550_directory* dir) {
160 strcpy(dir->dname, "");
161 dir->nStartBlock = -1;
162}
163
164static void prepareDirectoryEntry(cs1550_directory_entry* entry) {
165 entry->nFiles = 0;
166 memset(entry->files, 0, MAX_FILES_IN_DIR * sizeof(struct cs1550_file_directory));
167}
168
169static void prepareFileDirectory(struct cs1550_file_directory* entry, int size, int nStartBlock) {
170 entry->fsize = size;
171 entry->nStartBlock = nStartBlock;
172}
173
174static int checkFileExists(cs1550_directory_entry dir_entry, char* file_name, char* file_ext, int* free_file_loc) {
175 int j = 0;
176 int does_file_exist = 0;
177
178 while(j < MAX_FILES_IN_DIR){
179 struct cs1550_file_directory curr_file_dir = dir_entry.files[j];
180 if(strcmp(curr_file_dir.fname, "") == 0 &&
181 strcmp(curr_file_dir.fext, "") == 0 &&
182 *free_file_loc == -1)
183 {
184 *free_file_loc = j;
185 }
186
187 if(strcmp(curr_file_dir.fname, file_name) == 0
188 && strcmp(curr_file_dir.fext, file_ext) == 0)
189 {
190 does_file_exist = 1;
191 break;
192 }
193 j++;
194 }
195 printf("FILE EXITSTS IS: %d\n", does_file_exist);
196 return does_file_exist;
197}
198static void findFreeBlock(struct fat_table* fat_table, int* index_start) {
199 int y = 2;
200 int iterateTo = BLOCK_SIZE/sizeof(short);
201 while(y < iterateTo) {
202 if(fat_table->db[y] == 0){
203 fat_table->db[y] = EOF;
204 *index_start = y;
205 break;
206 }
207 y++;
208 }
209}
210
211static void getCurrentBlock(struct cs1550_file_directory* dir, int* currentBlock, struct fat_table fat_table, int offset) {
212 *currentBlock = dir->nStartBlock;
213 int blockNum = offset / BLOCK_SIZE;
214 if(blockNum != 0){
215 while(blockNum > 0){
216 // Get next block
217 *currentBlock = fat_table.db[*currentBlock];
218
219 // decrement number of blocks we vistied
220 blockNum -= 1;
221 }
222 }
223}
224static void initializeWriteVariables(int* bytesToWrite, int fsize, int offset, int* blockOffset) {
225 *bytesToWrite = fsize - offset;
226 *blockOffset = 0;
227}
228
229static void findFreeBlockToWrite(struct fat_table *fat_table, int* currentBlock, int* freeBlock) {
230 int y = 2;
231 // attempt to find a free block
232 while(y < BLOCK_SIZE/sizeof(short)) {
233 if(fat_table->db[y] == 0){
234 fat_table->db[y] = EOF;
235 fat_table->db[*currentBlock] = y;
236 *currentBlock = y;
237 *freeBlock = 1;
238 break;
239 }
240 y++;
241 }
242
243}
244/*
245 * Does the actual creation of a file. Mode and dev can be ignored.
246 *
247 */
248static int cs1550_mknod(const char *path, mode_t mode, dev_t dev)
249{
250
251 printf("IN mknod\n");
252 (void) mode;
253 (void) dev;
254
255
256 char* directory;
257 char* file_name;
258 char* extension;
259
260 // clear(&directory);
261 // clear(&file_name);
262 // clear(&extension);
263
264 // strcpy(directory, "");
265 // strcpy(file_name, "");
266 // strcpy(extension, "");
267
268
269 char path_copy[strlen(path)];
270 strcpy(path_copy, path);
271
272 directory = strtok(path_copy, "/");
273 file_name = strtok(NULL, ".");
274 extension = strtok(NULL, ".");
275
276 if((checkExists(directory)) &&
277 strcmp(directory, "") != 0)
278 {
279
280 if(checkExists(file_name)){
281 if(strcmp(file_name, "") == 0) return -EPERM;
282
283 if(checkExists(extension)){
284 if(strlen(file_name) > MAX_FILENAME ||
285 strlen(extension) > MAX_EXTENSION)
286 {
287 return -ENAMETOOLONG;
288 }
289 }
290 else{
291 if(strlen(file_name) > MAX_FILENAME){
292 return -ENAMETOOLONG;
293 }
294 }
295 } else
296 {
297 return -EPERM;
298 }
299
300 cs1550_root_directory root;
301 FILE* disk = fopen(DISK, MODE);
302 fseek(disk, 0, SEEK_SET);
303 fread(&root, BLOCK_SIZE, 1, disk);
304 fclose(disk);
305
306 struct fat_table fat_table;
307 disk = fopen(DISK, MODE);
308 fseek(disk, BLOCK_SIZE, SEEK_SET);
309 fread(&fat_table, BLOCK_SIZE, 1, disk);
310 fclose(disk);
311
312
313 struct cs1550_directory dir;
314
315 dir = getDirectory(directory, root);
316
317 if(strcmp(dir.dname, "") == 0) {
318 if(strcmp(directory, "") == 0) return 0;
319 else if(strcmp(file_name, "") == 0) return -EPERM;
320 }
321 else {
322
323 long disk_loc = getStartLocation(dir);
324 FILE* disk = fopen(DISK, MODE);
325 fseek(disk, disk_loc, SEEK_SET);
326
327 cs1550_directory_entry dir_entry;
328
329 printf("dir_entry.nFiles: %d\n", dir_entry.nFiles);
330 printf("MAX_FILES_IN_DIR: %d\n", MAX_FILES_IN_DIR);
331
332 int read_return = fread(&dir_entry, BLOCK_SIZE, 1, disk);
333
334 if(dir_entry.nFiles >= MAX_FILES_IN_DIR) {
335
336 return -EPERM;
337 }
338
339 if(read_return) {
340
341 int free_file_loc = -1;
342
343 int file_exists = checkFileExists(dir_entry, file_name, extension, &free_file_loc);
344
345 // File does not already exist, so lets go ahead and create one
346 if(!file_exists){
347 short file_fat_start_index = -1;
348
349 // Find our next free block
350 findFreeBlock(&fat_table, &file_fat_start_index);
351
352
353 struct cs1550_file_directory new_file_dir;
354 strcpy(new_file_dir.fname, file_name);
355
356 if(checkExists(extension)) strcpy(new_file_dir.fext, extension);
357 else strcpy(new_file_dir.fext, "");
358
359 prepareFileDirectory(&new_file_dir, 0, file_fat_start_index);
360 // new_file_dir.fsize = 0;
361 // new_file_dir.nStartBlock = file_fat_start_index;
362
363
364 dir_entry.files[free_file_loc] = new_file_dir;
365 dir_entry.nFiles += 1;
366
367
368 fseek(disk, disk_loc, SEEK_SET);
369 fwrite(&dir_entry, BLOCK_SIZE, 1, disk);
370
371 fclose(disk);
372
373 disk = fopen(DISK, MODE);
374 fwrite(&root, BLOCK_SIZE, 1, disk);
375 fclose(disk);
376
377 disk = fopen(DISK, MODE);
378 fseek(disk, BLOCK_SIZE, SEEK_SET);
379 fwrite(&fat_table, BLOCK_SIZE, 1, disk);
380 fclose(disk);
381
382 } else{
383 fclose(disk);
384 return -EEXIST;
385 }
386 } else{
387 fclose(disk);
388 return -EPERM;
389 }
390 }
391 }
392
393 return 0;
394}
395
396
397/*
398 * Called whenever the system wants to know the file attributes, including
399 * simply whether the file exists or not.
400 *
401 * man -s 2 stat will show the fields of a stat structure
402 */
403static int cs1550_getattr(const char *path, struct stat *stbuf)
404{
405 printf("IN GETATTR\n");
406 int res = 0;
407
408 memset(stbuf, 0, sizeof(struct stat));
409
410 //is path the root dir?
411 if (strcmp(path, "/") == 0) {
412
413 stbuf->st_mode = S_IFDIR | 0755;
414 stbuf->st_nlink = 2;
415 res = 0;
416 return res;
417 } else {
418 FILE* diskSim = fopen(DISK, MODE);
419 struct cs1550_directory dir;
420
421 dir.nStartBlock = -1;
422
423
424 int maxSize = MAX_FILENAME+1;
425 char directory[maxSize];
426 char filename[maxSize];
427 char extension[MAX_EXTENSION+1];
428
429 // get rid of any junk values
430 strcpy(dir.dname, "");
431 strcpy(filename, "");
432 strcpy(directory, "");
433 strcpy(extension, "");
434
435 // clear(&dir.dname);
436 // clear(&filename);
437 // clear(&directory);
438 // clear(&extension);
439
440 sscanf(path, "/%[^/]/%[^.].%s", directory, filename, extension);
441 printf("PATH: %s\n", path);
442 printf("directory: %s\n", directory);
443 printf("extension: %s\n", extension);
444 printf("IN SUB\n");
445 //Check if name is subdirectory
446
447 // Get the Root directory
448 FILE* disk = fopen(DISK, MODE);
449 fseek(disk, 0, SEEK_SET);
450 cs1550_root_directory rootDir;
451 fread(&rootDir, BLOCK_SIZE, 1, disk);
452
453 // grab the number of directories in the root folder
454 int directoryLength = rootDir.nDirectories;
455
456 dir = getDirectory(directory, rootDir);
457
458 if(!checkDName(&dir.dname)) {
459 printf("DONEST EXIST\n");
460 return -ENOENT;
461 }
462
463 if(!checkDName(&filename)){
464 stbuf->st_mode = S_IFDIR | 0755;
465 stbuf->st_nlink = 2;
466 res = 0;
467 return res; //no error
468 }
469 printf("DIRECTORY FIND: %s\n", dir.dname);
470 fclose(diskSim);
471
472
473
474
475 disk = fopen(DISK, MODE);
476 int loc = getStartLocation(dir);
477 fseek(diskSim, loc, SEEK_SET);
478
479 cs1550_directory_entry entry;
480 prepareDirectoryEntry(&entry);
481
482
483 int items_read = fread(&entry, BLOCK_SIZE, 1, diskSim);
484 fclose(diskSim);
485
486 if(items_read == 1){
487 struct cs1550_file_directory file;
488
489 strcpy(file.fname, "");
490 strcpy(file.fext, "");
491 // clear(&file.fname);
492 // clear(&file.fext);
493
494 file.fsize = 0;
495 file.nStartBlock = -1;
496
497 getFile(&entry, filename, extension, &file);
498
499 printf("Got file\n");
500 printf("FILE ATTR: %d\n", file.nStartBlock);
501 printf("FILE ATTR: %d\n", file.fsize);
502
503
504 // //regular file, probably want to be read and write
505 // stbuf->st_mode = S_IFREG | 0666;
506 // stbuf->st_nlink = 1; //file links
507 // stbuf->st_size = 0; //file size - make sure you replace with real size!
508 // res = 0; // no error
509
510
511 if((file.nStartBlock) != -1){
512
513 stbuf->st_mode = S_IFREG | 0666;
514 stbuf->st_nlink = 1;
515 stbuf->st_size = file.fsize;
516 return 0;
517
518 } else{
519 return -ENOENT;
520 }
521 }
522
523 }
524 return res;
525}
526
527// static void extract_file_parts(char *dest, char *fName, char *ext, char *the_path) {
528// printf("in extact\n");
529// printf("path is %s\n", the_path);
530// *dest = strtok(the_path, "/");
531// printf("dest is: %s\n", dest);
532// *fName = strtok(NULL, DOT);
533// printf("fname is: %s\n", fName);
534// *ext = strtok(NULL, ".");
535// printf("ext is: %s\n", ext);
536// }
537/*
538 * Called whenever the contents of a directory are desired. Could be from an 'ls'
539 * or could even be when a user hits TAB to do autocompletion
540 */
541static int cs1550_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
542 off_t offset, struct fuse_file_info *fi)
543{
544 printf("IN READDIR\n");
545
546 //Since we're building with -Wall (all warnings reported) we need
547 //to "use" every parameter, so let's just cast them to void to
548 //satisfy the compiler
549 (void) offset;
550 (void) fi;
551
552 //the filler function allows us to add entries to the listing
553 //read the fuse.h file for a description (in the ../include dir)
554 filler(buf, DOT, NULL, 0);
555 filler(buf, "..", NULL, 0);
556
557 //Parse the path, which is in the form: root/destination/filename.extension
558 char the_path[strlen(path)];
559 strcpy(the_path, path);
560
561
562 // Initialize the three components of our file
563 char* destination;
564 char* filename;
565 char* extension;
566
567
568 // function to extract the parts of file
569 // extract_file_parts(&destination, &filename, &extension, the_path);
570
571 destination = strtok(the_path, "/");
572 filename = strtok(NULL, ".");
573 extension = strtok(NULL, ".");
574 // printf("DEST FINAL %s\n", destination);
575 // printf("DEST FINAL LENGTH %s\n", strlen(destination));
576
577 // We must ensure that we don't have a file name or extension that is too long
578 if((checkExists(destination)) && strlen(destination) > MAX_FILENAME ||
579 ((checkExists(filename)) && strlen(filename) > MAX_FILENAME) ||
580 ((checkExists(extension)) && strlen(extension) > MAX_EXTENSION))
581 return -ENAMETOOLONG;
582
583
584 if(strcmp(path, "/") == 0){
585 int i = 0;
586
587 cs1550_root_directory root;
588 FILE* disk = fopen(DISK, MODE);
589 fseek(disk, 0, SEEK_SET);
590 fread(&root, BLOCK_SIZE, 1, disk);
591
592
593 for(i = 0; i < MAX_DIRS_IN_ROOT; i++) {
594 if(strcmp(root.directories[i].dname, "") != 0) filler(buf, root.directories[i].dname, NULL, 0);
595 }
596
597 return 0;
598 }
599 else{
600
601 struct cs1550_directory dir;
602 prepareDirectory(&dir);
603
604 cs1550_root_directory rootDir;
605 FILE* disk = fopen(DISK, MODE);
606 fseek(disk, 0, SEEK_SET);
607 fread(&rootDir, BLOCK_SIZE, 1, disk);
608
609 dir = (struct cs1550_directory) getDirectory(destination, rootDir);
610
611
612
613 if(strcmp(dir.dname, "") == 0) return -ENOENT;
614
615 else {
616 FILE* disk = fopen(DISK, MODE);
617 int location_on_disk = getStartLocation(dir);
618 fseek(disk, location_on_disk, SEEK_SET);
619
620 cs1550_directory_entry directory;
621 prepareDirectoryEntry(&directory);
622
623
624 fread(&directory, BLOCK_SIZE, 1, disk);
625 fclose(disk);
626
627
628 int j = 0;
629 while(j < MAX_FILES_IN_DIR) {
630
631 // Format the file we are going to display
632 char* file_to_display = formatFile(directory.files[j]);
633
634 // Display the file if it is not empty
635 if(strcmp(file_to_display, "") != 0) filler(buf, file_to_display, NULL, 0);
636
637 // Continue on to the next file
638 j++;
639 }
640 }
641 }
642 return 0;
643
644}
645
646
647
648
649
650/*
651 * Creates a directory. We can ignore mode since we're not dealing with
652 * permissions, as long as getattr returns appropriate ones for us.
653 */
654static int cs1550_mkdir(const char *path, mode_t mode)
655{
656 printf("IN MKDIR\n");
657 (void) path;
658 (void) mode;
659
660
661 char* dir;
662 char* sub_dir;
663
664
665
666
667 sub_dir = strtok(NULL, "/");
668 dir = strtok(path, "/");
669 printf("IN MKDIR4\n");
670
671 // The file name must not have a filename greater than MAX_FILENAME
672 if(strlen(dir) > MAX_FILENAME){
673 printf("CANNOT HAVE DIRECTORY GREATER THAN %d\n", MAX_FILENAME);
674 return -ENAMETOOLONG;
675 }
676
677 // Filesystem only supports directories in the root directory
678 else if(checkExists(sub_dir)){
679 printf("CANNOT HAVE DIRECTORY IN SUBDIRECTORY\n");
680 return -EPERM;
681 }
682
683
684 cs1550_root_directory rootDir;
685 FILE* disk = fopen(DISK, MODE);
686 fseek(disk, 0, SEEK_SET);
687 fread(&rootDir, BLOCK_SIZE, 1, disk);
688 fclose(disk);
689
690
691 struct fat_table fat_table;
692
693 disk = fopen(DISK, MODE);
694 fseek(disk, BLOCK_SIZE, SEEK_SET);
695 fread(&fat_table, BLOCK_SIZE, 1, disk);
696 fclose(disk);
697 dir = strtok(path, "/");
698
699
700 // Check to see if we already reached max number of directories
701 if(rootDir.nDirectories >= MAX_DIRS_IN_ROOT) {
702 printf("Max directories reached!\n");
703 return -EPERM;
704 }
705
706 int z = 0;
707 while (z < MAX_DIRS_IN_ROOT) {
708 if(strcmp(rootDir.directories[z++].dname, dir) == 0) return -EEXIST;
709 }
710
711
712 int i = 0;
713 while (i < MAX_DIRS_IN_ROOT) {
714
715 if(strcmp(rootDir.directories[i].dname, "") == 0) {
716 int y = 2;
717 int iterateTo = BLOCK_SIZE / sizeof(short);
718
719 struct cs1550_directory new_directory;
720
721 strcpy(new_directory.dname, dir);
722
723 // We need to find a empty block
724 while (y < iterateTo){
725
726 // We found a spot for our new file in our table
727 if(fat_table.db[y] == 0){
728 // We need to set our start block to the index we are currently at
729 new_directory.nStartBlock = y;
730
731 // Because this is the first block, we should store a value signifying its the last block in the list
732 fat_table.db[y] = EOF;
733
734 // Nothing more to do, so break
735 break;
736 }
737
738 y++;
739 }
740
741 printf("HERE4\n");
742 // Updated table, now must actually make the changes on disk
743 FILE* disk = fopen(DISK, MODE);
744 int loc = getStartLocation(new_directory);
745 fseek(disk, loc, SEEK_SET);
746
747 cs1550_directory_entry directory;
748 printf("HERE5\n");
749 prepareDirectoryEntry(&directory);
750 printf("HERE6\n");
751 int items_read = fread(&directory, BLOCK_SIZE, 1, disk);
752 printf("HERE7\n");
753 if(items_read != 1){
754 fclose(disk);
755 }
756 else{
757 printf("HERE8\n");
758 memset(&directory, 0, sizeof(struct cs1550_directory_entry));
759 fwrite(&directory, BLOCK_SIZE, 1, disk);
760 fclose(disk);
761
762
763 // We created new directory, so must increment the number of directories by 1
764 rootDir.nDirectories += 1;
765
766 // Set the next sub directory in our root directry to be out newly created directory
767 rootDir.directories[i] = new_directory;
768
769 // Write the root to disk
770 disk = fopen(DISK, MODE);
771 fwrite(&rootDir, BLOCK_SIZE, 1, disk);
772 fclose(disk);
773
774 disk = fopen(DISK, MODE);
775 fwrite(&rootDir, BLOCK_SIZE, 1, disk);
776 fclose(disk);
777
778 // Write fat table to disk
779 disk = fopen(DISK, MODE);
780 fseek(disk, BLOCK_SIZE, SEEK_SET);
781 fwrite(&fat_table, BLOCK_SIZE, 1, disk);
782 fclose(disk);
783
784 }
785 return 0;
786
787 }
788 i++;
789 }
790
791 return 0;
792}
793
794/*
795 * Removes a directory.
796 */
797static int cs1550_rmdir(const char *path)
798{
799 (void) path;
800 return 0;
801}
802
803
804/*
805 * Deletes a file
806 */
807static int cs1550_unlink(const char *path)
808{
809 (void) path;
810
811 return 0;
812}
813
814
815/*
816 * Read size bytes from file into buf starting from offset
817 *
818 */
819static int cs1550_read(const char *path, char *buf, size_t size, off_t offset,
820 struct fuse_file_info *fi)
821{
822 printf("IN READ\n");
823 (void) buf;
824 (void) offset;
825 (void) fi;
826 (void) path;
827
828
829 char* directory;
830 char* file_name;
831 char* file_ext;
832
833
834 int path_length = strlen(path);
835 char path_copy[path_length];
836 strcpy(path_copy, path);
837
838 directory = strtok(path_copy, "/");
839 file_name = strtok(NULL, ".");
840 file_ext = strtok(NULL, ".");
841
842 if((checkExists(directory)) &&
843 strcmp(directory, "") != 0){
844 if(file_name &&
845 file_name[0]){
846 if(strcmp(file_name, "") == 0){
847 return -EEXIST;
848 }
849
850 if(checkExists(file_ext)){
851
852 if(strlen(file_name) > MAX_FILENAME ||
853 strlen(file_ext) > MAX_EXTENSION){
854 return -ENAMETOOLONG;
855 }
856 } else{
857
858 if(strlen(file_name) > MAX_FILENAME){
859 return -ENAMETOOLONG;
860 }
861 }
862 } else{
863 return -EEXIST;
864 }
865
866
867 cs1550_root_directory root;
868 FILE* disk = fopen(DISK, MODE);
869 fseek(disk, 0, SEEK_SET);
870 fread(&root, BLOCK_SIZE, 1, disk);
871 fclose(disk);
872
873 struct fat_table fat_table;
874 disk = fopen(DISK, MODE);
875 fseek(disk, BLOCK_SIZE, SEEK_SET);
876 fread(&fat_table, BLOCK_SIZE, 1, disk);
877
878 struct cs1550_directory dir;
879
880
881 dir = getDirectory(directory, root);
882
883 if(strcmp(dir.dname,"") == 0) {
884
885 // Check value of directory
886 if(strcmp(directory,"") == 0) return 0;
887
888 // Check value of file name, if it is empty we have an error
889 else if(strcmp(file_name,"") == 0) return -EPERM;
890 }
891 else{
892
893 long dir_location_on_disk = getStartLocation(dir);
894
895 FILE* disk = fopen(DISK, MODE);
896 fseek(disk, dir_location_on_disk, SEEK_SET);
897
898 cs1550_directory_entry dir_entry;
899 int items_read = fread(&dir_entry, BLOCK_SIZE, 1, disk);
900 fclose(disk);
901
902 if(!items_read) return -EPERM;
903 else{
904 struct cs1550_file_directory file_dir;
905
906 int j = 0;
907 while(j < MAX_FILES_IN_DIR)
908 {
909 struct cs1550_file_directory curr_file_dir = dir_entry.files[j];
910 int found = 0;
911 if(strcmp(curr_file_dir.fname, file_name) == 0){
912 if(checkExists(file_ext)){
913 if(strcmp(curr_file_dir.fext, file_ext) == 0) found = 1;
914 }
915 else if(strcmp(curr_file_dir.fext, "") == 0) found = 1;
916 if(found == 1) {
917 file_dir = curr_file_dir;
918 break;
919 }
920 }
921 j++;
922 }
923 if(strcmp(file_dir.fname, "") == 0) return -EISDIR;
924 else {
925 if(offset > file_dir.fsize) return -EFBIG;
926
927
928 int block_number_of_file = 0;
929 int block_offset = 0;
930 if(offset != 0) {
931 block_number_of_file = offset / BLOCK_SIZE;
932 block_offset = offset - block_number_of_file * BLOCK_SIZE;
933 }
934
935
936
937 int curr_block = file_dir.nStartBlock;
938 if(block_number_of_file != 0){
939 int u;
940 // get the current block by following path in fat table
941 for(u = block_number_of_file; u > 0; u--) curr_block = fat_table.db[curr_block];
942 }
943
944
945 FILE* disk = fopen(DISK, MODE);
946 fseek(disk, BLOCK_SIZE * curr_block + block_offset, SEEK_SET);
947 cs1550_disk_block new_data;
948 fread(&new_data.data, BLOCK_SIZE-block_offset, 1, disk);
949 int curr_buffer_size = 0;
950
951
952 if(file_dir.fsize < BLOCK_SIZE) memcpy(buf, &new_data.data, file_dir.fsize);
953
954 else memcpy(buf, &new_data.data, BLOCK_SIZE-block_offset);
955
956 curr_buffer_size = BLOCK_SIZE - block_offset;
957
958
959 while(fat_table.db[curr_block] != EOF){
960 curr_block = fat_table.db[curr_block];
961
962 cs1550_disk_block data;
963 fseek(disk, BLOCK_SIZE*curr_block, SEEK_SET);
964 fread(&data.data, BLOCK_SIZE, 1, disk);
965 memcpy(buf+curr_buffer_size, &data, strlen(data.data));
966 curr_buffer_size += strlen(data.data);
967 }
968
969 fclose(disk);
970
971
972 disk = fopen(DISK, MODE);
973 fwrite(&root, BLOCK_SIZE, 1, disk);
974 fclose(disk);
975
976 disk = fopen(DISK, MODE);
977 fseek(disk, BLOCK_SIZE, SEEK_SET);
978 fwrite(&fat_table, BLOCK_SIZE, 1, disk);
979 fclose(disk);
980
981 size = curr_buffer_size;
982 }
983 }
984 }
985 }
986
987 return size;
988}
989
990
991
992
993/*
994 * Write size bytes from buf into file starting from offset
995 *
996 */
997static int cs1550_write(const char *path, const char *buf, size_t size,
998 off_t offset, struct fuse_file_info *fi)
999{
1000
1001 (void) buf;
1002 (void) offset;
1003 (void) fi;
1004 (void) path;
1005
1006 const int size_of_buffer = strlen(buf);
1007 const int offset_by_one = offset + 1;
1008
1009 char* directory;
1010 char* file_name;
1011 char* file_ext;
1012
1013
1014 char path_copy[strlen(path)];
1015 strcpy(path_copy, path);
1016
1017 directory = strtok(path_copy, "/");
1018 file_name = strtok(NULL, ".");
1019 file_ext = strtok(NULL, ".");
1020
1021 if(checkExists(directory) && strcmp(directory, "") != 0){
1022 if(checkExists(file_name)){
1023 if(strcmp(file_name, "") == 0) return -EEXIST;
1024
1025 if(checkExists(file_ext)){
1026 // in case i need to diffirenciate between the two conditions futher down the road
1027 int check = 0;
1028 if(strlen(file_name) > MAX_FILENAME) check = 1;
1029 if(strlen(file_ext) > MAX_EXTENSION) check = 1;
1030 if(check == 1) return -ENAMETOOLONG;
1031
1032 }
1033 else if (strlen(file_name) > MAX_FILENAME) return -ENAMETOOLONG;
1034 }
1035 else return -EEXIST;
1036
1037
1038
1039 cs1550_root_directory root;
1040 FILE* disk = fopen(DISK, MODE);
1041 fseek(disk, 0, SEEK_SET);
1042 fread(&root, BLOCK_SIZE, 1, disk);
1043 fclose(disk);
1044
1045 struct fat_table fat_table;
1046 disk = fopen(DISK, MODE);
1047 fseek(disk, BLOCK_SIZE, SEEK_SET);
1048 fread(&fat_table, BLOCK_SIZE, 1, disk);
1049
1050 struct cs1550_directory dir;
1051
1052 dir = getDirectory(directory, root);
1053
1054 if(strcmp(dir.dname, "") == 0) {
1055 if(strcmp(directory, "") == 0) return 0;
1056 else if(strcmp(file_name, "") == 0) return -EPERM;
1057 }
1058 else{
1059 long dir_location_on_disk = getStartLocation(dir);
1060
1061
1062 FILE* disk = fopen(DISK, MODE);
1063 fseek(disk, dir_location_on_disk, SEEK_SET);
1064 cs1550_directory_entry dir_entry;
1065 int read_return = fread(&dir_entry, BLOCK_SIZE, 1, disk);
1066 fclose(disk);
1067
1068 if(!read_return) return -EPERM;
1069 else {
1070 struct cs1550_file_directory file_dir;
1071 int file_directory_index = -1;
1072
1073 int x = 0;
1074 int found = 0;
1075 while(x < MAX_FILES_IN_DIR){
1076
1077 if(strcmp(dir_entry.files[x].fname, file_name) == 0){
1078
1079 // if file has extension, check to see if that is the same
1080 if(checkExists(file_ext)){
1081 if(strcmp(dir_entry.files[x].fext, file_ext) == 0) found = 1;
1082 }
1083
1084 // if file does not have extension make sure the file we are looking at doesn't have one either
1085 else if(strcmp(dir_entry.files[x].fext, "") == 0) found = 1;
1086
1087
1088 // We found what we were lookign for
1089 if(found == 1) {
1090 file_directory_index = x;
1091 file_dir = dir_entry.files[x];
1092 break;
1093 }
1094 x++;
1095
1096 }
1097 }
1098
1099 if(strcmp(file_dir.fname, "") == 0) return -EISDIR;
1100
1101 else {
1102
1103 // Check for valid offset
1104 if(offset > file_dir.fsize) return -EFBIG;
1105
1106 int bytesToWrite;
1107 int block_offset;
1108 initializeWriteVariables(&bytesToWrite, file_dir.fsize, offset, &block_offset);
1109
1110 if(offset != 0) block_offset = offset - (((int)(offset/BLOCK_SIZE)) * BLOCK_SIZE);
1111
1112
1113 // Get the correct block corresponding to the offset
1114 int theCurrentBlock = file_dir.nStartBlock;
1115 getCurrentBlock(&file_dir, &theCurrentBlock, fat_table, offset);
1116
1117 int bytesToProcess = size_of_buffer;
1118
1119
1120 FILE* disk = fopen(DISK, MODE);
1121 fseek(disk, BLOCK_SIZE*theCurrentBlock+block_offset, SEEK_SET);
1122 if(size_of_buffer >= BLOCK_SIZE){
1123 fwrite(buf, BLOCK_SIZE-block_offset, 1, disk);
1124 bytesToProcess -= (BLOCK_SIZE-block_offset);
1125
1126 if(offset == size){
1127 int newSize = offset_by_one;
1128 file_dir.fsize = newSize;
1129 }
1130 }
1131 else {
1132
1133 fwrite(buf, size_of_buffer, 1, disk);
1134
1135 int lengthOfArray = BLOCK_SIZE - size_of_buffer;
1136 char fillerArray[lengthOfArray];
1137 int c = 0;
1138 int maxRange = BLOCK_SIZE - size_of_buffer;
1139 while(c < maxRange) fillerArray[c++] = EMPTY;
1140
1141 fwrite(fillerArray, BLOCK_SIZE-size_of_buffer, 1, disk);
1142 bytesToProcess -= size_of_buffer;
1143
1144 if(file_dir.fsize > size){
1145 if(offset != size) file_dir.fsize = size;
1146 else file_dir.fsize = offset_by_one;
1147 }
1148 }
1149
1150
1151 int bytes_to_clear = size - size_of_buffer;
1152
1153 while(bytesToProcess > 0){
1154 if(fat_table.db[theCurrentBlock] == EOF){
1155 int freeBlock = 0;
1156 findFreeBlockToWrite(&fat_table, &theCurrentBlock, &freeBlock);
1157
1158 // We were not able to find a free block, so something went wrong
1159 if(freeBlock == 0) return -EPERM;
1160
1161 }
1162 else theCurrentBlock = fat_table.db[theCurrentBlock];
1163
1164
1165 fseek(disk, BLOCK_SIZE*theCurrentBlock, SEEK_SET);
1166 if(bytesToProcess < BLOCK_SIZE) {
1167 char* buff_addr_to_create = buf + (size_of_buffer - bytesToProcess);
1168 fwrite(buff_addr_to_create, bytesToProcess, 1, disk);
1169 bytesToProcess = 0;
1170 }
1171 else {
1172 char* buff_addr_to_create = buf + (size_of_buffer - bytesToProcess);
1173 fwrite(buff_addr_to_create, BLOCK_SIZE, 1, disk);
1174 bytesToProcess -= BLOCK_SIZE;
1175 }
1176 }
1177
1178
1179
1180 if(size_of_buffer - bytesToProcess - bytesToWrite > 0) file_dir.fsize += (size_of_buffer - bytesToProcess - bytesToWrite);
1181
1182
1183 dir_entry.files[file_directory_index] = file_dir;
1184 fseek(disk, dir.nStartBlock*BLOCK_SIZE, SEEK_SET);
1185 fwrite(&dir_entry, BLOCK_SIZE, 1, disk);
1186
1187 fclose(disk);
1188
1189 // Write root
1190 disk = fopen(DISK, MODE);
1191 fwrite(&root, BLOCK_SIZE, 1, disk);
1192 fclose(disk);
1193
1194 // Write fat table
1195 disk = fopen(DISK, MODE);
1196 fseek(disk, BLOCK_SIZE, SEEK_SET);
1197 fwrite(&fat_table, BLOCK_SIZE, 1, disk);
1198 fclose(disk);
1199
1200 size = size_of_buffer;
1201
1202 }
1203 }
1204
1205 }
1206
1207 }
1208
1209 return size;
1210}
1211
1212
1213
1214/******************************************************************************
1215 *
1216 * DO NOT MODIFY ANYTHING BELOW THIS LINE
1217 *
1218 *****************************************************************************/
1219
1220/*
1221 * truncate is called when a new file is created (with a 0 size) or when an
1222 * existing file is made shorter. We're not handling deleting files or
1223 * truncating existing ones, so all we need to do here is to initialize
1224 * the appropriate directory entry.
1225 *
1226 */
1227static int cs1550_truncate(const char *path, off_t size)
1228{
1229 (void) path;
1230 (void) size;
1231
1232 return 0;
1233}
1234
1235
1236/*
1237 * Called when we open a file
1238 *
1239 */
1240static int cs1550_open(const char *path, struct fuse_file_info *fi)
1241{
1242 (void) path;
1243 (void) fi;
1244 /*
1245 //if we can't find the desired file, return an error
1246 return -ENOENT;
1247 */
1248
1249 //It's not really necessary for this project to anything in open
1250
1251 /* We're not going to worry about permissions for this project, but
1252 if we were and we don't have them to the file we should return an error
1253
1254 return -EACCES;
1255 */
1256
1257 return 0; //success!
1258}
1259
1260/*
1261 * Called when close is called on a file descriptor, but because it might
1262 * have been dup'ed, this isn't a guarantee we won't ever need the file
1263 * again. For us, return success simply to avoid the unimplemented error
1264 * in the debug log.
1265 */
1266static int cs1550_flush (const char *path , struct fuse_file_info *fi)
1267{
1268 (void) path;
1269 (void) fi;
1270
1271 return 0; //success!
1272}
1273
1274
1275//register our new functions as the implementations of the syscalls
1276static struct fuse_operations hello_oper = {
1277 .getattr = cs1550_getattr,
1278 .readdir = cs1550_readdir,
1279 .mkdir = cs1550_mkdir,
1280 .rmdir = cs1550_rmdir,
1281 .read = cs1550_read,
1282 .write = cs1550_write,
1283 .mknod = cs1550_mknod,
1284 .unlink = cs1550_unlink,
1285 .truncate = cs1550_truncate,
1286 .flush = cs1550_flush,
1287 .open = cs1550_open,
1288};
1289
1290//Don't change this.
1291int main(int argc, char *argv[])
1292{
1293 return fuse_main(argc, argv, &hello_oper, NULL);
1294}