Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Data Structure only C++ Write a program that will simulate a Unix File System. T

ID: 3718195 • Letter: D

Question

Data Structure only C++

Write a program that will simulate a Unix File System. This program will use a tree to represent the file system. It should provide, at a minimum, the following functionality to the user: mkdir, touch, cd, ls, and exit. When this program runs it should display a welcome prompt and then wait for input from the user. The user should be then be able type in their commands. The idea is to simulate the command prompt of windows or the shell prompt of Linux. Your program should feel similar to either of these shells.

mkdir <dirname> – This should create a new “directory” in the current directory with ‘dirname’ as it’s name.

touch <filename> – This should create a new “file” in the current directory with ‘filename’ as it’s name.

cd <path> – This should change the current directory to the directory specified by ‘path’. It should be able to accept both relative and absolute paths. A relative path starts with a ‘/’ and describes a path from the root. A relative path will start with a ‘.’ and describes a path from the current directory. ‘..’ indicates the parent directory. ‘.’ Indicates the current directory. Paths should use a ‘/’ to separate folders in the path. For example ‘../home/fconlon’. A ‘/’ by itself indicates the root directory. If a user attempts to cd to a file or a directory that does not exist an error message should be displayed, and the program should continue to run.

ls <path> – This should display all of the files and directories in the directory specified by ‘path’. If not path is specified then it should display all the files and directories in the current directory. This command should first display all the directories in the current directory in alphabetical order the display all of the files in the current directory in alphabetical order. ‘path’ should follow the same conventions for the ‘path’ argument from cd. It should display the same errors under the same conditions as cd.

Exit – This should exit the program. Don’t forget to clear any memory that you allocated.

Explanation / Answer

Anwer:-

To compile, use the command: g++ -std=c++11 terminal.cpp
You need to use the c++11 flags for this. This code is specific to Unix.

terminal.cpp

#include <bits/stdc++.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>

using namespace std;

// Case insensitive string comparison
bool caseInsensitiveStrCompare(string s1, string s2) {
   int i;
   for(i = 0; i < s1.size() && i < s2.size(); i++) {
       if (tolower(s1[i]) < tolower(s2[i])) return true;
       else if (tolower(s1[i]) > tolower(s2[i])) return false;
   }

   // s1 is smaller than s2
   if (i < s2.size()) {
       return true;
   }

   // s2 is smaller than s1
   else if (i < s1.size()) {
       return false;
   }

   return true;
}

int main() {
   cout<<"Welcome! ";
   string command;
   while (true) {
       // Print the terminal text
       char cwd[1024];
       getcwd(cwd, 1024);
       cout<<cwd<<"> ";
      
       // Get the command from the user
       getline(cin, command);
       if (command.size() < 1) continue;      
      
       // Split the string using spaces
       istringstream iss(command);
       vector<string> words(istream_iterator<string>{iss}, std::istream_iterator<string>());;

       // mkdir
       if (words[0] == "mkdir") {
           // if no directory name mentioned
           if (words.size() < 2) {
               cout<<"mkdir: missing operand ";
               continue;
           }

           // print error if fails
           if (mkdir(words[1].c_str(), 0777) < 0) {
               if (errno == EACCES) cout<<"mkdir failed Error " <<errno<<": Permission denied"<<endl;
               else if (errno == EEXIST) cout<<"mkdir failed Error " <<errno<<": directory is already present"<<endl;
           }
       }

       // touch
       else if (words[0] == "touch") {
           // if no filename mentioned
           if (words.size() < 2) {
               cout<<"mkdir: missing file operand ";
               continue;
           }

           // create a file in append mode and close it
           ofstream outfile;
           outfile.open(words[1], ios_base::app);
           outfile.close();
       }

       // cd
       else if (words[0] == "cd") {
           // if no directory mentioned
           if (words.size() < 2) {
               cout<<"cd: missing operand ";
               continue;
           }

           // if cd fails
           if (chdir(words[1].c_str()) < 0) {
               cout<<"Invalid directory "<<words[1]<<endl;
           }
       }

       // ls
       else if (words[0] == "ls") {
           // Set the directory for ls
           string dir = cwd;
           if (words.size() > 1) dir = words[1];
          
           // Check if the directory is present
           DIR *dp = opendir(dir.c_str());;
           if(dp == NULL) {
               cout<<"Invalid directory "<<dir<<endl;
               continue;
           }

           // Read while files are present and append to a vector
           vector<string> filenames;
           struct dirent *dirp = readdir(dp);
           while (dirp!= NULL) {
               // Skip hidden directories and . and ..
               if (dirp->d_name[0] != '.') filenames.push_back(dirp->d_name);
               dirp = readdir(dp);
           }

           // Sort and print the filenames
           sort(filenames.begin(), filenames.end(), caseInsensitiveStrCompare);
           for (int i = 0; i < filenames.size(); i++) {
               cout<<filenames[i]<<endl;
           }

           // Close the directory
           closedir(dp);
       }

       // exit
       else if (words[0] == "exit") {
           break;
       }

       // Invalid command
       else {
           cout<<"Invalid command "<<words[0]<<endl;
       }
   }

   return 0;
}

Sample output:

Welcome!
/media/user/Files/work/Chegg/22042018_terminal>
/media/user/Files/work/Chegg/22042018_terminal> ls
a.out
fileSystem.cpp
/media/user/Files/work/Chegg/22042018_terminal> ls abc
Invalid directory abc
/media/user/Files/work/Chegg/22042018_terminal> mkdir dir
/media/user/Files/work/Chegg/22042018_terminal> ls
a.out
dir
fileSystem.cpp
/media/user/Files/work/Chegg/22042018_terminal> mkdir dir
mkdir failed Error 17: directory is already present
/media/user/Files/work/Chegg/22042018_terminal> cd yo
Invalid directory yo
/media/user/Files/work/Chegg/22042018_terminal> cd dir
/media/user/Files/work/Chegg/22042018_terminal/dir> ls
/media/user/Files/work/Chegg/22042018_terminal/dir> touch file
/media/user/Files/work/Chegg/22042018_terminal/dir> ls
file
/media/user/Files/work/Chegg/22042018_terminal/dir> cd ..
/media/user/Files/work/Chegg/22042018_terminal> ls
a.out
dir
fileSystem.cpp
/media/user/Files/work/Chegg/22042018_terminal> exit