Advertisement
Guest User

Untitled

a guest
Jan 21st, 2017
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 39.60 KB | None | 0 0
  1. //============================================================================
  2. // Name        : UNIX-FileSystem.cpp
  3. // Author      : Zdravko Chiflishki
  4. // Version     : 1.01030
  5. // Copyright   : Your copyright notice
  6. // Description : Unix File System Implementation
  7. //============================================================================
  8.  
  9. /*
  10. *  Created on: Oct 18, 2016
  11. *      Author: Zdravko Chiflishki
  12. */
  13.  
  14. #include<iostream>
  15. #include<stdio.h>
  16. #include<fcntl.h>
  17. #include<string>
  18. #include<cstring>
  19.  
  20.  
  21. using namespace std;
  22.  
  23. //Constant variables.
  24. const unsigned int NADDR = 16; // The maximum number of blocks a file can use.Used in struct inode
  25. const unsigned int BLOCK_SIZE = 512; // Size of a block
  26. const unsigned int FILE_SIZE_MAX = NADDR * BLOCK_SIZE; //The maximum size of a file
  27. const unsigned int BLOCK_NUM = 512; //The maximum number of data block
  28. const unsigned int INODE_SIZE = 512; //Size of an inode
  29. const unsigned int INODE_NUM = 512; //The maximum number of inodes
  30. /*
  31. *   The start position of inode chain.
  32. *   First four blocks are used for loader sector(empty in this program), super block, inode bitmap and block bitmap.
  33. */
  34. const unsigned int INODE_START = 4 * BLOCK_SIZE;
  35. const unsigned int DATA_START = INODE_START + INODE_NUM * BLOCK_SIZE; //The start position of data blocks
  36. const unsigned int ACCOUNT_NUM = 10; //The maximum number of the file system users
  37. const unsigned int DIRECTORY_NUM = 12; //The maximum number of sub-files and sub-directories in one directory
  38. const unsigned short FILE_NAME_LENGTH = 20; //The maximum length of a file name
  39. const unsigned short USER_NAME_LENGTH = 10;//The maximum length of a user's name
  40. const unsigned short USER_PASSWORD_LENGTH = 8;//The maximum length of user's password
  41.  
  42. //Data structures.
  43.  
  44. struct inode // inode
  45. {
  46.     unsigned int i_ino;         //Identification of the inode.
  47.     unsigned int di_addr[NADDR];//Number of data blocks where the file stored.
  48.     unsigned short di_number;   //Number of associated files.
  49.     unsigned short di_mode;     //0 stands for a directory, 1 stands for a file.
  50.     unsigned short di_uid;      //File's user id.
  51.     unsigned short di_size;     //File size. For directories, the value is 0.
  52. };
  53.  
  54. struct filsys // super block
  55. {
  56.     unsigned short s_num_inode;         //Total number of inodes.
  57.     unsigned short s_num_finode;        //Total number of free inodes.
  58.     unsigned short s_size_inode;        //Size of an inode.
  59.  
  60.     unsigned short s_num_block;         //Total number of blocks.
  61.     unsigned short s_num_fblock;        //Total number of free blocks.
  62.     unsigned short s_size_block;        //Size of a block.
  63. };
  64.  
  65. struct directory // Directory file
  66. {
  67.     char fileName[DIRECTORY_NUM][FILE_NAME_LENGTH];
  68.    
  69.     unsigned int inodeID[DIRECTORY_NUM];
  70. };
  71.  
  72. struct userPsw //Accounting file
  73. {
  74.     unsigned short userID[ACCOUNT_NUM];
  75.     char userName[ACCOUNT_NUM][USER_NAME_LENGTH];
  76.     char password[ACCOUNT_NUM][USER_PASSWORD_LENGTH];
  77. };
  78.  
  79. //Globle varibles.
  80. FILE* fd = NULL; //A descriptor of a file where the file system is emulated.
  81. filsys superBlock; // Super Block
  82. userPsw users; // Accounting information
  83. directory currentDirectory; // Current directory
  84. unsigned short inode_bitmap[INODE_NUM]; // Bitmaps for inode.Element 1 stands for 'used', 0 for 'free'.
  85. unsigned short block_bitmap[BLOCK_NUM]; // Bitmaps for blocks.Element 1 stands for 'used', 0 for 'free'.
  86. unsigned short userID = ACCOUNT_NUM; // current user ID
  87. char userName[USER_NAME_LENGTH + 6]; //current user name used in command line
  88.  
  89.  
  90. /*
  91. *   Formatting function of the file system, including the establishment
  92. *   of superblock, inode chain, root directory, password file and so on.
  93. *
  94. *   return: the function return true only the file system is initialized
  95. *           successfully.
  96. */
  97. bool Format()
  98. {
  99.     /*
  100.     *   1. Create a empty file to emulate the file system.
  101.     */
  102.     FILE* fd = fopen("./UnixFileSystem.dat", "wb+");
  103.     if (fd == NULL)
  104.     {
  105.         printf("Fail to initialize the file system!\n");
  106.         return false;
  107.     }
  108.  
  109.     /*
  110.     *   2. Initialize super block.
  111.     */
  112.     filsys superBlock;
  113.     superBlock.s_num_inode = INODE_NUM;
  114.     superBlock.s_num_block = BLOCK_NUM;
  115.     superBlock.s_size_inode = INODE_SIZE;
  116.     superBlock.s_size_block = BLOCK_SIZE;
  117.     //Root directory and accounting file will use some inodes and blocks.
  118.     superBlock.s_num_fblock = BLOCK_NUM - 2;
  119.     superBlock.s_num_finode = INODE_NUM - 2;
  120.     //Write super block into file.
  121.     fseek(fd, BLOCK_SIZE, SEEK_SET);
  122.     fwrite(&superBlock, sizeof(filsys), 1, fd);
  123.  
  124.     /*
  125.     *   3. Initialize inode and block bitmaps.
  126.     */
  127.     unsigned short inode_bitmap[INODE_NUM];
  128.     unsigned short block_bitmap[BLOCK_NUM];
  129.     //Root directory and accounting file will use some inodes and blocks.
  130.     memset(inode_bitmap, 0, INODE_NUM);
  131.     memset(block_bitmap, 0, BLOCK_NUM);
  132.     inode_bitmap[0] = 1;
  133.     inode_bitmap[1] = 1;
  134.     block_bitmap[0] = 1;
  135.     block_bitmap[1] = 1;
  136.     //Write bitmaps into file.
  137.     fseek(fd, 2 * BLOCK_SIZE, SEEK_SET);
  138.     fwrite(inode_bitmap, sizeof(unsigned short) * INODE_NUM, 1, fd);
  139.     fseek(fd, 3 * BLOCK_SIZE, SEEK_SET);
  140.     fwrite(block_bitmap, sizeof(unsigned short) * BLOCK_NUM, 1, fd);
  141.  
  142.     /*
  143.     *   4. Create root directory.
  144.     */
  145.     //Create inode
  146.  
  147.  
  148.     //Now root directory contain 1 accounting file.
  149.     inode iroot_tmp;
  150.     iroot_tmp.i_ino = 0;                    //Identification
  151.     iroot_tmp.di_number = 2;                //Associations: itself and accouting file
  152.     iroot_tmp.di_mode = 0;                  //0 stands for directory
  153.     iroot_tmp.di_size = 0;                  //"For directories, the value is 0."
  154.     memset(iroot_tmp.di_addr, 0xFF, sizeof(unsigned int) * NADDR);
  155.     iroot_tmp.di_addr[0] = 0;               //Root directory is stored on 1st block. FFFFFF means empty.
  156.     iroot_tmp.di_uid = 0;                   //Root user id.
  157.     fseek(fd, INODE_START, SEEK_SET);
  158.     fwrite(&iroot_tmp, sizeof(inode), 1, fd);
  159.  
  160.     //Create directory file.
  161.     directory droot_tmp;
  162.     memset(droot_tmp.fileName, 0, sizeof(char) * DIRECTORY_NUM * FILE_NAME_LENGTH);
  163.     memset(droot_tmp.inodeID, 0xFF, sizeof(unsigned int) * DIRECTORY_NUM);
  164.     strcpy(droot_tmp.fileName[0], ".");
  165.     droot_tmp.inodeID[0] = 0;
  166.     strcpy(droot_tmp.fileName[1], "..");
  167.     droot_tmp.inodeID[1] = 0;
  168.     //A sub directory for accounting files
  169.     strcpy(droot_tmp.fileName[2], "psw");
  170.     droot_tmp.inodeID[2] = 1;
  171.     //Write
  172.     fseek(fd, DATA_START, SEEK_SET);
  173.     fwrite(&droot_tmp, sizeof(directory), 1, fd);
  174.  
  175.     /*
  176.     *   5. Create accouting file.
  177.     */
  178.     //Create inode
  179.     inode iaccouting_tmp;
  180.     iaccouting_tmp.i_ino = 1;                   //Identification
  181.     iaccouting_tmp.di_number = 1;               //Associations
  182.     iaccouting_tmp.di_mode = 1;                 //1 stands for file
  183.     iaccouting_tmp.di_size = sizeof(userPsw);   //File size
  184.     memset(iaccouting_tmp.di_addr, 0xFF, sizeof(unsigned int) * NADDR);
  185.     iaccouting_tmp.di_addr[0] = 1;              //Root directory is stored on 1st block.
  186.     iaccouting_tmp.di_uid = 0;                  //Root user id.
  187.     fseek(fd, INODE_START + BLOCK_SIZE, SEEK_SET);
  188.     fwrite(&iaccouting_tmp, sizeof(inode), 1, fd);
  189.  
  190.     //Create accouting file.
  191.     userPsw paccouting_tmp;
  192.     memset(paccouting_tmp.userName, 0, sizeof(char) * USER_NAME_LENGTH * ACCOUNT_NUM);
  193.     memset(paccouting_tmp.password, 0, sizeof(char) * USER_PASSWORD_LENGTH * ACCOUNT_NUM);
  194.    
  195.     strcpy(paccouting_tmp.userName[0], "admin");
  196.     strcpy(paccouting_tmp.password[0], "admin");
  197.     //0 stands for super user. Other IDs are only used to identify users.
  198.     for (unsigned short i = 0; i < ACCOUNT_NUM; i++)
  199.     {
  200.         paccouting_tmp.userID[i] = i;
  201.     }
  202.     //Write
  203.     fseek(fd, DATA_START + BLOCK_SIZE, SEEK_SET);
  204.     fwrite(&paccouting_tmp, sizeof(userPsw), 1, fd);
  205.     /*
  206.     userPsw zaccouting_tmp;
  207.     memset(zaccouting_tmp.userName, 0, sizeof(char) * USER_NAME_LENGTH * ACCOUNT_NUM);
  208.     memset(zaccouting_tmp.password, 0, sizeof(char) * USER_PASSWORD_LENGTH * ACCOUNT_NUM);
  209.  
  210.     strcpy(zaccouting_tmp.userName[0], "zdravko");
  211.     strcpy(zaccouting_tmp.password[0], "chiflishki");
  212.     for (unsigned short i = 0; i < ACCOUNT_NUM; i++)
  213.     {
  214.         zaccouting_tmp.userID[i] = i;
  215.     }
  216.  
  217.     fseek(fd, DATA_START + BLOCK_SIZE, SEEK_SET);
  218.     fwrite(&zaccouting_tmp, sizeof(userPsw), 1, fd);
  219.     */
  220.     //Close file.
  221.     fclose(fd);
  222.  
  223.     return true;
  224. };
  225.  
  226. /*
  227. *   Initialization function of the file system. Open an existing file system
  228. *   from 'UnixFileSystem.dat'.
  229. *
  230. *   return: the function return true only when the file system has been
  231. *           formatted and is complete.
  232. */
  233. bool Mount()
  234. {
  235.     /*
  236.     *   1. Open the emulation file where the file system is installed.
  237.     */
  238.     fd = fopen("./UnixFileSystem.dat", "rb+");
  239.     if (fd == NULL)
  240.     {
  241.         printf("Error: File system not found!\n");
  242.         return false;
  243.     }
  244.  
  245.     /*
  246.     *   2. Read superblock, bitmaps, accouting file, current directory (root)
  247.     */
  248.     //Read superblock
  249.     fseek(fd, BLOCK_SIZE, SEEK_SET);
  250.     fread(&superBlock, sizeof(superBlock), 1, fd);
  251.  
  252.     //Read inode bitmap
  253.     fseek(fd, 2 * BLOCK_SIZE, SEEK_SET);
  254.     fread(inode_bitmap, sizeof(unsigned short) * INODE_NUM, 1, fd);
  255.     //Read block bitmap
  256.     fseek(fd, 3 * BLOCK_SIZE, SEEK_SET);
  257.     fread(block_bitmap, sizeof(unsigned short) * BLOCK_NUM, 1, fd);
  258.  
  259.     //Read current directory, namely root directory
  260.     fseek(fd, DATA_START, SEEK_SET);
  261.     fread(&currentDirectory, sizeof(directory), 1, fd);
  262.  
  263.     //Read accouting file
  264.     fseek(fd, DATA_START + BLOCK_SIZE, SEEK_SET);
  265.     fread(&users, sizeof(userPsw), 1, fd);
  266.  
  267.     return true;
  268. };
  269.  
  270. /*
  271. *   Log in function. Update user information by checking log in inputs.
  272. *
  273. *   return: the function return true only when log in process succeed.
  274. */
  275. bool Login(const char* user, const char* password)
  276. {
  277.     //parameters check
  278.     if (user == NULL || password == NULL)
  279.     {
  280.         printf("Error: User name or password illegal!\n");
  281.         return false;
  282.     }
  283.     if (strlen(user) > USER_NAME_LENGTH || strlen(password) > USER_PASSWORD_LENGTH)
  284.     {
  285.         printf("Error: User name or password illegal!\n");
  286.         return false;
  287.     }
  288.  
  289.     //have logged in?
  290.     if (userID != ACCOUNT_NUM)
  291.     {
  292.         printf("Login failed: User has been logged in. Please log out first.\n");
  293.         return false;
  294.     }
  295.  
  296.     //search the user in accouting file
  297.     for (int i = 0; i < ACCOUNT_NUM; i++)
  298.     {
  299.         if (strcmp(users.userName[i], user) == 0)
  300.         {
  301.             //find the user and check password
  302.             if (strcmp(users.password[i], password) == 0)
  303.             {
  304.                 //Login successfully
  305.                 printf("Login successfully.\n");
  306.                 userID = users.userID[i];
  307.                 //make user's name, root user is special
  308.                 memset(userName, 0, USER_NAME_LENGTH + 6);
  309.                 if (userID == 0)
  310.                 {
  311.                     strcat(userName, "root<");
  312.                     strcat(userName, users.userName[i]);
  313.                     strcat(userName, "@");
  314.                 }
  315.                 else
  316.                 {
  317.                     strcat(userName, users.userName[i]);
  318.                     strcat(userName, "#");
  319.                 }
  320.  
  321.                 return true;
  322.             }
  323.             else
  324.             {
  325.                 //Password wrong
  326.                 printf("Login failed: Wrong password.\n");
  327.                 return false;
  328.             }
  329.         }
  330.     }
  331.  
  332.     //User not found
  333.     printf("Login failed: User not found.\n");
  334.     return false;
  335.  
  336. };
  337.  
  338. /*
  339. *   Log out function. Remove user's states.
  340. */
  341. void Logout()
  342. {
  343.     //remove user's states
  344.     userID = ACCOUNT_NUM;
  345.     memset(&users, 0, sizeof(users));
  346.     memset(userName, 0, 6 + USER_NAME_LENGTH);
  347. };
  348.  
  349. /*
  350. *   Create a new empty file with the specific file name.
  351. *
  352. *   return: the function return true only when the new file is successfully
  353. *           created.
  354. */
  355. bool CreateFile(const char* filename)
  356. {
  357.     //parameter check
  358.     if (filename == NULL || strlen(filename) > FILE_NAME_LENGTH)
  359.     {
  360.         printf("Error: Illegal file name.\n");
  361.         return false;
  362.     }
  363.  
  364.     /*
  365.     *   1. Check whether free inodes and blocks are used up.
  366.     */
  367.     if (superBlock.s_num_fblock <= 0 || superBlock.s_num_finode <= 0)
  368.     {
  369.         printf("File creation error: No valid spaces.\n");
  370.         return false;
  371.     }
  372.     //Find new inode number and new block address
  373.     int new_ino = 0;
  374.     int new_block_addr = 0;
  375.     for (; new_ino < INODE_NUM; new_ino++)
  376.     {
  377.         if (inode_bitmap[new_ino] == 0)
  378.         {
  379.             break;
  380.         }
  381.     }
  382.     for (; new_block_addr < BLOCK_NUM; new_block_addr++)
  383.     {
  384.         if (block_bitmap[new_block_addr] == 0)
  385.         {
  386.             break;
  387.         }
  388.     }
  389.     if (new_ino == INODE_NUM || new_block_addr == BLOCK_NUM)
  390.     {
  391.         printf("File creation error: No valid spaces.\n");
  392.         return false;
  393.     }
  394.  
  395.     /*
  396.     *   2. Check whether file name has been used in current directory.
  397.     */
  398.     for (int i = 0; i < DIRECTORY_NUM; i++)
  399.     {
  400.         if (strcmp(currentDirectory.fileName[i], filename) == 0)
  401.         {
  402.             printf("File creation error: File name '%s' has been used.\n", currentDirectory.fileName[i]);
  403.             return false;
  404.         }
  405.     }
  406.  
  407.     /*
  408.     *   3. Check whether current directory contains too many items already.
  409.     */
  410.     int itemCounter = 0;
  411.     for (int i = 0; i < DIRECTORY_NUM; i++)
  412.     {
  413.         if (strlen(currentDirectory.fileName[i]) > 0)
  414.         {
  415.             itemCounter++;
  416.         }
  417.     }
  418.     if (itemCounter >= DIRECTORY_NUM)
  419.     {
  420.         printf("File creation error: Too many files or directories in current path.\n");
  421.         return false;
  422.     }
  423.  
  424.     /*
  425.     *   4. Create new inode.
  426.     */
  427.     //Create inode
  428.     inode ifile_tmp;
  429.     ifile_tmp.i_ino = new_ino;              //Identification
  430.     ifile_tmp.di_number = 1;                //Associations
  431.     ifile_tmp.di_mode = 1;                  //1 stands for file
  432.     ifile_tmp.di_size = 0;                  //New file is empty
  433.     memset(ifile_tmp.di_addr, 0xFF, sizeof(unsigned int) * NADDR);
  434.     ifile_tmp.di_addr[0] = new_block_addr;  //0xFFFFFF means empty.
  435.     ifile_tmp.di_uid = userID;              //Current user id.
  436.     fseek(fd, INODE_START + new_ino * BLOCK_SIZE, SEEK_SET);
  437.     fwrite(&ifile_tmp, sizeof(inode), 1, fd);
  438.  
  439.     /*
  440.     *   5.  Update bitmaps.
  441.     */
  442.     //Update bitmaps
  443.     inode_bitmap[new_ino] = 1;
  444.     fseek(fd, 2 * BLOCK_SIZE, SEEK_SET);
  445.     fwrite(inode_bitmap, sizeof(unsigned short) * INODE_NUM, 1, fd);
  446.     block_bitmap[new_block_addr] = 1;
  447.     fseek(fd, 3 * BLOCK_SIZE, SEEK_SET);
  448.     fwrite(block_bitmap, sizeof(unsigned short) * BLOCK_NUM, 1, fd);
  449.  
  450.     /*
  451.     *   6. Update directory.
  452.     */
  453.     //Fetch current directory's inode
  454.     //Inode position of current directory
  455.     int pos_directory_inode = 0;
  456.     pos_directory_inode = currentDirectory.inodeID[0]; //"."
  457.     inode tmp_directory_inode;
  458.     fseek(fd, INODE_START + pos_directory_inode * BLOCK_SIZE, SEEK_SET);
  459.     fread(&tmp_directory_inode, sizeof(inode), 1, fd);
  460.  
  461.     //Add to current directory item
  462.     for (int i = 2; i < DIRECTORY_NUM; i++)
  463.     {
  464.         if (strlen(currentDirectory.fileName[i]) == 0)
  465.         {
  466.             strcat(currentDirectory.fileName[i], filename);
  467.             currentDirectory.inodeID[i] = new_ino;
  468.             break;
  469.         }
  470.     }
  471.     //write
  472.     fseek(fd, DATA_START + tmp_directory_inode.di_addr[0] * BLOCK_SIZE, SEEK_SET);
  473.     fwrite(&currentDirectory, sizeof(directory), 1, fd);
  474.  
  475.     //Update associations
  476.     directory tmp_directory = currentDirectory;
  477.     int tmp_pos_directory_inode = pos_directory_inode;
  478.     while (true)
  479.     {
  480.         //Update association
  481.         tmp_directory_inode.di_number++;
  482.         fseek(fd, INODE_START + tmp_pos_directory_inode * BLOCK_SIZE, SEEK_SET);
  483.         fwrite(&tmp_directory_inode, sizeof(inode), 1, fd);
  484.         //If reach the root directory, finish updating.
  485.         if (tmp_directory.inodeID[1] == tmp_directory.inodeID[0])
  486.         {
  487.             break;
  488.         }
  489.         //Fetch father directory
  490.         tmp_pos_directory_inode = tmp_directory.inodeID[1];     //".."
  491.         fseek(fd, INODE_START + tmp_pos_directory_inode * BLOCK_SIZE, SEEK_SET);
  492.         fread(&tmp_directory_inode, sizeof(inode), 1, fd);
  493.         fseek(fd, DATA_START + tmp_directory_inode.di_addr[0] * BLOCK_SIZE, SEEK_SET);
  494.         fread(&tmp_directory, sizeof(directory), 1, fd);
  495.     }
  496.  
  497.     /*
  498.     *   7. Update super block.
  499.     */
  500.     superBlock.s_num_fblock--;
  501.     superBlock.s_num_finode--;
  502.     fseek(fd, BLOCK_SIZE, SEEK_SET);
  503.     fwrite(&superBlock, sizeof(filsys), 1, fd);
  504.  
  505.     return true;
  506. };
  507.  
  508. /*
  509. *   Delete a file.
  510. *
  511. *   return: the function returns true only delete the file successfully.
  512. */
  513. bool DeleteFile(const char* filename)
  514. {
  515.     //parameter check
  516.     if (filename == NULL || strlen(filename) > FILE_NAME_LENGTH)
  517.     {
  518.         printf("Error: Illegal file name.\n");
  519.         return false;
  520.     }
  521.  
  522.     /*
  523.     *   1. Check whether the file exists in current directory.
  524.     */
  525.     int pos_in_directory = 0;
  526. FILE_NAME_RE_SEARCH:
  527.     for (; pos_in_directory < DIRECTORY_NUM; pos_in_directory++)
  528.     {
  529.         if (strcmp(currentDirectory.fileName[pos_in_directory], filename) == 0)
  530.         {
  531.             break;
  532.         }
  533.     }
  534.     if (pos_in_directory == DIRECTORY_NUM)
  535.     {
  536.         printf("Delete error: File not found.\n");
  537.         return false;
  538.     }
  539.  
  540.     /*
  541.     *   2. Fetch inode and check whether it's a directory.
  542.     */
  543.     //Fetch inode
  544.     int tmp_file_ino = currentDirectory.inodeID[pos_in_directory];
  545.     inode tmp_file_inode;
  546.     fseek(fd, INODE_START + tmp_file_ino * BLOCK_SIZE, SEEK_SET);
  547.     fread(&tmp_file_inode, sizeof(inode), 1, fd);
  548.     //Directory check
  549.     if (tmp_file_inode.di_mode == 0)
  550.     {
  551.         //is a directory, roll back and continue to search the file
  552.         goto FILE_NAME_RE_SEARCH;
  553.     }
  554.  
  555.     //Access check
  556.     if (userID != 0 && userID != tmp_file_inode.di_uid)
  557.     {
  558.         printf("Delete error: Access deny.\n");
  559.         return -1;
  560.     }
  561.  
  562.     /*
  563.     *   3. Start deleting. Fill the inode's original space with 0s.
  564.     */
  565.     //Fill original space
  566.     int tmp_fill[sizeof(inode)];
  567.     memset(tmp_fill, 0, sizeof(inode));
  568.     fseek(fd, INODE_START + tmp_file_ino * BLOCK_SIZE, SEEK_SET);
  569.     fwrite(&tmp_fill, sizeof(inode), 1, fd);
  570.  
  571.     /*
  572.     *   4. Update bitmaps
  573.     */
  574.     //inode bitmap
  575.     inode_bitmap[tmp_file_ino] = 0;
  576.     fseek(fd, 2 * BLOCK_SIZE, SEEK_SET);
  577.     fwrite(&inode_bitmap, sizeof(unsigned short) * INODE_NUM, 1, fd);
  578.     //block bitmap
  579.     for (int i = 0; i < (tmp_file_inode.di_size / BLOCK_SIZE + 1); i++)
  580.     {
  581.         block_bitmap[tmp_file_ino + i] = 0;
  582.     }
  583.     fseek(fd, 3 * BLOCK_SIZE, SEEK_SET);
  584.     fwrite(&block_bitmap, sizeof(unsigned short) * BLOCK_NUM, 1, fd);
  585.  
  586.     /*
  587.     *   5. Update directories
  588.     */
  589.     //Fetch current directory inode
  590.     int pos_directory_inode = currentDirectory.inodeID[0];  //"."
  591.     inode tmp_directory_inode;
  592.     fseek(fd, INODE_START + pos_directory_inode * BLOCK_SIZE, SEEK_SET);
  593.     fread(&tmp_directory_inode, sizeof(inode), 1, fd);
  594.  
  595.     //Update current directory item
  596.     memset(currentDirectory.fileName[pos_in_directory], 0, FILE_NAME_LENGTH);
  597.     currentDirectory.inodeID[pos_in_directory] = 0xFFFFFFFF;
  598.     fseek(fd, DATA_START + tmp_directory_inode.di_addr[0] * BLOCK_SIZE, SEEK_SET);
  599.     fwrite(&currentDirectory, sizeof(directory), 1, fd);
  600.  
  601.     //Update associations
  602.     directory tmp_directory = currentDirectory;
  603.     int tmp_pos_directory_inode = pos_directory_inode;
  604.     while (true)
  605.     {
  606.         //Update association
  607.         tmp_directory_inode.di_number--;
  608.         fseek(fd, INODE_START + tmp_pos_directory_inode * BLOCK_SIZE, SEEK_SET);
  609.         fwrite(&tmp_directory_inode, sizeof(inode), 1, fd);
  610.         //If reach the root directory, finish updating.
  611.         if (tmp_directory.inodeID[1] == tmp_directory.inodeID[0])
  612.         {
  613.             break;
  614.         }
  615.         //Fetch father directory
  616.         tmp_pos_directory_inode = tmp_directory.inodeID[1];     //".."
  617.         fseek(fd, INODE_START + tmp_pos_directory_inode * BLOCK_SIZE, SEEK_SET);
  618.         fread(&tmp_directory_inode, sizeof(inode), 1, fd);
  619.         fseek(fd, DATA_START + tmp_directory_inode.di_addr[0] * BLOCK_SIZE, SEEK_SET);
  620.         fread(&tmp_directory, sizeof(directory), 1, fd);
  621.     }
  622.  
  623.     /*
  624.     *   6. Update super block
  625.     */
  626.     superBlock.s_num_fblock += tmp_file_inode.di_size / BLOCK_SIZE + 1;
  627.     superBlock.s_num_finode++;
  628.     fseek(fd, BLOCK_SIZE, SEEK_SET);
  629.     fwrite(&superBlock, sizeof(filsys), 1, fd);
  630.  
  631.     return true;
  632. }
  633.  
  634. /*
  635. *   Open the specific file under current directory.
  636. *
  637. *   return: the function returns a pointer of the file's inode if the file is
  638. *           successfully opened and NULL otherwise.
  639. */
  640. inode* OpenFile(const char* filename)
  641. {
  642.     //parameter check
  643.     if (filename == NULL || strlen(filename) > FILE_NAME_LENGTH)
  644.     {
  645.         printf("Error: Illegal file name.\n");
  646.         return NULL;
  647.     }
  648.  
  649.     /*
  650.     *   1. Check whether the file exists in current directory.
  651.     */
  652.     int pos_in_directory = 0;
  653. FILE_NAME_RE_RESEARCH:
  654.     for (; pos_in_directory < DIRECTORY_NUM; pos_in_directory++)
  655.     {
  656.         if (strcmp(currentDirectory.fileName[pos_in_directory], filename) == 0)
  657.         {
  658.             break;
  659.         }
  660.     }
  661.     if (pos_in_directory == DIRECTORY_NUM)
  662.     {
  663.         printf("Open file error: File not found.\n");
  664.         return NULL;
  665.     }
  666.  
  667.     /*
  668.     *   2. Fetch inode and check whether it's a directory.
  669.     */
  670.     //Fetch inode
  671.     int tmp_file_ino = currentDirectory.inodeID[pos_in_directory];
  672.     inode* tmp_file_inode = new inode;
  673.     fseek(fd, INODE_START + tmp_file_ino * BLOCK_SIZE, SEEK_SET);
  674.     fread(tmp_file_inode, sizeof(inode), 1, fd);
  675.     //Directory check
  676.     if (tmp_file_inode->di_mode == 0)
  677.     {
  678.         //is a directory, roll back and continue to search the file
  679.         goto FILE_NAME_RE_RESEARCH;
  680.     }
  681.  
  682.     return tmp_file_inode;
  683. };
  684.  
  685. /*
  686. *   Append a string "content" to the specific file.
  687. *
  688. *   return: the function returns the number of bytes it has writen or -1 when
  689. *           some error occur.
  690. */
  691. int Write(inode& ifile, const char* content)
  692. {
  693.     //parameter check
  694.     if (content == NULL)
  695.     {
  696.         printf("Error: Illegal file name.\n");
  697.         return -1;
  698.     }
  699.     //Access check
  700.     if (userID != 0 && userID != ifile.di_uid)
  701.     {
  702.         printf("Write error: Access deny.\n");
  703.         return -1;
  704.     }
  705.  
  706.     /*
  707.     *   1. Check whether the expected file will be out of length.
  708.     */
  709.     int len_content = strlen(content);
  710.     unsigned int new_file_length = len_content + ifile.di_size;
  711.     if (new_file_length >= FILE_SIZE_MAX)
  712.     {
  713.         printf("Write error: File over length.\n");
  714.         return -1;
  715.     }
  716.  
  717.     /*
  718.     *   2. Get the number of needed blocks and check is there any enough free spaces.
  719.     */
  720.     //Get the number of needed blocks
  721.     int free_space_firstBlock = BLOCK_SIZE - ifile.di_size % BLOCK_SIZE;
  722.     unsigned int num_block_needed;
  723.     if (len_content - free_space_firstBlock > 0)
  724.     {
  725.         num_block_needed = (len_content - free_space_firstBlock) / BLOCK_SIZE + 1;
  726.     }
  727.     else
  728.     {
  729.         num_block_needed = 0;
  730.     }
  731.     //Check is there any enough free spaces
  732.     if (num_block_needed > superBlock.s_num_fblock)
  733.     {
  734.         printf("Write error: No enough space available.\n");
  735.         return -1;
  736.     }
  737.  
  738.     /*
  739.     *   3. Write first block.
  740.     */
  741.     fseek(fd, DATA_START + ifile.di_addr[0] * BLOCK_SIZE + ifile.di_size % BLOCK_SIZE, SEEK_SET);
  742.     if (num_block_needed == 0)
  743.     {
  744.         fwrite(content, len_content, 1, fd);
  745.         ifile.di_size += len_content;
  746.     }
  747.     else
  748.     {
  749.         fwrite(content, free_space_firstBlock, 1, fd);
  750.         ifile.di_size += free_space_firstBlock;
  751.     }
  752.  
  753.     /*
  754.     *   4. Write the other blocks. Update file information in inode and block bitmap in the meanwhile.
  755.     */
  756.     char write_buf[BLOCK_SIZE];
  757.     int new_block_addr = 0;
  758.     unsigned int content_write_pos = free_space_firstBlock;
  759.     //Loop and write each blocks
  760.     for (int i = 0; i < num_block_needed; i++)
  761.     {
  762.         memset(write_buf, 0, BLOCK_SIZE);
  763.         //Find a new empty block
  764.         for (new_block_addr = 0; new_block_addr < BLOCK_NUM; new_block_addr++)
  765.         {
  766.             if (block_bitmap[new_block_addr] == 0)
  767.             {
  768.                 block_bitmap[new_block_addr] = 1;
  769.                 break;
  770.             }
  771.         }
  772.         //Copy from content to write buffer
  773.         unsigned int tmp_counter = 0;
  774.         for (; tmp_counter < BLOCK_SIZE; tmp_counter++)
  775.         {
  776.             if (content[content_write_pos + tmp_counter] == '\0')
  777.                 break;
  778.             write_buf[tmp_counter] = content[content_write_pos + tmp_counter];
  779.         }
  780.         content_write_pos += tmp_counter;
  781.         //Write
  782.         fseek(fd, DATA_START + new_block_addr * BLOCK_SIZE, SEEK_SET);
  783.         fwrite(write_buf, tmp_counter, 1, fd);
  784.  
  785.         //Update inode information: blocks address and file size
  786.         ifile.di_size += tmp_counter;
  787.         for (int j = 0; j < NADDR; j++)
  788.         {
  789.             if (ifile.di_addr[j] == 0xFFFFFFFF)
  790.             {
  791.                 ifile.di_addr[j] = new_block_addr;
  792.                 break;
  793.             }
  794.         }
  795.     }
  796.     //Write inode
  797.     fseek(fd, INODE_START + ifile.i_ino * BLOCK_SIZE, SEEK_SET);
  798.     fwrite(&ifile, sizeof(inode), 1, fd);
  799.     //Write block bitmap
  800.     fseek(fd, 3 * BLOCK_SIZE, SEEK_SET);
  801.     fwrite(block_bitmap, sizeof(unsigned short) * BLOCK_SIZE, 1, fd);
  802.  
  803.     /*
  804.     *   5. Update super block.
  805.     */
  806.     superBlock.s_num_fblock -= num_block_needed;
  807.     fseek(fd, BLOCK_SIZE, SEEK_SET);
  808.     fwrite(&superBlock, sizeof(superBlock), 1, fd);
  809.  
  810.     return len_content;
  811. };
  812.  
  813. /*
  814. *   Create a new drirectory only with "." and ".." items.
  815. *
  816. *   return: the function returns true only when the new directory is
  817. *           created successfully.
  818. */
  819. bool MakeDir(const char* dirname)
  820. {
  821.     //parameter check
  822.     if (dirname == NULL || strlen(dirname) > FILE_NAME_LENGTH)
  823.     {
  824.         printf("Error: Illegal directory name.\n");
  825.         return false;
  826.     }
  827.  
  828.     /*
  829.     *   1. Check whether free inodes and blocks are used up.
  830.     */
  831.     if (superBlock.s_num_fblock <= 0 || superBlock.s_num_finode <= 0)
  832.     {
  833.         printf("File creation error: No valid spaces.\n");
  834.         return false;
  835.     }
  836.     //Find new inode number and new block address
  837.     int new_ino = 0;
  838.     int new_block_addr = 0;
  839.     for (; new_ino < INODE_NUM; new_ino++)
  840.     {
  841.         if (inode_bitmap[new_ino] == 0)
  842.         {
  843.             break;
  844.         }
  845.     }
  846.     for (; new_block_addr < BLOCK_NUM; new_block_addr++)
  847.     {
  848.         if (block_bitmap[new_block_addr] == 0)
  849.         {
  850.             break;
  851.         }
  852.     }
  853.     if (new_ino == INODE_NUM || new_block_addr == BLOCK_NUM)
  854.     {
  855.         printf("File creation error: No valid spaces.\n");
  856.         return false;
  857.     }
  858.  
  859.     /*
  860.     *   2. Check whether directory name has been used in current directory.
  861.     */
  862.     for (int i = 0; i < DIRECTORY_NUM; i++)
  863.     {
  864.         if (strcmp(currentDirectory.fileName[i], dirname) == 0)
  865.         {
  866.             printf("File creation error: Directory name '%s' has been used.\n", currentDirectory.fileName[i]);
  867.             return false;
  868.         }
  869.     }
  870.  
  871.     /*
  872.     *   3. Check whether current directory contains too many items already.
  873.     */
  874.     int itemCounter = 0;
  875.     for (int i = 0; i < DIRECTORY_NUM; i++)
  876.     {
  877.         if (strlen(currentDirectory.fileName[i]) > 0)
  878.         {
  879.             itemCounter++;
  880.         }
  881.     }
  882.     if (itemCounter >= DIRECTORY_NUM)
  883.     {
  884.         printf("File creation error: Too many files or directories in current path.\n");
  885.         return false;
  886.     }
  887.  
  888.     /*
  889.     *   4. Create new inode.
  890.     */
  891.     //Create inode
  892.     inode idir_tmp;
  893.     idir_tmp.i_ino = new_ino;               //Identification
  894.     idir_tmp.di_number = 1;                 //Associations
  895.     idir_tmp.di_mode = 0;                   //0 stands for directory
  896.     idir_tmp.di_size = sizeof(directory);   //"For directories, the value is 0."
  897.     memset(idir_tmp.di_addr, 0xFF, sizeof(unsigned int) * NADDR);
  898.     idir_tmp.di_addr[0] = new_block_addr;   //0xFFFFFF means empty.
  899.     idir_tmp.di_uid = userID;               //Current user id.
  900.     fseek(fd, INODE_START + new_ino * BLOCK_SIZE, SEEK_SET);
  901.     fwrite(&idir_tmp, sizeof(inode), 1, fd);
  902.  
  903.     /*
  904.     *   5. Create directory file.
  905.     */
  906.     directory tmp_dir;
  907.     memset(tmp_dir.fileName, 0, sizeof(char) * DIRECTORY_NUM * FILE_NAME_LENGTH);
  908.     memset(tmp_dir.inodeID, 0xFF, sizeof(unsigned int) * DIRECTORY_NUM);
  909.     strcpy(tmp_dir.fileName[0], ".");
  910.     tmp_dir.inodeID[0] = new_ino;
  911.     strcpy(tmp_dir.fileName[1], "..");
  912.     tmp_dir.inodeID[1] = currentDirectory.inodeID[0];
  913.     fseek(fd, DATA_START + new_block_addr * BLOCK_SIZE, SEEK_SET);
  914.     fwrite(&tmp_dir, sizeof(directory), 1, fd);
  915.  
  916.     /*
  917.     *   6.  Update bitmaps.
  918.     */
  919.     //Update bitmaps
  920.     inode_bitmap[new_ino] = 1;
  921.     fseek(fd, 2 * BLOCK_SIZE, SEEK_SET);
  922.     fwrite(inode_bitmap, sizeof(unsigned short) * INODE_NUM, 1, fd);
  923.     block_bitmap[new_block_addr] = 1;
  924.     fseek(fd, 3 * BLOCK_SIZE, SEEK_SET);
  925.     fwrite(block_bitmap, sizeof(unsigned short) * BLOCK_NUM, 1, fd);
  926.  
  927.     /*
  928.     *   7. Update directory.
  929.     */
  930.     //Fetch current directory's inode
  931.     //Inode position of current directory
  932.     int pos_directory_inode = 0;
  933.     pos_directory_inode = currentDirectory.inodeID[0]; //"."
  934.     inode tmp_directory_inode;
  935.     fseek(fd, INODE_START + pos_directory_inode * BLOCK_SIZE, SEEK_SET);
  936.     fread(&tmp_directory_inode, sizeof(inode), 1, fd);
  937.  
  938.     //Add to current directory item
  939.     for (int i = 2; i < DIRECTORY_NUM; i++)
  940.     {
  941.         if (strlen(currentDirectory.fileName[i]) == 0)
  942.         {
  943.             strcat(currentDirectory.fileName[i], dirname);
  944.             currentDirectory.inodeID[i] = new_ino;
  945.             break;
  946.         }
  947.     }
  948.     //write
  949.     fseek(fd, DATA_START + tmp_directory_inode.di_addr[0] * BLOCK_SIZE, SEEK_SET);
  950.     fwrite(&currentDirectory, sizeof(directory), 1, fd);
  951.  
  952.     //Update associations
  953.     directory tmp_directory = currentDirectory;
  954.     int tmp_pos_directory_inode = pos_directory_inode;
  955.     while (true)
  956.     {
  957.         //Update association
  958.         tmp_directory_inode.di_number++;
  959.         fseek(fd, INODE_START + tmp_pos_directory_inode * BLOCK_SIZE, SEEK_SET);
  960.         fwrite(&tmp_directory_inode, sizeof(inode), 1, fd);
  961.         //If reach the root directory, finish updating.
  962.         if (tmp_directory.inodeID[1] == tmp_directory.inodeID[0])
  963.         {
  964.             break;
  965.         }
  966.         //Fetch father directory
  967.         tmp_pos_directory_inode = tmp_directory.inodeID[1];     //".."
  968.         fseek(fd, INODE_START + tmp_pos_directory_inode * BLOCK_SIZE, SEEK_SET);
  969.         fread(&tmp_directory_inode, sizeof(inode), 1, fd);
  970.         fseek(fd, DATA_START + tmp_directory_inode.di_addr[0] * BLOCK_SIZE, SEEK_SET);
  971.         fread(&tmp_directory, sizeof(directory), 1, fd);
  972.     }
  973.  
  974.     /*
  975.     *   8. Update super block.
  976.     */
  977.     superBlock.s_num_fblock--;
  978.     superBlock.s_num_finode--;
  979.     fseek(fd, BLOCK_SIZE, SEEK_SET);
  980.     fwrite(&superBlock, sizeof(filsys), 1, fd);
  981.  
  982.     return true;
  983. };
  984.  
  985. /*
  986. *   Delete a drirectory as well as all files and sub-directories in it.
  987. *
  988. *   return: the function returns true only when the directory as well
  989. *           as all files and sub-directories in it is deleted successfully.
  990. */
  991. bool RemoveDir(const char* dirname)
  992. {
  993.     //parameter check
  994.     if (dirname == NULL || strlen(dirname) > FILE_NAME_LENGTH)
  995.     {
  996.         printf("Error: Illegal directory name.\n");
  997.         return false;
  998.     }
  999.  
  1000.     /*
  1001.     *   1. Check whether the directory exists in current directory.
  1002.     */
  1003.     int pos_in_directory = 0;
  1004. DIR_NAME_RE_SEARCH:
  1005.     for (; pos_in_directory < DIRECTORY_NUM; pos_in_directory++)
  1006.     {
  1007.         if (strcmp(currentDirectory.fileName[pos_in_directory], dirname) == 0)
  1008.         {
  1009.             break;
  1010.         }
  1011.     }
  1012.     if (pos_in_directory == DIRECTORY_NUM)
  1013.     {
  1014.         printf("Delete error: Directory not found.\n");
  1015.         return false;
  1016.     }
  1017.  
  1018.     /*
  1019.     *   2. Fetch inode and check whether it's a file.
  1020.     */
  1021.     //Fetch inode
  1022.     int tmp_dir_ino = currentDirectory.inodeID[pos_in_directory];
  1023.     inode tmp_dir_inode;
  1024.     fseek(fd, INODE_START + tmp_dir_ino * BLOCK_SIZE, SEEK_SET);
  1025.     fread(&tmp_dir_inode, sizeof(inode), 1, fd);
  1026.     //Directory check
  1027.     if (tmp_dir_inode.di_mode == 1)
  1028.     {
  1029.         //is a file, roll back and continue to search the file
  1030.         goto DIR_NAME_RE_SEARCH;
  1031.     }
  1032.  
  1033.     /*
  1034.     *   3. Access check.
  1035.     */
  1036.     if (userID != 0 && userID != tmp_dir_inode.di_uid)
  1037.     {
  1038.         printf("Delete error: Access deny.\n");
  1039.         return false;
  1040.     }
  1041.  
  1042.     /*
  1043.     *   4. Start deleting. Delete all sub-directories and files first.
  1044.     */
  1045.     directory tmp_dir;
  1046.     fseek(fd, DATA_START + tmp_dir_inode.di_addr[0] * BLOCK_SIZE, SEEK_SET);
  1047.     fread(&tmp_dir, sizeof(directory), 1, fd);
  1048.  
  1049.     //Search all sub files and directories and delete them.
  1050.     inode tmp_sub_inode;
  1051.     char tmp_sub_filename[FILE_NAME_LENGTH];
  1052.     memset(tmp_sub_filename, 0, FILE_NAME_LENGTH);
  1053.     for (int i = 2; i < DIRECTORY_NUM; i++)
  1054.     {
  1055.         if (strlen(tmp_dir.fileName[i]) > 0)
  1056.         {
  1057.             strcpy(tmp_sub_filename, tmp_dir.fileName[i]);
  1058.             //Determine whether it's a file or a directory.
  1059.             fseek(fd, INODE_START + tmp_dir.inodeID[i] * BLOCK_SIZE, SEEK_SET);
  1060.             fread(&tmp_sub_inode, sizeof(inode), 1, fd);
  1061.             //Before delete sub files and directories, change current directory first and recover after deleting.
  1062.             directory tmp_swp;
  1063.             tmp_swp = currentDirectory;
  1064.             currentDirectory = tmp_dir;
  1065.             tmp_dir = tmp_swp;
  1066.             //Is a file.
  1067.             if (tmp_sub_inode.di_mode == 1)
  1068.             {
  1069.                 DeleteFile(tmp_sub_filename);
  1070.             }
  1071.             //Is a directory.
  1072.             else if (tmp_sub_inode.di_mode == 0)
  1073.             {
  1074.                 RemoveDir(tmp_sub_filename);
  1075.             }
  1076.             tmp_swp = currentDirectory;
  1077.             currentDirectory = tmp_dir;
  1078.             tmp_dir = tmp_swp;
  1079.         }
  1080.     }
  1081.  
  1082.     /*
  1083.     *   5. Start deleting itself. Fill the inode's original space with 0s.
  1084.     */
  1085.     //Fill original space
  1086.     int tmp_fill[sizeof(inode)];
  1087.     memset(tmp_fill, 0, sizeof(inode));
  1088.     fseek(fd, INODE_START + tmp_dir_ino * BLOCK_SIZE, SEEK_SET);
  1089.     fwrite(&tmp_fill, sizeof(inode), 1, fd);
  1090.  
  1091.     /*
  1092.     *   6. Update bitmaps
  1093.     */
  1094.     //inode bitmap
  1095.     inode_bitmap[tmp_dir_ino] = 0;
  1096.     fseek(fd, 2 * BLOCK_SIZE, SEEK_SET);
  1097.     fwrite(&inode_bitmap, sizeof(unsigned short) * INODE_NUM, 1, fd);
  1098.     //block bitmap
  1099.     for (int i = 0; i < (tmp_dir_inode.di_size / BLOCK_SIZE + 1); i++)
  1100.     {
  1101.         block_bitmap[tmp_dir_ino + i] = 0;
  1102.     }
  1103.     fseek(fd, 3 * BLOCK_SIZE, SEEK_SET);
  1104.     fwrite(&block_bitmap, sizeof(unsigned short) * BLOCK_NUM, 1, fd);
  1105.  
  1106.     /*
  1107.     *   7. Update directories
  1108.     */
  1109.     //Fetch current directory inode
  1110.     int pos_directory_inode = currentDirectory.inodeID[0];  //"."
  1111.     inode tmp_directory_inode;
  1112.     fseek(fd, INODE_START + pos_directory_inode * BLOCK_SIZE, SEEK_SET);
  1113.     fread(&tmp_directory_inode, sizeof(inode), 1, fd);
  1114.  
  1115.     //Update current directory item
  1116.     memset(currentDirectory.fileName[pos_in_directory], 0, FILE_NAME_LENGTH);
  1117.     currentDirectory.inodeID[pos_in_directory] = 0xFFFFFFFF;
  1118.     fseek(fd, DATA_START + tmp_directory_inode.di_addr[0] * BLOCK_SIZE, SEEK_SET);
  1119.     fwrite(&currentDirectory, sizeof(directory), 1, fd);
  1120.  
  1121.     //Update associations
  1122.     directory tmp_directory = currentDirectory;
  1123.     int tmp_pos_directory_inode = pos_directory_inode;
  1124.     while (true)
  1125.     {
  1126.         //Update association
  1127.         tmp_directory_inode.di_number--;
  1128.         fseek(fd, INODE_START + tmp_pos_directory_inode * BLOCK_SIZE, SEEK_SET);
  1129.         fwrite(&tmp_directory_inode, sizeof(inode), 1, fd);
  1130.         //If reach the root directory, finish updating.
  1131.         if (tmp_directory.inodeID[1] == tmp_directory.inodeID[0])
  1132.         {
  1133.             break;
  1134.         }
  1135.         //Fetch father directory
  1136.         tmp_pos_directory_inode = tmp_directory.inodeID[1];     //".."
  1137.         fseek(fd, INODE_START + tmp_pos_directory_inode * BLOCK_SIZE, SEEK_SET);
  1138.         fread(&tmp_directory_inode, sizeof(inode), 1, fd);
  1139.         fseek(fd, DATA_START + tmp_directory_inode.di_addr[0] * BLOCK_SIZE, SEEK_SET);
  1140.         fread(&tmp_directory, sizeof(directory), 1, fd);
  1141.     }
  1142.  
  1143.     /*
  1144.     *   78 Update super block
  1145.     */
  1146.     superBlock.s_num_fblock += tmp_dir_inode.di_size / BLOCK_SIZE + 1;
  1147.     superBlock.s_num_finode++;
  1148.     fseek(fd, BLOCK_SIZE, SEEK_SET);
  1149.     fwrite(&superBlock, sizeof(filsys), 1, fd);
  1150.  
  1151.     return true;
  1152. };
  1153.  
  1154. /*
  1155. *   Open a directory.
  1156. *
  1157. *   return: the function returns true only when the directory is
  1158. *           opened successfully.
  1159. */
  1160. bool OpenDir(const char* dirname)
  1161. {
  1162.     //parameter check
  1163.     if (dirname == NULL || strlen(dirname) > FILE_NAME_LENGTH)
  1164.     {
  1165.         printf("Error: Illegal directory name.\n");
  1166.         return false;
  1167.     }
  1168.  
  1169.     /*
  1170.     *   1. Check whether the directory exists in current directory.
  1171.     */
  1172.     int pos_in_directory = 0;
  1173. DIR_NAME_RE_RESEARCH:
  1174.     for (; pos_in_directory < DIRECTORY_NUM; pos_in_directory++)
  1175.     {
  1176.         if (strcmp(currentDirectory.fileName[pos_in_directory], dirname) == 0)
  1177.         {
  1178.             break;
  1179.         }
  1180.     }
  1181.     if (pos_in_directory == DIRECTORY_NUM)
  1182.     {
  1183.         printf("Delete error: Directory not found.\n");
  1184.         return false;
  1185.     }
  1186.  
  1187.     /*
  1188.     *   2. Fetch inode and check whether it's a file.
  1189.     */
  1190.     //Fetch inode
  1191.     int tmp_dir_ino = currentDirectory.inodeID[pos_in_directory];
  1192.     inode tmp_dir_inode;
  1193.     fseek(fd, INODE_START + tmp_dir_ino * BLOCK_SIZE, SEEK_SET);
  1194.     fread(&tmp_dir_inode, sizeof(inode), 1, fd);
  1195.     //Directory check
  1196.     if (tmp_dir_inode.di_mode == 1)
  1197.     {
  1198.         //is a file, roll back and continue to search the file
  1199.         goto DIR_NAME_RE_RESEARCH;
  1200.     }
  1201.  
  1202.     /*
  1203.     *   3. Update current directory.
  1204.     */
  1205.     directory new_current_dir;
  1206.     fseek(fd, DATA_START + tmp_dir_inode.di_addr[0] * BLOCK_SIZE, SEEK_SET);
  1207.     fread(&new_current_dir, sizeof(directory), 1, fd);
  1208.     currentDirectory = new_current_dir;
  1209.  
  1210.     return true;
  1211. };
  1212.  
  1213. /*
  1214. *   Print file and directory information under current directory.
  1215. */
  1216. void List()
  1217. {
  1218.     printf("\nname\t\t\tuser\t\tinodeID\t\tsize\t\ttype\n");
  1219.     for (int i = 0; i < DIRECTORY_NUM; i++)
  1220.     {
  1221.         if (strlen(currentDirectory.fileName[i]) > 0)
  1222.         {
  1223.             inode tmp_inode;
  1224.             fseek(fd, INODE_START + currentDirectory.inodeID[i] * BLOCK_SIZE, SEEK_SET);
  1225.             fread(&tmp_inode, sizeof(inode), 1, fd);
  1226.  
  1227.             const char* tmp_type = tmp_inode.di_mode == 0 ? "dir" : "file";
  1228.             const char* tmp_user = users.userName[tmp_inode.di_uid];
  1229.  
  1230.             printf("%10s\t\t%s\t\t%d\t\t%u\t\t%s\n", currentDirectory.fileName[i], tmp_user, tmp_inode.i_ino, tmp_inode.di_size, tmp_type);
  1231.         }
  1232.     }
  1233.  
  1234.     printf("\n\n");
  1235. }
  1236. void pwd()
  1237. {
  1238.     int current = 0;
  1239.     current = currentDirectory.inodeID[0];
  1240.     inode tmp_inode;
  1241.     fseek(fd, INODE_START + currentDirectory.inodeID[1] * BLOCK_SIZE, SEEK_SET);
  1242.     fread(&tmp_inode, sizeof(inode), 1, fd);
  1243.  
  1244.     printf("PWD : ", currentDirectory.fileName[]);
  1245.  
  1246. }
  1247.    
  1248.  
  1249. /*
  1250. *   Function declaritions.
  1251. */
  1252. void CommParser(inode*&);
  1253. void Help();
  1254. void Tests();
  1255.  
  1256. int main()
  1257. {
  1258.     //Check file system has been formatted or not.
  1259.     FILE* fs_test = fopen("UnixFileSystem.dat", "r");
  1260.     if (fs_test == NULL)
  1261.     {
  1262.         printf("File system not found... Format file system first...\n");
  1263.         Format();
  1264.     }
  1265.  
  1266.     //Install file system
  1267.     Mount();
  1268.  
  1269.     //First log in
  1270.     char tmp_userName[USER_NAME_LENGTH];
  1271.     char tmp_userPassword[USER_PASSWORD_LENGTH];
  1272.  
  1273.     do {
  1274.         memset(tmp_userName, 0, USER_NAME_LENGTH);
  1275.         memset(tmp_userPassword, 0, USER_PASSWORD_LENGTH);
  1276.         printf("=================================================================================\n");
  1277.         printf("==============THIS IS Zdravko Ivanov Chiflishki UNIX FILE SYSTEM=================\n");
  1278.         printf("=============================USER LOG IN=========================================\n");
  1279.         printf("User name:\t");
  1280.         scanf("%s", tmp_userName);
  1281.         printf("Password:\t");
  1282.         scanf("%s", tmp_userPassword);
  1283.     } while (Login(tmp_userName, tmp_userPassword) != true);
  1284.  
  1285.     //User's mode of file system
  1286.     inode* currentInode = new inode;
  1287.  
  1288.     CommParser(currentInode);
  1289.     return 0;
  1290. }
  1291.  
  1292. /*
  1293. *   Recieve commands from console and call functions accordingly.
  1294. *
  1295. *   para cuurentInode: a global inode used for 'open' and 'write'
  1296. */
  1297. void CommParser(inode*& currentInode)
  1298. {
  1299.     char para1[11];
  1300.     char para2[1024];
  1301.  
  1302.     //Recieve commands
  1303.     while (true)
  1304.     {
  1305.         memset(para1, 0, 11);
  1306.         memset(para2, 0, 1024);
  1307.  
  1308.         printf("%s>", userName);
  1309.         scanf("%s", para1);
  1310.         para1[10] = 0;  //security protection
  1311.  
  1312.         //Choose function
  1313.         //Print current directory
  1314.         if (strcmp("ls", para1) == 0)
  1315.         {
  1316.             List();
  1317.         }
  1318.         //print pwd()
  1319.         else if (strcmp("pwd", para1) == 0)
  1320.         {
  1321.             pwd();
  1322.         }
  1323.         //Create file
  1324.         else if (strcmp("create", para1) == 0)
  1325.         {
  1326.             scanf("%s", para2);
  1327.             para2[1023] = 0;    //security protection
  1328.  
  1329.             CreateFile(para2);
  1330.         }
  1331.         //Delete file
  1332.         else if (strcmp("del", para1) == 0)
  1333.         {
  1334.             scanf("%s", para2);
  1335.             para2[1023] = 0;    //security protection
  1336.  
  1337.             DeleteFile(para2);
  1338.         }
  1339.         //Open file
  1340.         else if (strcmp("open", para1) == 0)
  1341.         {
  1342.             scanf("%s", para2);
  1343.             para2[1023] = 0;    //security protection
  1344.  
  1345.             currentInode = OpenFile(para2);
  1346.         }
  1347.         //Write file
  1348.         else if (strcmp("write", para1) == 0)
  1349.         {
  1350.             scanf("%s", para2);
  1351.             para2[1023] = 0;    //security protection
  1352.  
  1353.             Write(*currentInode, para2);
  1354.         }
  1355.         //Open a directory
  1356.         else if (strcmp("cd", para1) == 0)
  1357.         {
  1358.             scanf("%s", para2);
  1359.             para2[1023] = 0;    //security protection
  1360.  
  1361.             OpenDir(para2);
  1362.         }
  1363.         //Create dirctory
  1364.         else if (strcmp("mkdir", para1) == 0)
  1365.         {
  1366.             scanf("%s", para2);
  1367.             para2[1023] = 0;    //security protection
  1368.  
  1369.             MakeDir(para2);
  1370.         }
  1371.         //Delete directory
  1372.         else if (strcmp("rmdir", para1) == 0)
  1373.         {
  1374.             scanf("%s", para2);
  1375.             para2[1023] = 0;    //security protection
  1376.  
  1377.             RemoveDir(para2);
  1378.         }
  1379.         //Log out
  1380.         else if (strcmp("Logout", para1) == 0)
  1381.         {
  1382.             Logout();
  1383.         }
  1384.         //Log in
  1385.         else if (strcmp("Login", para1) == 0)
  1386.         {
  1387.             char para3[USER_PASSWORD_LENGTH + 1];
  1388.             memset(para3, 0, USER_PASSWORD_LENGTH + 1);
  1389.  
  1390.             scanf("%s", para2);
  1391.             para2[1023] = 0;    //security protection
  1392.             scanf("%s", para3);
  1393.             para3[USER_PASSWORD_LENGTH] = 0;    //security protection
  1394.  
  1395.             Login(para2, para3);
  1396.         }
  1397.         //Exit
  1398.         else if (strcmp("Exit", para1) == 0)
  1399.         {
  1400.             break;
  1401.         }
  1402.         //Error or help
  1403.         else
  1404.         {
  1405.             Help();
  1406.         }
  1407.     }
  1408. };
  1409.  
  1410. /*
  1411. *   Print all commands help information when 'help' is
  1412. *   called or input error occurs.
  1413. */
  1414. void Help()
  1415. {
  1416.     printf("\n=======================================================\n");
  1417.     printf("=================This is Help info=======================\n");
  1418.     printf("Command\tParametar\t\tInformation.\n");
  1419.     printf("ls\t\t\tPrint current directory information.\n");
  1420.     printf("create\t<filename>\tCreate a new empty file in current directory.\n");
  1421.     printf("del\t<filename>\tDelete the file in current directory.\n");
  1422.     printf("open\t<filename>\tOpen a file. Must be used before 'write'.\n");
  1423.     printf("cd\t<dirname>\tOpen a directory.\n");
  1424.     printf("mkdir\t<dirname>\tCreate a new directory.\n");
  1425.     printf("rmdir\t<dirname>\tDelete the directory and all sub files and directoies in\t\t\tit.\n");
  1426.     printf("Logout\t\t\tLog out.\n");
  1427.     printf("Login <name> <psd>\tLog in as another user.\n");
  1428.     printf("Exit\t\t\tExit the file system console.\n");
  1429.     printf("Help\t\t\tShow help info.\n\n");
  1430. };
  1431.  
  1432.  
  1433. void Test() {
  1434.         char str[] = "Каждый хороший программист должен знать функцию memset!n";
  1435.         memset(str, '_', 12); // заполнить первые 12 байт символом '_'
  1436.         std::cout << str;
  1437. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement