-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsfs.c
More file actions
1487 lines (1336 loc) · 41.1 KB
/
sfs.c
File metadata and controls
1487 lines (1336 loc) · 41.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
Simple File System
This code is derived from function prototypes found /usr/include/fuse/fuse.h
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
His code is licensed under the LGPLv2.
*/
#include "params.h"
#include "block.h"
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <fuse.h>
#include <libgen.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "structures.h"
#ifdef HAVE_SYS_XATTR_H
#include <sys/xattr.h>
#endif
#include "log.h"
#define SetBit(A,k) ( A[(k/32)] |= (1 << (k%32)) )
#define ClearBit(A,k) ( A[(k/32)] &= ~(1 << (k%32)) )
#define TestBit(A,k) ( A[(k/32)] & (1 << (k%32)) )
inode* inode_table;
/* HELPER FUNCTIONS - inode table functions
*
*
*
*/
/*
* Takes in an inode table and writes the table to the disk. The only error checking the inode table does is with disk_write,
* and will log messages if the disk could not be written to
*/
int write_inode_table(inode* inode_table, superblock* superblock_t) {
// writing inode table to fs file
int inode_start = superblock_t->start_of_inode_table;
int i = 0;
int q = 0;
for(i = inode_start; i < superblock_t->start_of_data_block; ++i){
inode* temp = (inode*)malloc(sizeof(inode)*32);
for(q = 0; q < 32; ++q){
log_msg("temp index: %d - inode_table index: %d\n", q, q + ((i - inode_start)*32));
temp[q] = inode_table[q + ((i-inode_start)*32)];
}
int j = block_write(i, (const void*)temp);
if (j < 1){
log_msg("error trying to write inode table to block\n");
return -1;
}
}
for(i = 0; i < superblock_t->num_of_inodes; ++i){
log_msg("parent of i: %d\n", inode_table[i].parent);
}
free(inode_table);
log_msg("inode table is loaded\n");
return 0;
}
/*
* This function will return the inode table currently written to disk
* The only error checking done is with disk_read. Log messages will be written if
* the blocks read are empty or if the blocks cannot be read.
*/
inode* load_inode_table(superblock* superblock_t) {
log_msg("in load_inode\n");
inode* inode_table = (inode*)malloc(sizeof(inode) * superblock_t->num_of_inodes);
char* buffer[4096];
int inode_start = superblock_t->start_of_inode_table;
// load inode table into disk file
int i = 0;
int q = 0;
for(i = superblock_t->start_of_inode_table; i < superblock_t->start_of_data_block; ++i){
inode* temp;
int j = block_read(i, buffer);
temp = (inode*)buffer;
if (j < 0){
log_msg("error trying to write inode table to block\n");
return NULL;
}
else if (j == 0){
log_msg("while reading inode table block, blocks are empty\n");
return NULL;
}
log_msg("pass read\n");
for(q = 0; q < 32; ++q){
inode_table[q + ((i-inode_start)*32)] = temp[q];
}
}
/*
for(i = 0; i < superblock_t->num_of_inodes; ++i){
log_msg("parent of i: %d\n", inode_table[i].parent);
}*/
log_msg("inode table is loaded\n");
return inode_table;
}
/* HELPER FUNCTIONS - Bitmap Functions
*
*
*
*/
/*
* This function searches the inode_bitmap and returns an index number of the first found free inode, also sets the bit
* If a free inode cannot be found, whether there are no more free inodes or undefined behavior occurs, the function will return -1.
*/
int find_inode(superblock* superblock_t){
log_msg("in find_inode\n");
// load in bitmap
char buffer[4096];
int j = block_read(superblock_t->start_of_inode_bitmap, buffer);
int* inode_bitmap = (int*)buffer;
if (j < 0){
log_msg("error trying to write inode table to block\n");
return -1;
}
else if (j == 0){
log_msg("while reading inode table block, blocks are empty\n");
return -1;
}
log_msg("num_of_inodes: %d\n", superblock_t->num_of_inodes);
int i = 0;
// find free inode in inode_bitmap
log_msg("num of inodes: %d\n", superblock_t->num_of_inodes);
for(i = 1; i < superblock_t->num_of_inodes; ++i){
log_msg("testbit ret val: %d\n", TestBit(inode_bitmap, i));
if(!TestBit(inode_bitmap, i)){
log_msg("found a free inode\n");
// set bit because it is no longer free
SetBit(inode_bitmap, i);
if(!TestBit(inode_bitmap, i))
log_msg("WE HAVE A WINNNNNERRRR LEO AIN't A STREET BABY AHAHAHAHAHAHHAAHHAAHAHA\n");
// write bitmap back to fs file, error check
j = block_write(superblock_t->start_of_inode_bitmap, inode_bitmap);
if (j < 1){
log_msg("error trying to write inode table to block\n");
return -1;
}
return i;
}
}
log_msg("could not find a free inode\n");
return -1;
}
/*
* This function searches the block bitmap for a free block. The block number is returned, and the bit is set in the bitmap
* If a free block cannot be found, whether there are no more free blocks or undefined behavior occurs, the function will return -1.
*/
int find_block(superblock* superblock_t){
log_msg("in find_block\n");
// load in bitmap
char buffer[4096];
int j = block_read(superblock_t->start_of_block_bitmap, buffer);
int* block_bitmap = (int*)buffer;
if (j < 0){
log_msg("error trying to write inode table to block\n");
return -1;
}
else if (j == 0){
log_msg("while reading inode table block, blocks are empty\n");
return -1;
}
// find free block in block_bitmap
int i = 0;
for(i = 1; i < superblock_t->num_of_data_blocks; ++i){
int x = TestBit(block_bitmap, i);
log_msg("testbit ret val: %d\n", x);
if(!TestBit(block_bitmap, i)){
log_msg("found a free block\n");
// set bit because it is no longer free
SetBit(block_bitmap, i);
// write bitmap back to fs file, error check
j = block_write(superblock_t->start_of_block_bitmap, block_bitmap);
if (j < 1){
log_msg("error trying to write inode table to block\n");
return -1;
}
return i;
}
}
log_msg("could not find a free block\n");
return -1;
}
/* HELPER FUNCTIONS - parser functions
*
*
*
*/
//ALL YOUR SLASHING NEEDS:
//returns number of slashes found in given path
//returns -1 if consecutive slashes or no beginning slash or has an ending slash
int numslash(const char *path){
int pathlen = strlen(path);
int slashcount=0;
int lastslashind=-1;//make sure no consecutive slashes
int i;//loop
if (path[pathlen-1]=='/'||path[0]!='/')//path must begin with a slash and NOT end with a slash
return -1;
for (i=0;i<pathlen;i++){
if (path[i]=='/'){
if (lastslashind==-1){
lastslashind=i;
}else{
if (i-1==lastslashind){
return -1;
}
}
slashcount++;
lastslashind=i;
}
}
return slashcount;
}
///////////////////////////////////////////////////////////
//
// Prototypes for all these functions, and the C-style comments,
// come indirectly from /usr/include/fuse.h
//
/**
* Initialize filesystem
*
* The return value will passed in the private_data field of
* fuse_context to all file operations and as a parameter to the
* destroy() method.
*
* Introduced in version 2.3
* Changed in version 2.6
*/
void *sfs_init(struct fuse_conn_info *conn)
{
fprintf(stderr, "in bb-init\n");
log_msg("\nsfs_init()\n");
struct sfs_state* state = SFS_DATA;
char* disk=state->diskfile;
log_conn(conn);
log_fuse_context(fuse_get_context());
// Create superblock struct
superblock* superblock_t = (superblock*)malloc(sizeof(superblock));
superblock_t->magic_num = 69;
superblock_t->num_of_inodes = 256;
superblock_t->num_of_data_blocks = 4085;
superblock_t->max_num_of_files = 256;
superblock_t->max_num_of_blocks = 87;
superblock_t->block_size = 4096;
superblock_t->start_of_inode_table = 3;
superblock_t->start_of_block_bitmap = 2;
superblock_t->start_of_inode_bitmap = 1;
superblock_t->start_of_data_block = 11;
// declare bitmaps and set all to 0 indicating open
int* inode_bitmap = (int*)malloc(sizeof(int) * 1024);
int i;
for(i = 0; i < 1024; ++i){
inode_bitmap[i] = 0;
}
int* block_bitmap = (int*)malloc(sizeof(int) * 1024);
for(i = 0; i < 1024; ++i){
block_bitmap[i] = 0;
}
// declare inode table
inode_table = (inode*)malloc(sizeof(inode)*256);
// root dir
memcpy(inode_table[0].filename, "/", 1);
inode_table[0].num = 0;
inode_table[0].type = IS_DIR;
inode_table[0].isOpen = IS_CLOSED;
inode_table[0].size = 0;
inode_table[0].parent = -2;
int j = 0;
for(j = 0; j < 15; ++j){
inode_table[0].blocks[j] = -1;
}
// fulling inode table
for(i = 1; i < 256; ++i){
inode_table[i].num = i;
inode_table[0].isOpen = IS_CLOSED;
for(j = 0; j < 15; ++j){
inode_table[i].blocks[j] = -1;
}
inode_table[i].parent = -1;
}
disk_open(disk);
// write superblock to disk
j = block_write(0, superblock_t);
if (j < 1){
log_msg("error trying to write inode table to block\n");
return;
}
// write inode bitmap
j = block_write(superblock_t->start_of_inode_bitmap, inode_bitmap);
if (j < 1){
log_msg("error trying to write inode table to block\n");
return;
}
// write block bitmap
j = block_write(superblock_t->start_of_block_bitmap, block_bitmap);
if (j < 1){
log_msg("error trying to write inode table to block\n");
return;
}
/*
// write inode table
if(write_inode_table(inode_table, superblock_t) == -1){
log_msg("failed to write inode_table\n");
return;
}*/
free(superblock_t);
free(inode_bitmap);
free(block_bitmap);
return SFS_DATA;
}
/**
* Clean up filesystem
*
* Called on filesystem exit.
*
* Introduced in version 2.3
*/
void sfs_destroy(void *userdata)
{
log_msg("\nsfs_destroy(userdata=0x%08x)\n", userdata);
disk_close();
}
/** Get file attributes (metadata)
*
* Similar to stat(). The 'st_dev' and 'st_blksize' fields are
* ignored. The 'st_ino' field is ignored except if the 'use_ino'
* mount option is given.
*/
int sfs_getattr(const char *path, struct stat *statbuf)
{
char *filename=NULL;
char tokenpath[PATH_MAX];
tokenpath[PATH_MAX]='\0';
int retstat = 0;
log_msg("\nsfs_getattr(path=\"%s\", statbuf=0x%08x)\n",
path, statbuf);
char buffers[4096];
// read in superblock
block_read(0, buffers);
superblock* superblock_t = (superblock*) buffers;
// read in inode_table
//inode* inode_table = load_inode_table(superblock_t);
if(inode_table == NULL){
log_msg("inode table returned -1 in getattr\n");
return -1;
}
inode root=inode_table[0];
//If the inode is the root directory
if ((strcmp(path,"/")==0)) {
statbuf->st_mode = S_IFDIR | 0755;
statbuf->st_size=root.size;
statbuf->st_nlink = 1;
statbuf->st_blocks=((root.size-1)+4096)/4096;
statbuf->st_atime = time(NULL);
statbuf->st_ctime = time(NULL);
statbuf->st_mtime = time(NULL);
/*
// write changes to inode_table into the fs file
if(write_inode_table(inode_table, superblock_t) == -1){
log_msg("could not write inode_table to fs file\n");
return -1;
}*/
log_msg("get attr returning\n");
return retstat;
}
else {
//Get the disk path
char* disk=SFS_DATA->diskfile;
//buffer to read into
char buffer[4096];
//Read in the root node
inode rootDir=inode_table[0];
int cp = rootDir.num;
//Search through all the direct map ptrs
int i=1;
for(i;i<superblock_t->num_of_inodes;i++) {
//block num referenced by ptr
inode temp=inode_table[i];
int parent = temp.parent;
if(parent == cp) {
// get filename, -1 for null terminator + -1 for root '/'
strcpy(tokenpath, path);
filename=strtok(tokenpath,"/");
log_msg("tempgpath: %s - %s\n", temp.filename, filename);
//Compares paths for match
if(strcmp(temp.filename,filename)==0) {
statbuf->st_nlink = 1;
statbuf->st_mode = S_IFDIR | 0775;
statbuf->st_size=temp.size;
statbuf->st_blocks=((temp.size-1)+4096)/4096;
statbuf->st_atime = time(NULL);
statbuf->st_ctime = time(NULL);
statbuf->st_mtime = time(NULL);
if(temp.type == IS_FILE){
log_msg("ISA FILE BITCH\n");
statbuf->st_mode = S_IFREG | 0777;
}
/*
// write changes to inode_table into the fs file
if(write_inode_table(inode_table, superblock_t) == -1){
log_msg("could not write inode_table to fs file\n");
return -1;
}*/
return retstat;
}
}
}
}
/*
// write changes to inode_table into the fs file
if(write_inode_table(inode_table, superblock_t) == -1){
log_msg("could not write inode_table to fs file\n");
return -1;
}*/
//free(inode_table);
return -ENOENT;
}
/**
* Create and open a file
*
* If the file does not exist, first create it with the specified
* mode, and then open it.
*
* If this method is not implemented or under Linux kernel
* versions earlier than 2.6.15, the mknod() and open() methods
* will be called instead.
*
* Introduced in version 2.5
*/
int sfs_create(const char *path, mode_t mode, struct fuse_file_info *fi){
int retstat = 0;
log_msg("\nsfs_create(path=\"%s\", mode=0%03o, fi=0x%08x)\n",
path, mode, fi);
int i,j;
int iposition;//bit index of inode bitmap
int dposition;//bit index of data block bitmap
int slashcount;
char tokenpath[PATH_MAX];//can't modify path so copy
char *token=NULL;//will hold current token
char *parname; //store file's parent (IMPORTANT)
int parid;//parent id
char **pathwords;//tokenized "words" in path
int numdir;//number of directories in path input
//inode *table;//will hold inode table read from disk
//some path checking
if ((slashcount = numslash(path))>=1){//checking numslash doesn't give -1
numdir=slashcount-1;
}else if (strcmp(path,"/")==0){//path shouldnt be "/"
log_msg("failure in create with path: %s\n",path);
return -1;
}else{//either numslash returned -1, or 0
log_msg("failure in create with bad path: %s\n",path);
return -1;
}
//retrieve superblock
char sbuf[4096];
superblock* s;
int z = block_read(0, sbuf);
if (z < 0){
log_msg("error trying to write inode table to block\n");
}
else if (z == 0){
log_msg("while reading inode table block, blocks are empty\n");
}
s=(superblock*)sbuf;
log_msg("num_of_inodes in create: %d\n", s->block_size);
log_msg("num_of_inodes in create: %d\n", s->num_of_inodes);
int it_start = 0;
int it_end = s->max_num_of_files;
iposition=find_inode(s);
dposition=find_block(s);
log_msg("inode returned: %d\n", iposition);
log_msg("data block returned: %d\n", dposition);
if (iposition==-1 || dposition==-1){
log_msg("failure in create with invalid space left\n");
return -1;
}
//tokenizing time!
log_msg("path before strcpy: %s\n", path);
tokenpath[PATH_MAX] = '\0';
strcpy(tokenpath,path);
token=strtok(tokenpath,"/");
log_msg("path after strcpy: %s\n", path);
if (slashcount==1){//root case: root is parent dir
//inode_table=(inode *)malloc(it_end*sizeof(inode));
//inode_table = load_inode_table(s);
if(inode_table == NULL){
log_msg("inode_table returned NULL in create\n");
return -1;
}
//check if file exists
for (i=it_start;i<it_end;i++){//iterate thru inode table block nums
if (strcmp(inode_table[i].filename,token)==0 && inode_table[i].parent==0){//filenames match and rootdir is parent (inum=0?)
//BADDD it EXISTS!!!
log_msg("failure in create: FILE EXISTS\n");
//free(table);
return -1;
}
}
//create file at iposition
//modify superblock
s->num_of_inodes++;
s->num_of_data_blocks++;
//modify bitmaps with indices: dposition, iposition
//initialize new inode
inode_table[iposition].type=IS_FILE;
inode_table[iposition].isOpen=IS_OPEN;//open it
strcpy(inode_table[iposition].filename,token);
log_msg("create is inserting filename %s into new inode\n",inode_table[iposition].filename);
inode_table[iposition].parent=0;
inode_table[iposition].size=0;
inode_table[iposition].blocks[0]=dposition;
inode_table[iposition].single_indir_ptr=NULL;
inode_table[iposition].double_indir_ptr=NULL;
//writing back to disk
block_write(0,s);//write superblock back
/*
//write bitmaps back
if(write_inode_table(table,s) == -1){
log_msg("could not write inode table to disk in create\n");
return -1;
}//write back to disk
*/
//free(inode_table);
log_msg("create is a success with path: %s\n",path);
return 0;
}
}
/** Remove a file */
int sfs_unlink(const char *path){
int retstat = 0;
log_msg("sfs_unlink(path=\"%s\")\n", path);
int slashcount;//return value of numslash
int i=0;//loop var
int j=0;//loop var
char tokenpath[PATH_MAX];//can't modify path so copy
char *token=NULL;//will hold current token
char **pathwords;//tokenized "words" in path
int numdir;//number of directories in path input
//inode *table;
//path checking
if ((slashcount = numslash(path))>=1){//checking numslash doesn't give -1
numdir=slashcount-1;
}else if (strcmp(path,"/")==0){//path shouldnt be "/"
log_msg("failure in unlink with path: %s\n",path);
return -1;
}else{//either numslash returned -1, or 0
log_msg("failure in unlink with bad path\n");
return -1;
}
//load in superblock
char sbuf[BLOCK_SIZE];
superblock *s = (superblock *)malloc(sizeof(superblock));
block_read(0,sbuf);
s=(superblock *)sbuf;
if(s == NULL){
log_msg("superblock returned NULL in unlink\n");
return -1;
}
//load in inode table
//inode_table=(inode *)malloc(s->num_of_inodes*sizeof(inode));
//inode_table = load_inode_table(s);
//load in block bitmap
int* block_bitmap = (int*)malloc(sizeof(int) * 1024);
block_read(s->start_of_block_bitmap, block_bitmap);
//load in inode bitmap
int* inode_bitmap = (int*)malloc(sizeof(int) * 1024);
block_read(s->start_of_inode_bitmap, inode_bitmap);
//check table and bitmap mallocs
if(inode_table == NULL){
log_msg("inode_table returned NULL in open\n");
return -1;
}else if(inode_bitmap == NULL){
log_msg("inode_bitmap returned NULL in open\n");
return -1;
}else if(block_bitmap == NULL){
log_msg("block_bitmap returned NULL in open\n");
return -1;
}
//tokenizing time!
strcpy(tokenpath,path);
token=strtok(tokenpath,"/");
int blocksfreed=0;
if (slashcount==1){//root parent case
for (i=0;i<s->num_of_inodes;i++){//iterate thru inode table block nums
if (strcmp(inode_table[i].filename,token)==0 && inode_table[i].parent==0){//filenames match and rootdir is parent (inum=0?)
//update inode
inode_table[i].isOpen=IS_CLOSED;//close it
inode_table[i].parent=-1;//reset parent
inode_table[i].size=0;//reset size
//clear filename
for (j=0;j<32;j++){
inode_table[i].filename[j]='\0';
}
//clear each block and reset their bits
for (j=0;j<15;j++){
if (inode_table[i].blocks[j]!=-1){//something is there
ClearBit(block_bitmap,j);//reset block bit
inode_table[i].blocks[j]=-1;//reset block
blocksfreed++;
}
}
//reset inode bit
ClearBit(inode_bitmap,i);
//update superblock
s->num_of_inodes--;
s->num_of_data_blocks-=blocksfreed;
//write back bitmaps, superblock, inode table
if(block_write(0,s) == -1){//superblock
log_msg("couldn't write superblock back");
return -1;
}else if(block_write(s->start_of_inode_bitmap, inode_bitmap) == -1){//inode bitmap
log_msg("couldn't write inode bitmap back");
return -1;
}else if(block_write(s->start_of_block_bitmap,block_bitmap) == -1){//block bitmap
log_msg("couldn't write block bitmap back");
return -1;
}/*
else if(write_inode_table(table,s) == -1){//inode table
log_msg("couldn't write inode table back");
return -1;
}*/
//free superblock and return
//free(table);
free(block_bitmap);
free(inode_bitmap);
log_msg("unlink is successful with path: %s\n",path);
return 0;
}
}
//free(table);
free(block_bitmap);
free(inode_bitmap);
log_msg("unlink is a failure with path: %s\n",path);
return -1;
}
//free(table);
free(block_bitmap);
free(inode_bitmap);
log_msg("unlink is a failure with path: %s\n",path);
return -1;
}
/** File open operation
*
* No creation, or truncation flags (O_CREAT, O_EXCL, O_TRUNC)
* will be passed to open(). Open should check if the operation
* is permitted for the given flags. Optionally open may also
* return an arbitrary filehandle in the fuse_file_info structure,
* which will be passed to all file operations.
*
* Changed in version 2.2
*/
int sfs_open(const char *path, struct fuse_file_info *fi){
int retstat = 0;
log_msg("\nsfs_open(path\"%s\", fi=0x%08x)\n",
path, fi);
int slashcount;//return value of numslash
int i=0;//loop var
int j=0;//loop var
char tokenpath[PATH_MAX];//can't modify path so copy
char *token=NULL;//will hold current token
char *parname; //store file's parent (IMPORTANT)
int parid;//parent id
char **pathwords;//tokenized "words" in path
int numdir;//number of directories in path input
//inode *table;
if ((slashcount = numslash(path))>=1){//checking numslash doesn't give -1
numdir=slashcount-1;
}else if (strcmp(path,"/")==0){//path shouldnt be "/"
log_msg("failure in open with path: %s\n",path);
return -1;
}else{//either numslash returned -1, or 0
log_msg("failure in open with bad path\n");
return -1;
}
//retrieve superblock
char sbuf[BLOCK_SIZE];
superblock *s;
block_read(0,sbuf);
s=(superblock *)sbuf;
int it_start = 0;
int it_end = s->max_num_of_files;
//tokenizing time!
strcpy(tokenpath,path);
token=strtok(tokenpath,"/");
if (slashcount==1){//root parent case
//table=(inode *)malloc(it_end*sizeof(inode));
//table = load_inode_table(s);
if(inode_table == NULL){
log_msg("inode_table returned NULL in open\n");
}
for (i=it_start;i<it_end;i++){//iterate thru inode table block nums
if (strcmp(inode_table[i].filename,token)==0 && inode_table[i].parent==0){//filenames match and rootdir is parent (inum=0?)
inode_table[i].isOpen=IS_OPEN;//open it
/*
//write back
if(write_inode_table(table,s) == -1){
return -1;
}*/
log_msg("open is successful with path: %s\n",path);
return 0;
}
}
//free(table);
log_msg("open is a failure with path: %s\n",path);
return -1;
}else{//othercases that are deeper than rootdir
/*
pathwords=(char **)malloc(slashcount*sizeof(char *));
for (j=0;j<slashcount;j++){
pathwords[j]=(char *)malloc(16*sizeof(char));
}
i=0;
while (token!=NULL){
printf("token is currently: %s\n",token);
pathwords[i]=token;
//do stuff before next token
if (i==numdir-1){//store parent of file
parname=token;
}
//store stuff?
//end do stuff
token = strtok(NULL, "/");//next token
i++;
}
*/
//ALGO
//iterate thru ALL files
//fetch current inode
//see if filename matches token && see if parent inode = root inode (from superblock)
//if so, set to open, free shit and return 0
//[after loop]: file does not exist, free shit, return -1
//if not, then create and set its parent to "/"
return -1;
}
/*
// write inode table back to fs file
if(write_inode_table(table, s) == -1){
log_msg("could not write inode_table to disk\n");
return -1;
}*/
}
/** Release an open file
*
* Release is called when there are no more references to an open
* file: all file descriptors are closed and all memory mappings
* are unmapped.
*
* For every open() call there will be exactly one release() call
* with the same flags and file descriptor. It is possible to
* have a file opened more than once, in which case only the last
* release will mean, that no more reads/writes will happen on the
* file. The return value of release is ignored.
*
* Changed in version 2.2
*/
int sfs_release(const char *path, struct fuse_file_info *fi)
{
int retstat = 0;
log_msg("\nsfs_release(path=\"%s\", fi=0x%08x)\n",
path, fi);
if(strcmp(path, "/") == 0){
log_msg("you done goofed, you tried to file release the root dir!\n");
return -1;
}
// CASE FOR ONLY FILES IN ROOT DIR
int i = numslash(path);
if (i == 1){
log_msg("only 1 slash in the path\n");
// load in superblock
superblock* superblock_t = (superblock*)malloc(sizeof(superblock));
log_msg("works so far\n");
int z = block_read(0, superblock_t);
if (z < 0){
log_msg("error trying to write inode table to block\n");
return -1;
}
else if (z == 0){
log_msg("while reading inode table block, blocks are empty\n");
return -1;
}
log_msg("wrote superblock\n");
// get filename, -1 for null terminator + -1 for root '/'
char token[32];
strcpy(token, path);
char filename[sizeof(token)-1];
memcpy(filename, &token[1], (sizeof(token)-1));
log_msg("filename to be searched for in release: %s\n", filename);
// load in inode table
//inode* inode_table = load_inode_table(superblock_t);
if(inode_table == NULL){
log_msg("inode_table returned NULL in release\n");
return -1;
}
// look for file in inode table
for(i = 1; i < superblock_t->num_of_inodes; ++i){
// if file exists and is in the root dir
if((strcmp(filename, inode_table[i].filename) == 0) && (inode_table->parent == -1)){
// change isOpen field to IS_OPEN
log_msg("found file to close in releasedir\n");
inode_table[i].isOpen = IS_CLOSED;
log_msg("release just closed file\n");
break;
}
}
}
else {
log_msg("There is a consecutive slash or no beginning slash or has an ending slash in the path when closing");
return -1;
}
log_msg("release ended");
return retstat;
}
/** Read data from an open file
*
* Read should return exactly the number of bytes requested except
* on EOF or error, otherwise the rest of the data will be
* substituted with zeroes. An exception to this is when the
* 'direct_io' mount option is specified, in which case the return
* value of the read system call will reflect the return value of
* this operation.
*
* Changed in version 2.2
*/
int sfs_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
{
int retstat = 0;
log_msg("\nsfs_read(path=\"%s\", buf=0x%08x, size=%d, offset=%lld, fi=0x%08x)\n",
path, buf, size, offset, fi);
char bufferss[4096];
int z = block_read(0, bufferss);
if (z < 0)
log_msg("error trying to write inode table to block\n");
else if (z == 0)
log_msg("while reading inode table block, blocks are empty\n");
superblock* superblock_t = (superblock*) bufferss;
// read in inode_table
//inode* inode_table = load_inode_table(superblock_t);
if(inode_table == NULL){
log_msg("inode table returned -1 in read\n");
return -1;
}
inode r = inode_table[0];
int x = 1;
int amountRead = 0;
for (; x <superblock_t->num_of_inodes ; x++)
{
inode r = inode_table[x];
if(strcmp(r.filename,path+1) == 0)
{
int numBlocksToRead = ((offset%4096+size)-1+4096)/4096;
int firstBlock = offset/4096;
int lastBlock = firstBlock+numBlocksToRead;
int i = firstBlock;
for(i;i<=lastBlock;i++) {
if(i<15) {
char buffer3[4096];
//initialize
if(r.blocks[i]==-1) {
return amountRead;
}
block_read(r.blocks[i], buffer3);
if(i==firstBlock) {
memcpy(buf+amountRead,buffer3+offset%4096,4096-offset%4096);
amountRead+=4096-offset%4096;
}
else if (i==lastBlock) {
memcpy(buf+amountRead,buffer3,size-amountRead);
amountRead+=size-amountRead;
}
else {
memcpy(buf+amountRead,buffer3,4096);
amountRead+=4096-offset%4096;
}
}
}
}
}
return amountRead;
}
/** Write data to an open file
*
* Write should return exactly the number of bytes requested
* except on error. An exception to this is when the 'direct_io'
* mount option is specified (see read operation).
*
* Changed in version 2.2
*/
int sfs_write(const char *path, const char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
int retstat = 0;
log_msg("\nsfs_write(path=\"%s\", buf=0x%08x, size=%d, offset=%lld, fi=0x%08x)\n",
path, buf, size, offset, fi);
int u=0;
char buffers[4096];
// read in superblock
block_read(0, buffers);
superblock* superblock_t = (superblock*) buffers;
// read in inode_table
//inode* inode_table = load_inode_table(superblock_t);
inode root = inode_table[0];
int cp = root.num;
for(u;u<superblock_t->num_of_inodes;u++)