17 #include "test3_aux.h"
21 struct filedesc files[MAXFILES];
22 struct InodeBitmap ib;
23 struct BlockBitmap bb;
25 int bbbptr; // pointer to the BlockBitmap block
26 int ibbptr; // pointer to the InodeBlock block
27 int itbptr; // pointer to the InodeTable block
28 int rdiptr; // pointer to the RootDirectoryInode block
30 struct InodeBitmap* sc_ib;
31 struct BlockBitmap* sc_bb;
32 struct InodeBlock* sc_it;
38 #include "SimpleHash.h"
40 int testinode(int i) {
43 temp = sc_ib->inode[i/8]&(1<<(i%8));
44 return temp == 0 ? 0 : 1;
47 int testblock(int i) {
50 temp = sc_bb->blocks[i/8]&(1<<(i%8));
51 return temp == 0 ? 0 : 1;
54 unsigned long selfcheck2(struct block* d) {
56 struct timeval begin,end;
58 gettimeofday(&begin,NULL);
62 gettimeofday(&end,NULL);
63 t=(end.tv_sec-begin.tv_sec)*1000000+end.tv_usec-begin.tv_usec;
67 void selfcheck(struct block* diskptr) {
69 /* get time information for statistics */
70 struct timeval begin,end;
72 gettimeofday(&begin,NULL);
75 /* hand written data structure consistency */
77 struct SuperBlock* sb = (struct SuperBlock*)&diskptr[0];
78 struct GroupBlock* gb = (struct GroupBlock*)&diskptr[1];
80 int numblocks = sb->NumberofBlocks;
81 int numinodes = sb->NumberofInodes;
83 SimpleHash* hash_inodeof = new SimpleHash(1000); // estimation of the number of files!
84 SimpleHash* hash_contents = new SimpleHash(1000); // contents
85 SimpleList* list_inodes = new SimpleList();
86 SimpleList* list_blocks = new SimpleList();
90 // check bitmap consistency with superblock, groupblock, inotetableblock
91 // inodebitmapblock, blockbitmapblock, rootidrectoryinode
93 sc_bbbptr = gb->BlockBitmapBlock;
94 sc_ibbptr = gb->InodeBitmapBlock;
95 sc_itbptr = gb->InodeTableBlock;
96 sc_rdiptr = sb->RootDirectoryInode;
98 // constraint 8: automatic...
99 // constraint 9: automatic...
102 if (sc_itbptr < numblocks) {
103 sc_it = (InodeBlock*)&diskptr[sc_itbptr];
109 if (sc_ibbptr < numblocks) {
110 sc_ib = (InodeBitmap*)&diskptr[sc_ibbptr];
116 if (sc_bbbptr < numblocks) {
117 sc_bb = (BlockBitmap*)&diskptr[sc_bbbptr];
125 assert(testblock(0)); // superblock
134 assert(testblock(1)); // groupblock
136 // building list_blocks
143 assert(testblock(sc_itbptr));
145 // building list_blocks
146 list_blocks->add(sc_itbptr);
152 assert(testblock(sc_ibbptr));
154 // building list_blocks
155 list_blocks->add(sc_ibbptr);
161 assert(testblock(sc_bbbptr));
163 // building list_blocks
164 list_blocks->add(sc_bbbptr);
167 // build inodeof and contents
168 if (sb->RootDirectoryInode < numinodes) {
169 int dinode = sb->RootDirectoryInode;
171 // building list_inodes
172 list_inodes->add(dinode);
174 for (int k = 0 ; k <= 11 ; k++) {
176 int block = sc_it->entries[dinode].Blockptr[k];
179 hash_contents->add(dinode, block);
180 list_blocks->add(block);
183 if (block < numblocks) {
185 DirectoryBlock* db = (DirectoryBlock*)&diskptr[block];
187 for (int j = 0; j < sb->blocksize/128 ; j++) {
189 DirectoryEntry* de = (DirectoryEntry*)&db->entries[j];
191 if (de->inodenumber < numinodes) {
192 // add <de, de.inodenumber> to inodeof
193 hash_inodeof->add((int)de, de->inodenumber);
196 if (de->inodenumber < numinodes && de->inodenumber != 0) {
199 list_inodes->add(de->inodenumber);
201 for (int j2 = 0 ; j2 <= 11 ; j2++) {
202 int block2 = sc_it->entries[de->inodenumber].Blockptr[j2];
204 hash_contents->add(de->inodenumber, block2);
205 if (block2 < numblocks) {
206 list_blocks->add(block2);
218 // rule 6 and rule 11: rootdirectoryinode
219 if (sb->RootDirectoryInode < numinodes) {
220 int inode = sb->RootDirectoryInode;
223 assert(testinode(inode));
225 int filesize = sc_it->entries[inode].filesize;
227 for (int j = 0; j <= 11; j++) {
228 int block2 = sc_it->entries[inode].Blockptr[j];
230 // TBD: needs to actual store state because
231 // there could be duplicate numbers and they
232 // shouldn't be double counted
236 if (block2 < numblocks) {
238 assert(testblock(block2));
241 //printf("%d - %d %d %d\n", inode, j, block2, hash_contents->countdata(block2));
242 assert(hash_contents->countdata(block2)==1);
248 assert(filesize <= (contents*8192));
251 assert(sc_it->entries[inode].referencecount == hash_inodeof->countdata(inode));
255 if (sb->RootDirectoryInode < numinodes) {
256 int dinode = sb->RootDirectoryInode;
258 for (int j = 0; j < sb->blocksize/128 ; j++) {
259 for (int k = 0 ; k <= 11 ; k++) {
260 int block = sc_it->entries[dinode].Blockptr[k];
261 if (block < numblocks) {
262 DirectoryBlock* db = (DirectoryBlock*)&diskptr[block];
263 DirectoryEntry* de = (DirectoryEntry*)&db->entries[j];
265 int inode = de->inodenumber;
266 if (inode < numinodes && inode != 0) {
269 assert(testinode(inode));
272 int filesize = sc_it->entries[inode].filesize;
274 for (int j2 = 0; j2 <= 11; j2++) {
275 int block2 = sc_it->entries[inode].Blockptr[j2];
281 if (block2 < numblocks) {
283 assert(testblock(block2));
286 assert(hash_contents->countdata(block2)==1);
290 assert(filesize <= (contents*8192));
293 assert(sc_it->entries[inode].referencecount == hash_inodeof->countdata(inode));
301 // interesting question is going to be how to deal with 7 and 8
302 // actually it turns out that the constraints bound to rules 7 and 8 are
303 // easy... its just that creating the lists for 7 and 8 is a little tricky...
304 // 7 can easily piggyback on the creation of inodeof/contents... it fits quite
305 // nicely into that traversal... same goes for 8
308 for (int i = 0 ; i < numinodes ; i++) {
309 if (!list_inodes->contains(i)) {
312 printf("<bad inode,%d>", i);
313 assert(testinode(i)==0);
319 for (int i = 0 ; i < numblocks ; i++) {
320 if (!list_blocks->contains(i)) {
323 printf("<bad block,%d>", i);
324 assert(testblock(i)==0);
331 gettimeofday(&end,NULL);
332 t=(end.tv_sec-begin.tv_sec)*1000000+end.tv_usec-begin.tv_usec;
334 printf("\npassed tests in %ld u-seconds!\n", t);
340 int main(int argc, char **argv)
344 for(int i=0;i<MAXFILES;i++)
349 printf("Filesystem Repair:\n\tusage: main [0..9]\n\n");
350 printf("\t 0 : creates disk\n");
351 printf("\t 1 : mount disk, creates files and writes test data\n");
353 printf("\t 3 : inserts errors to break specs\n");
372 /* mounts the disk, creates NUMFILES files, and writes "buf" in each file
374 struct block * ptr=mountdisk("disk");
376 for(int i=0; i<NUMFILES; i++) {
378 sprintf(filename,"file_%d",i);
379 openfile(ptr,filename);
382 for(int j=0; j<90; j++) {
383 for(int i=0; i<NUMFILES; i++) {
384 char *buf="01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123";
385 writefile(ptr,i,buf,122);
389 for(int i=0; i<NUMFILES; i++) {
394 printinodeblock(ptr);
402 struct block * ptr=mountdisk("disk");
405 printinodeblock(ptr);
408 unsigned long time = 0;
409 for (int i = 0; i < 50; i++) {
410 // time += benchmark();
413 printf("\ninterpreted: %u us\n", (time/50));
419 struct block * ptr=mountdisk("disk");
422 printinodeblock(ptr);
432 struct block * ptr=mountdisk("disk");
435 printinodeblock(ptr);
439 unsigned long time = 0;
441 time += selfcheck2(ptr);
443 printf("\ncompiled: %u us\n", (time));
449 // insert errors that break the specs
452 // prints the directory structure, and prints the contents of each file
453 struct block * ptr=mountdisk("disk");
455 for(int i=1; i<NUMFILES; i++) {
457 sprintf(filename,"file_%d",i);
458 printfile(filename,ptr);
465 // the same as "case '1'" only that the files are accessed in reversed order
466 struct block * ptr=mountdisk("disk");
467 for(int i=NUMFILES; i>1; i--) {
469 sprintf(filename,"file_%d",i);
470 openfile(ptr,filename);
472 for(int j=0; j<90; j++) {
473 for(int i=NUMFILES; i>1; i--) {
474 char *buf="01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123";
475 writefile(ptr,i,buf,122);
478 for(int i=NUMFILES; i>1; i--) {
486 struct block * ptr=mountdisk("disk");
487 for(int i=NUMFILES; i>=0; i--) {
489 sprintf(filename,"file_%d",i);
490 openfile(ptr,filename);
493 for(int j=0;j<6000;j++) {
494 for(int i=NUMFILES; i>=0; i--) {
496 int len=sprintf(name, "%d ",i);
497 writefile(ptr,i,name,len);
500 for(int i=NUMFILES; i>=0; i--) {
503 for(int i=NUMFILES; i>=0; i--) {
505 sprintf(filename,"file_%d",i);
506 openfile(ptr,filename);
509 for(int j=0;j<400;j++) {
510 for(int i=NUMFILES; i>=0; i--) {
513 int len=sprintf(name, "%d ",i);
514 readfile(ptr,i,name,len);
515 sscanf(name, "%d ", &l);
517 printf("ERROR in benchmark\n");
521 for(int i=NUMFILES; i>=0; i--) {
531 struct block * ptr=chmountdisk("disk");
532 int t=selfcheck2(ptr);
533 printf("\ncompiled: %u us\n", (t));
536 struct block * ptr=mountdisk("disk");
537 for(int i=NUMFILES; i>=0; i--) {
539 sprintf(filename,"file_%d",i);
540 openfile(ptr,filename);
542 for(int j=0; j<6000; j++) {
543 for(int i=NUMFILES; i>=0; i--) {
545 int len=sprintf(name, "%d ",i);
546 writefile(ptr,i,name,len);
549 for(int i=NUMFILES; i>=0; i--) {
552 for(int i=NUMFILES; i>=0; i--) {
554 sprintf(filename,"file_%d",i);
555 openfile(ptr,filename);
557 for(int j=0;j<400;j++) {
558 for(int i=NUMFILES; i>=0; i--) {
561 int len=sprintf(name, "%d ",i);
562 readfile(ptr,i,name,len);
563 sscanf(name, "%d ", &l);
565 printf("ERROR in benchmark\n");
569 for(int i=NUMFILES; i>=0; i--) {
576 for(int i=0;i<MAXFILES;i++)
580 struct block * ptr=mountdisk("disk");
582 for(int i=0; i<NUMFILES; i++)
585 sprintf(filename,"file_%d", i);
586 openfile(ptr,filename);
589 for(int i=0; i<NUMFILES; i++)
592 sprintf(buf,"This is file_%d.", i);
593 writefile(ptr,i,buf,strlen(buf));
597 createlink(ptr, "file_1", "link_1");
598 createlink(ptr, "file_1", "link_2");
600 removefile("file_1", ptr);
602 int fd = openfile(ptr, "new");
603 writefile(ptr, fd, "new", 3);
605 printfile("file_1", ptr);
606 printfile("link_1", ptr);
607 printfile("link_2", ptr);
609 for(int i=0; i<NUMFILES; i++)
621 struct block * chmountdisk(char *filename) {
622 int fd=open(filename,O_CREAT|O_RDWR);
623 struct block *ptr=(struct block *) mmap(NULL,LENGTH,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,fd,0);
630 void chunmountdisk(struct block *vptr) {
631 int val=munmap(vptr,LENGTH);
639 // mounts the disk from the file "filename"
640 struct block * mountdisk(char *filename) {
641 int fd=open(filename,O_CREAT|O_RDWR);
642 struct block *ptr=(struct block *) mmap(NULL,LENGTH,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,fd,0);
645 if ((int)ptr == -1) {
646 perror("mountdisk\0");
651 struct SuperBlock *sb=(struct SuperBlock *) &ptr[0];
652 struct GroupBlock *gb=(struct GroupBlock *) &ptr[1];
653 bbbptr=gb->BlockBitmapBlock;
654 ibbptr=gb->InodeBitmapBlock;
655 itbptr=gb->InodeTableBlock;
656 rdiptr=sb->RootDirectoryInode;
658 struct InodeBitmap *ibb=(struct InodeBitmap *) &ptr[ibbptr];
659 for(int i=0;i<(NUMINODES/8+1);i++)
660 ib.inode[i]=ibb->inode[i];
662 struct BlockBitmap *bbb=(struct BlockBitmap *) &ptr[bbbptr];
663 for(int i=0;i<(NUMBLOCK/8+1);i++)
664 bb.blocks[i]=bbb->blocks[i];
666 printf("Disk mounted successfully from the file %s\n", filename);
674 void unmountdisk(struct block *vptr) {
675 struct InodeBitmap *ibb=(struct InodeBitmap *) &vptr[ibbptr];
676 for(int i=0;i<(NUMINODES/8+1);i++)
677 ibb->inode[i]=ib.inode[i];
679 struct BlockBitmap *bbb=(struct BlockBitmap *) &vptr[bbbptr];
680 for(int i=0;i<(NUMBLOCK/8+1);i++)
681 bbb->blocks[i]=bb.blocks[i];
682 int val=munmap(vptr,LENGTH);
689 void removefile(char *filename, struct block *ptr) {
690 struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
691 for(int i=0;i<12;i++) {
692 struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
693 for(int j=0;j<BLOCKSIZE/128;j++) {
694 if (db->entries[j].name[0]!=0) {
695 if(strcmp(filename,db->entries[j].name)==0) {
697 db->entries[j].name[0]=0; //Delete entry
698 int inode=db->entries[j].inodenumber;
699 db->entries[j].inodenumber=0;
701 struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
702 itb->entries[inode].referencecount--;
704 if (itb->entries[inode].referencecount==0) {
705 for(int i=0;i<((itb->entries[inode].filesize+BLOCKSIZE-1)/BLOCKSIZE);i++) {
706 int blocknum=itb->entries[inode].Blockptr[i];
707 bb.blocks[blocknum/8]^=(1<<(blocknum%8));
709 ib.inode[inode/8]^=(1<<(inode%8));
718 void createlink(struct block *ptr,char *filename, char *linkname) {
719 struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
720 for(int i=0;i<12;i++) {
721 struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
722 for(int j=0;j<BLOCKSIZE/DIRECTORYENTRYSIZE;j++) {
723 if (db->entries[j].name[0]!=0) {
724 if(strcmp(filename,db->entries[j].name)==0) {
726 int inode=db->entries[j].inodenumber;
727 struct InodeBlock * itb=(struct InodeBlock *) &ptr[4];
728 itb->entries[inode].referencecount++;
729 addtode(ptr, inode, linkname);
737 void closefile(struct block *ptr, int fd) {
738 struct InodeBlock * itb=(struct InodeBlock *) &ptr[4];
741 msync(&itb->entries[fd],sizeof(DirectoryEntry),MS_SYNC);
742 files[fd].used=false;
746 bool writefile(struct block *ptr, int fd, char *s) {
747 return (writefile(ptr,fd,s,1)==1);
751 int writefile(struct block *ptr, int fd, char *s, int len) {
752 struct filedesc *tfd=&files[fd];
753 if (tfd->used==false)
755 struct InodeBlock * itb=(struct InodeBlock *) &ptr[4];
756 int filelen=itb->entries[tfd->inode].filesize;
757 if ((12*BLOCKSIZE-tfd->offset)<len)
758 len=12*BLOCKSIZE-tfd->offset;
759 for(int i=0;i<len;i++) {
760 int nbuffer=tfd->offset/BLOCKSIZE;
761 int noffset=tfd->offset%BLOCKSIZE;
762 if (tfd->offset>=filelen) {
764 int bptr=getblock(ptr);
766 if (itb->entries[files[fd].inode].filesize<files[fd].offset)
767 itb->entries[files[fd].inode].filesize=files[fd].offset;
770 itb->entries[tfd->inode].Blockptr[nbuffer]=bptr;
773 int block=itb->entries[tfd->inode].Blockptr[nbuffer];
774 char *fchar=(char *)&ptr[block];
776 if (tocopy>(BLOCKSIZE-noffset))
777 tocopy=BLOCKSIZE-noffset;
778 memcpy(&fchar[noffset],&s[i],tocopy);
779 msync(&fchar[noffset],tocopy,MS_SYNC);
783 if (itb->entries[files[fd].inode].filesize<files[fd].offset)
784 itb->entries[files[fd].inode].filesize=files[fd].offset;
789 // reads one char from the file fd and returns it
790 char readfile(struct block *ptr, int fd) {
792 if (readfile(ptr,fd,array,1)==1)
798 // reads len chars from file fd (file system *ptr) and returns them in buf
799 int readfile(struct block *ptr, int fd, char *buf, int len) {
800 struct filedesc *tfd=&files[fd];
801 if (tfd->used==false)
804 struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
805 int filelen=itb->entries[tfd->inode].filesize;
807 // if there are fewer than len chars left, read until the end
808 if ((filelen-tfd->offset)<len)
809 len=filelen-tfd->offset;
811 for(int i=0;i<len;) {
812 int nbuffer=tfd->offset/BLOCKSIZE;
813 int noffset=tfd->offset%BLOCKSIZE;
814 int block=itb->entries[tfd->inode].Blockptr[nbuffer];
815 char *fchar=(char *)&ptr[block];
817 if (tocopy>(BLOCKSIZE-noffset))
818 tocopy=BLOCKSIZE-noffset;
819 memcpy(&buf[i],&fchar[noffset],tocopy);
828 int openfile(struct block *ptr, char *filename) {
831 for(int k=0;k<MAXFILES;k++) {
839 if (fd==-1) return fd;
841 /* Check to see if file exists*/
842 struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
843 for(int i=0;i<12;i++)
845 struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
846 for(int j=0;j<BLOCKSIZE/DIRECTORYENTRYSIZE;j++)
848 if (db->entries[j].name[0]!=0) {
849 if(strcmp(filename, db->entries[j].name)==0)
851 files[fd].inode=db->entries[j].inodenumber;
859 /* If file doesn't exist, create it */
860 int inode=getinode(ptr);
862 files[fd].used=false;
865 itb->entries[inode].filesize=0;
866 itb->entries[inode].referencecount=1;
867 for (int i=0;i<12;i++)
868 itb->entries[inode].Blockptr[i]=0;
870 addtode(ptr, inode, filename);
871 files[fd].inode=inode;
877 void createfile(struct block *ptr,char *filename, char *buf,int buflen) {
878 int fd=openfile(ptr,filename);
879 writefile(ptr,fd,buf,buflen);
885 // adds a file to the directory entry
886 void addtode(struct block *ptr, int inode, char *filename) {
887 struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
888 for(int i=0;i<12;i++) {
889 struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
890 for(int j=0;j<BLOCKSIZE/DIRECTORYENTRYSIZE;j++) {
891 if (db->entries[j].name[0]==0) {
893 strncpy(db->entries[j].name,filename,124);
894 db->entries[j].inodenumber=inode;
895 msync(&db->entries[j],sizeof(DirectoryEntry),MS_SYNC);
903 // return the first free node in the InodeTable. Marks that inode as used.
904 int getinode(struct block *ptr) {
905 for(int i=0;i<NUMINODES;i++) {
906 if (!(ib.inode[i/8]&(1<<(i%8)))) {
907 ib.inode[i/8]=ib.inode[i/8]|(1<<(i%8));
915 int getblock(struct block * ptr) {
916 for(int i=0;i<NUMBLOCK;i++) {
917 if (!(bb.blocks[i/8]&(1<<(i%8)))) {
918 bb.blocks[i/8]=bb.blocks[i/8]|(1<<(i%8));
929 int blocksize=BLOCKSIZE;
930 int numblocks=NUMBLOCK;
932 int fd=open("disk",O_CREAT|O_RDWR|O_TRUNC, S_IREAD|S_IWRITE);
934 // creates numblocks and initializes them with 0
935 char *buf=(char *)calloc(1,blocksize);
936 for(int i=0;i<numblocks;i++) {
937 write(fd,buf,blocksize);
941 // maps the file 'disk' into memory
942 void *vptr=mmap(NULL,LENGTH,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,fd,0);
944 // added by dan roy for debugging
945 if ((int)vptr == -1) {
946 perror("createdisk()\0");
951 struct block *ptr=(struct block *)vptr;
953 struct SuperBlock * sb=(struct SuperBlock*) &ptr[0];
954 sb->FreeBlockCount=NUMBLOCK-5;
955 sb->FreeInodeCount=NUMINODES-1;
956 sb->NumberofInodes=NUMINODES;
957 sb->NumberofBlocks=NUMBLOCK;
958 sb->RootDirectoryInode=0;
959 sb->blocksize=BLOCKSIZE;
962 struct GroupBlock * gb=(struct GroupBlock *) &ptr[1];
963 gb->BlockBitmapBlock=2;
964 gb->InodeBitmapBlock=3;
965 gb->InodeTableBlock=4;
966 gb->GroupFreeBlockCount=NUMBLOCK-5;
967 gb->GroupFreeInodeCount=NUMINODES-1;
970 struct BlockBitmap * bb=(struct BlockBitmap *) &ptr[2];
971 //memset(bb, 0, sizeof(BlockBitmap));
972 for(int i=0;i<(5+12);i++) {
973 bb->blocks[i/8]=bb->blocks[i/8]|(1<<(i%8));
977 struct InodeBitmap * ib=(struct InodeBitmap *) &ptr[3];
978 //memset(ib, 0, sizeof(InodeBitmap));
982 struct InodeBlock * itb=(struct InodeBlock *) &ptr[4];
984 itb->entries[0].filesize=12*BLOCKSIZE;
985 for(int i=0;i<12;i++)
986 itb->entries[0].Blockptr[i]=i+5; // blocks 5 to 16 are RootDirectory entries
987 itb->entries[0].referencecount=0;
990 int val=munmap(vptr,LENGTH);
995 printf("Disk created successfully!\n");
999 void printdirectory(struct block *ptr)
1001 struct InodeBlock *itb=(struct InodeBlock *) &ptr[itbptr];
1003 for(int i=0;i<12;i++)
1005 struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
1007 for(int j=0;j<BLOCKSIZE/DIRECTORYENTRYSIZE;j++) {
1008 if (db->entries[j].name[0]!=0)
1011 //printf("%s %d\n",db->entries[j].name, db->entries[j].inodenumber);
1012 printf("%s (inode %d) (%d bytes)\n",db->entries[j].name, db->entries[j].inodenumber, itb->entries[db->entries[j].inodenumber].filesize);
1017 //printf("end of printdirectory\n");
1020 // prints the contents of the file with filename "filename"
1021 void printfile(char *filename, struct block *ptr)
1023 printf("=== BEGIN of %s ===\n", filename);
1024 struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
1025 for(int i=0;i<12;i++) {
1026 struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
1027 for(int j=0;j<BLOCKSIZE/DIRECTORYENTRYSIZE;j++) {
1028 if (db->entries[j].name[0]!=0) {
1029 if(strcmp(filename,db->entries[j].name)==0) {
1031 int inode=db->entries[j].inodenumber;
1033 struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
1034 for(int i=0;i<((itb->entries[inode].filesize+BLOCKSIZE-1)/BLOCKSIZE);i++) {
1035 struct block *b=&ptr[itb->entries[inode].Blockptr[i]];
1036 write(0,b,BLOCKSIZE);
1042 printf("\n=== END of %s ===\n", filename);
1046 void printinodeblock(struct block *ptr)
1048 struct InodeBlock *itb=(struct InodeBlock *) &ptr[itbptr];
1050 for (int i=0; i<NUMINODES; i++)
1052 Inode inode = itb->entries[i];
1053 printf("inode %d: (filesize %d), (referencecount %d)\n", i, inode.filesize, inode.referencecount);