SimpleFS
A Simple File Sytem implementation including Disk and Shell Layers
fs_layer_2.cpp
Go to the documentation of this file.
1 
12 #include "sfs/fs.h"
13 #include "sfs/sha256.h"
14 
15 #include <algorithm>
16 #include <string>
17 #include <math.h>
18 #include <assert.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <iostream>
22 
23 #define streq(a, b) (strcmp((a), (b)) == 0)
24 
25 using namespace std;
26 
33  if(!mounted){return false;}
34  if(MetaData.Protected) return change_password();
35 
37  SHA256 hasher;
38  char pass[1000], line[1000];
39  Block block;
40 
42  printf("Enter new password: ");
43  if (fgets(line, BUFSIZ, stdin) == NULL) return false;
44  sscanf(line, "%s", pass);
45 
47  MetaData.Protected = 1;
48  strcpy(MetaData.PasswordHash,hasher(pass).c_str());
49 
50  // Write chanes back to the disk */
51  block.Super = MetaData;
52  fs_disk->write(0,block.Data);
53  printf("New password set.\n");
54  return true;
55 }
56 
63  if(!mounted){return false;}
64 
65  if(MetaData.Protected){
67  char pass[1000], line[1000];
68  SHA256 hasher;
69 
71  printf("Enter current password: ");
72  if (fgets(line, BUFSIZ, stdin) == NULL) return false;
73  sscanf(line, "%s", pass);
74 
76  if(hasher(pass) != string(MetaData.PasswordHash)){
77  printf("Old password incorrect.\n");
78  return false;
79  }
80 
82  MetaData.Protected = 0;
83  }
84  return FileSystem::set_password();
85 }
86 
92  if(!mounted){return false;}
93 
94  if(MetaData.Protected){
96  char pass[1000], line[1000];
97  SHA256 hasher;
98  Block block;
99 
101  printf("Enter old password: ");
102  if (fgets(line, BUFSIZ, stdin) == NULL) return false;
103  sscanf(line, "%s", pass);
104 
106  if(hasher(pass) != string(MetaData.PasswordHash)){
107  printf("Old password incorrect.\n");
108  return false;
109  }
110 
112  MetaData.Protected = 0;
113 
115  block.Super = MetaData;
116  fs_disk->write(0,block.Data);
117  printf("Password removed successfully.\n");
118 
119  return true;
120  }
121  return false;
122 
123 }
124 
125 FileSystem::Directory FileSystem::add_dir_entry(Directory dir, uint32_t inum, uint32_t type, char name[]){
130  Directory tempdir = dir;
131 
133  uint32_t idx = 0;
134  for(; idx < FileSystem::ENTRIES_PER_DIR; idx++){
135  if(tempdir.Table[idx].valid == 0){break;}
136  }
137 
139  if(idx == FileSystem::ENTRIES_PER_DIR){
140  printf("Directory entry limit reached..exiting\n");
141  tempdir.Valid = 0;
142  return tempdir;
143  }
144 
146  tempdir.Table[idx].inum = inum;
147  tempdir.Table[idx].type = type;
148  tempdir.Table[idx].valid = 1;
149  strcpy(tempdir.Table[idx].Name,name);
150 
151  return tempdir;
152 }
153 
160  if(
161  (offset < 0) ||
162  (offset >= ENTRIES_PER_DIR) ||
163  (curr_dir.Table[offset].valid == 0) ||
164  (curr_dir.Table[offset].type != 0)
165  ){Directory temp; temp.Valid=0; return temp;}
166 
168  uint32_t inum = curr_dir.Table[offset].inum;
169  uint32_t block_idx = (inum / FileSystem::DIR_PER_BLOCK);
170  uint32_t block_offset = (inum % FileSystem::DIR_PER_BLOCK);
171 
173  Block blk;
174  fs_disk->read(MetaData.Blocks - 1 - block_idx, blk.Data);
175  return (blk.Directories[block_offset]);
176 }
177 
184  uint32_t block_idx = (dir.inum / FileSystem::DIR_PER_BLOCK) ;
185  uint32_t block_offset = (dir.inum % FileSystem::DIR_PER_BLOCK);
186 
188  Block block;
189  fs_disk->read(MetaData.Blocks - 1 - block_idx, block.Data);
190  block.Directories[block_offset] = dir;
191 
193  fs_disk->write(MetaData.Blocks - 1 - block_idx, block.Data);
194 }
195 
196 int FileSystem::dir_lookup(Directory dir,char name[]){
202  uint32_t offset = 0;
203  for(;offset < FileSystem::ENTRIES_PER_DIR; offset++){
204  if(
205  (dir.Table[offset].valid == 1) &&
206  (streq(dir.Table[offset].Name,name))
207  ){break;}
208  }
209 
211  if(offset == FileSystem::ENTRIES_PER_DIR){return -1;}
212 
213  return offset;
214 }
215 
216 bool FileSystem::ls_dir(char name[]){
221  if(!mounted){return false;}
222 
224  int offset = dir_lookup(curr_dir,name);
225  if(offset == -1){printf("No such Directory\n"); return false;}
226 
228  FileSystem::Directory dir = read_dir_from_offset(offset);
229 
231  if(dir.Valid == 0){printf("Directory Invalid\n"); return false;}
232 
234  printf(" inum | name | type\n");
235  for(uint32_t idx=0; idx<FileSystem::ENTRIES_PER_DIR; idx++){
236  struct Dirent temp = dir.Table[idx];
237  if(temp.valid == 1){
238  if(temp.type == 1) printf("%-10u | %-16s | %-5s\n",temp.inum,temp.Name, "file");
239  else printf("%-10u | %-16s | %-5s\n",temp.inum,temp.Name, "dir");
240  }
241  }
242  return true;
243 }
244 
245 bool FileSystem::mkdir(char name[FileSystem::NAMESIZE]){
250  if(!mounted){return false;}
251 
253  uint32_t block_idx = 0;
254  for(;block_idx < MetaData.DirBlocks; block_idx++)
255  if(dir_counter[block_idx] < FileSystem::DIR_PER_BLOCK)
256  break;
257 
258  if(block_idx == MetaData.DirBlocks){printf("Directory limit reached\n"); return false;}
259 
261  Block block;
262  fs_disk->read(MetaData.Blocks - 1 - block_idx, block.Data);
263 
264 
266  uint32_t offset=0;
267  for(;offset < FileSystem::DIR_PER_BLOCK; offset++)
268  if(block.Directories[offset].Valid == 0)
269  break;
270 
271  if(offset == DIR_PER_BLOCK){printf("Error in creating directory.\n"); return false;}
272 
274  Directory new_dir, temp;
275  memset(&new_dir,0,sizeof(Directory));
276  new_dir.inum = block_idx*DIR_PER_BLOCK + offset;
277  new_dir.Valid = 1;
278  strcpy(new_dir.Name,name);
279 
281  char tstr1[] = ".", tstr2[] = "..";
282  temp = new_dir;
283  temp = add_dir_entry(temp,temp.inum,0,tstr1);
284  temp = add_dir_entry(temp,curr_dir.inum,0,tstr2);
285  if(temp.Valid == 0){printf("Error creating new directory\n"); return false;}
286  new_dir = temp;
287 
289  temp = add_dir_entry(curr_dir,new_dir.inum,0,new_dir.Name);
290  if(temp.Valid == 0){printf("Error adding new directory\n"); return false;}
291  curr_dir = temp;
292 
294  write_dir_back(new_dir);
295 
297  write_dir_back(curr_dir);
298 
300  dir_counter[block_idx]++;
301 
302  return true;
303 
304 }
305 
312  Directory dir, temp;
313  uint32_t inum, blk_idx, blk_off;
314  Block blk;
315 
317  if(!mounted){dir.Valid = 0; return dir;}
318 
320  int offset = dir_lookup(parent, name);
321  if(offset == -1){dir.Valid = 0; return dir;}
322 
324  inum = parent.Table[offset].inum;
325  blk_idx = inum / DIR_PER_BLOCK;
326  blk_off = inum % DIR_PER_BLOCK;
327  fs_disk->read(MetaData.Blocks - 1 -blk_idx, blk.Data);
328 
330  dir = blk.Directories[blk_off];
331  if(dir.Valid == 0){return dir;}
332 
334  if(streq(dir.Name,curr_dir.Name)){printf("Current Directory cannot be removed.\n"); dir.Valid=0; return dir;}
335 
337  for(uint32_t ii=0; ii<ENTRIES_PER_DIR; ii++){
338  if((ii>1)&&(dir.Table[ii].valid == 1)){
339  temp = rm_helper(dir, dir.Table[ii].Name);
340  if(temp.Valid == 0) return temp;
341  dir = temp;
342  }
343  dir.Table[ii].valid = 0;
344  }
345 
347  fs_disk->read(MetaData.Blocks - 1 -blk_idx, blk.Data);
348 
350  dir.Valid = 0;
351  blk.Directories[blk_off] = dir;
352  fs_disk->write(MetaData.Blocks - 1-blk_idx, blk.Data);
353 
355  parent.Table[offset].valid = 0;
356  write_dir_back(parent);
357 
359  dir_counter[blk_idx]--;
360 
361  return parent;
362 }
363 
364 FileSystem::Directory FileSystem::rm_helper(Directory dir, char name[FileSystem::NAMESIZE]){
369  if(!mounted){dir.Valid = 0; return dir;}
370 
372  int offset = dir_lookup(dir,name);
373  if(offset == -1){printf("No such file/directory\n"); dir.Valid=0; return dir;}
374 
376  if(dir.Table[offset].type == 0){
377  return rmdir_helper(dir,name);
378  }
379 
381  uint32_t inum = dir.Table[offset].inum;
382 
383  printf("%u\n",inum);
384 
386  if(!remove(inum)){printf("Failed to remove Inode\n"); dir.Valid = 0; return dir;}
387 
389  dir.Table[offset].valid = 0;
390 
392  write_dir_back(dir);
393 
394  return dir;
395 }
396 
397 bool FileSystem::rmdir(char name[FileSystem::NAMESIZE]){
402  Directory temp = rmdir_helper(curr_dir,name);
403  if(temp.Valid == 0){
404  curr_dir = temp;
405  return true;
406  }
407  return false;
408 }
409 
410 bool FileSystem::touch(char name[FileSystem::NAMESIZE]){
415  if(!mounted){return false;}
416 
418  for(uint32_t offset=0; offset<FileSystem::ENTRIES_PER_DIR; offset++){
419  if(curr_dir.Table[offset].valid){
420  if(streq(curr_dir.Table[offset].Name,name)){
421  printf("File already exists\n");
422  return false;
423  }
424  }
425  }
427  ssize_t new_node_idx = FileSystem::create();
428  if(new_node_idx == -1){printf("Error creating new inode\n"); return false;}
429 
431  Directory temp = add_dir_entry(curr_dir,new_node_idx,1,name);
432  if(temp.Valid == 0){printf("Error adding new file\n"); return false;}
433  curr_dir = temp;
434 
436  write_dir_back(curr_dir);
437 
438  return true;
439 }
440 
441 bool FileSystem::cd(char name[FileSystem::NAMESIZE]){
446  if(!mounted){return false;}
447 
448  int offset = dir_lookup(curr_dir,name);
449  if((offset == -1) || (curr_dir.Table[offset].type == 1)){
450  printf("No such directory\n");
451  return false;
452  }
453 
455  Directory temp = read_dir_from_offset(offset);
456  if(temp.Valid == 0){return false;}
457  curr_dir = temp;
458  return true;
459 }
460 
462  if(!mounted){return false;}
463 
464  char name[] = ".";
465  return ls_dir(name);
466 }
467 
468 bool FileSystem::rm(char name[]){
469  Directory temp = rm_helper(curr_dir,name);
470  if(temp.Valid == 1){
471  curr_dir = temp;
472  return true;
473  }
474  return false;
475 }
476 
478  if(!mounted){return;}
479 
480  fs_disk->unmount();
481  mounted = false;
482  fs_disk = nullptr;
483 }
484 
485 bool FileSystem::copyout(char name[],const char *path) {
491  if(!mounted){return false;}
492 
494  int offset = dir_lookup(curr_dir,name);
495  if(offset == -1){return false;}
496 
497  if(curr_dir.Table[offset].type == 0){return false;}
498 
499  uint32_t inum = curr_dir.Table[offset].inum;
500 
502  FILE *stream = fopen(path, "w");
503  if (stream == nullptr) {
504  fprintf(stderr, "Unable to open %s: %s\n", path, strerror(errno));
505  return false;
506  }
507 
509  char buffer[4*BUFSIZ] = {0};
510  offset = 0;
511  while (true) {
512  ssize_t result = read(inum, buffer, sizeof(buffer), offset);
513  if (result <= 0) {
514  break;
515  }
516  fwrite(buffer, 1, result, stream);
517  offset += result;
518  }
519 
521  printf("%d bytes copied\n", offset);
522  fclose(stream);
523  return true;
524 }
525 
526 bool FileSystem::copyin(const char *path, char name[]) {
532  if(!mounted){return false;}
533 
535  touch(name);
536  int offset = dir_lookup(curr_dir,name);
537  if(offset == -1){return false;}
538 
539  if(curr_dir.Table[offset].type == 0){return false;}
540 
542  uint32_t inum = curr_dir.Table[offset].inum;
543 
545  FILE *stream = fopen(path, "r");
546  if (stream == nullptr) {
547  fprintf(stderr, "Unable to open %s: %s\n", path, strerror(errno));
548  return false;
549  }
550 
552  char buffer[4*BUFSIZ] = {0};
553  offset = 0;
554  while (true) {
555  ssize_t result = fread(buffer, 1, sizeof(buffer), stream);
556  if (result <= 0) {
557  break;
558  }
559 
561  ssize_t actual = write(inum, buffer, result, offset);
562  if (actual < 0) {
563  fprintf(stderr, "fs.write returned invalid result %ld\n", actual);
564  break;
565  }
566 
568  offset += actual;
569  if (actual != result) {
570  fprintf(stderr, "fs.write only wrote %ld bytes, not %ld bytes\n", actual, result);
571  break;
572  }
573  }
574 
576  printf("%d bytes copied\n", offset);
577  fclose(stream);
578  return true;
579 }
580 
581 // Directory stat ------------------------------------------------------------------
582 
589  if(!mounted){return;}
590 
592  Block blk;
593  fs_disk->read(0,blk.Data);
594  printf("Total Blocks : %u\n",blk.Super.Blocks);
595  printf("Total Directory Blocks : %u\n",blk.Super.DirBlocks);
596  printf("Total Inode Blocks : %u\n",blk.Super.InodeBlocks);
597  printf("Total Inode : %u\n",blk.Super.Inodes);
598  printf("Password protected : %u\n\n",blk.Super.Protected);
599 
600  printf("Max Directories per block : %u\n",DIR_PER_BLOCK);
601  printf("Max Namsize : %u\n",NAMESIZE);
602  printf("Max Inodes per block : %u\n",INODES_PER_BLOCK);
603  printf("Max Entries per directory : %u\n\n",ENTRIES_PER_DIR);
604 
606  for(uint32_t blk_idx=0; blk_idx<MetaData.DirBlocks; blk_idx++){
607  fs_disk->read(MetaData.Blocks - 1- blk_idx,blk.Data);
608  printf("Block %u\n",blk_idx);
609 
611  for(uint32_t offset=0; offset<DIR_PER_BLOCK; offset++){
612  Directory dir = blk.Directories[offset];
613  if(dir.Valid){
614  printf(" Offset %u: Directory Name - \"%s\"\n",offset,dir.Name);
615 
617  for(uint32_t tbl_idx=0; tbl_idx < ENTRIES_PER_DIR; tbl_idx++){
618  Dirent ent = dir.Table[tbl_idx];
619  if(ent.valid){
620  printf(" tbl_idx %u: Entry Name - \"%s\", type - %u, inum - %u\n",tbl_idx,ent.Name,ent.type,ent.inum);
621  }
622  }
623  }
624  }
625  }
626 }
FileSystem::rmdir_helper
Directory rmdir_helper(Directory parent, char name[])
Helper function to remove directory from parent directory.
Definition: fs_layer_2.cpp:306
FileSystem::Directory::Table
Dirent Table[ENTRIES_PER_DIR]
Definition: fs.h:181
FileSystem::rm_helper
Directory rm_helper(Directory parent, char name[])
Helper function to remove file/directory from parent directory.
Definition: fs_layer_2.cpp:364
fs.h
Interface for the FileSystem layer.
FileSystem::create
ssize_t create()
creates a new inode
Definition: fs_layer_1.cpp:291
FileSystem::Directory::inum
uint32_t inum
Definition: fs.h:179
FileSystem::write_dir_back
void write_dir_back(struct Directory dir)
Writes the Directory back to the disk.
Definition: fs_layer_2.cpp:178
FileSystem::ls
bool ls()
List all the curr_dir Dirent.
Definition: fs_layer_2.cpp:461
FileSystem::SuperBlock::Inodes
uint32_t Inodes
Definition: fs.h:153
FileSystem::copyout
bool copyout(char name[], const char *path)
Copies the file in curr_dir to the path provided. Prints amount of bytes copied.
Definition: fs_layer_2.cpp:485
FileSystem::Block::Directories
struct Directory Directories[FileSystem::DIR_PER_BLOCK]
Definition: fs.h:207
FileSystem::SuperBlock::Blocks
uint32_t Blocks
Definition: fs.h:150
FileSystem::Dirent::inum
uint32_t inum
Definition: fs.h:166
FileSystem::Dirent::valid
uint8_t valid
Definition: fs.h:165
FileSystem::Dirent::Name
char Name[NAMESIZE]
Definition: fs.h:167
FileSystem::stat
void stat()
Returns the stat of the disk. The stat contains information like number of directories,...
Definition: fs_layer_2.cpp:583
FileSystem::Block
Block Union Corresponds to one block of disk of size Disk::BLOCKSIZE. Can be used as a SuperBlock,...
Definition: fs.h:202
FileSystem::touch
bool touch(char name[])
Creates a file with size 0. Main function is to allocate an Inode and add Dirent to the curr_dir....
Definition: fs_layer_2.cpp:410
FileSystem::Dirent
Directory Entry. Contains necessary fields to locate the file and directory Consumes 64 KB per object...
Definition: fs.h:163
FileSystem::mkdir
bool mkdir(char name[])
Creates an empty directory with the given name Adds 2 Dirent , '.' and '..' in it's table.
Definition: fs_layer_2.cpp:245
FileSystem::remove_password
bool remove_password()
Removes password from the mounted disk (fs_disk).
Definition: fs_layer_2.cpp:87
FileSystem::Directory::Name
char Name[NAMESIZE]
Definition: fs.h:180
FileSystem::add_dir_entry
Directory add_dir_entry(Directory dir, uint32_t inum, uint32_t type, char name[])
Adds directory entry to the cached curr_dir. dir_write_back should be done by the caller.
Definition: fs_layer_2.cpp:125
FileSystem::cd
bool cd(char name[])
Change curr_dir to the given Directory name.
Definition: fs_layer_2.cpp:441
FileSystem::set_password
bool set_password()
Adds password to the mounted disk (fs_disk). Gives the control to change_password if disk is pasword ...
Definition: fs_layer_2.cpp:27
FileSystem::exit
void exit()
Unmounts the disk and resets pointer.
Definition: fs_layer_2.cpp:477
FileSystem::SuperBlock::DirBlocks
uint32_t DirBlocks
Definition: fs.h:152
FileSystem::copyin
bool copyin(const char *path, char name[])
Copies the file with path provided to the curr_dir. Prints amount of bytes copied....
Definition: fs_layer_2.cpp:526
FileSystem::SuperBlock::InodeBlocks
uint32_t InodeBlocks
Definition: fs.h:151
FileSystem::Directory
Directory Structure. Contains a table of directory entries for storing hierarchy. Also contains field...
Definition: fs.h:177
FileSystem::read_dir_from_offset
Directory read_dir_from_offset(uint32_t offset)
Reads Directory from Dirent offset in curr_dir.
Definition: fs_layer_2.cpp:154
FileSystem::ls_dir
bool ls_dir(char name[])
List the Directory given by the name. Called by ls to print curr_dir. Prints a table of Dirent.
Definition: fs_layer_2.cpp:216
FileSystem::Block::Data
char Data[Disk::BLOCK_SIZE]
Definition: fs.h:206
FileSystem::rm
bool rm(char name[])
Removes the given file/Directory.
Definition: fs_layer_2.cpp:468
FileSystem::dir_lookup
int dir_lookup(Directory dir, char name[])
Finds a valid entry with the same name.
Definition: fs_layer_2.cpp:196
FileSystem::SuperBlock::Protected
uint32_t Protected
Definition: fs.h:154
FileSystem::rmdir
bool rmdir(char name[])
Removes the directory with given name. Also removes all the Dirent in it's table.
Definition: fs_layer_2.cpp:397
FileSystem::change_password
bool change_password()
Changes password in the mounted disk (fs_disk). Checks the current password and gives control to set_...
Definition: fs_layer_2.cpp:57