C++开发的伪File System实现

135次阅读
一条评论

共计 21029 个字符,预计需要花费 53 分钟才能阅读完成。

#include <bits/stdc++.h>
#include <string>
#include <fstream>

using namespace std;

typedef long long ll;
typedef double db;

// 外部系统函数 
bool fileExists(const std::string& filename)
{
    std::ifstream file(filename);
    return file.good();
}

// 保存 vector<vector<ll>> 到二进制文件 
void saveVector2DBinary(const std::vector<std::vector<ll>>& data, const std::string& filename) {
    std::ofstream file(filename, std::ios::binary);
    if (!file.is_open()) {
        std::cerr << " 无法打开文件: " << filename << std::endl;
        return;
    }
    
    // 先写入行数 
    size_t rows = data.size();
    file.write(reinterpret_cast<const char*>(&rows), sizeof(rows));
    
    // 写入每一行 
    for (const auto& row : data) {
        size_t cols = row.size();
        file.write(reinterpret_cast<const char*>(&cols), sizeof(cols));
        if (cols > 0) {
            file.write(reinterpret_cast<const char*>(row.data()), cols * sizeof(ll));
        }
    }
    file.close();
}

// 从二进制文件读取 vector<vector<ll>>
std::vector<std::vector<ll>> loadVector2DBinary(const std::string& filename) {
    std::vector<std::vector<ll>> data;
    std::ifstream file(filename, std::ios::binary);
    if (!file.is_open()) {
        std::cerr << " 无法打开文件: " << filename << std::endl;
        return data;
    }
    
    // 读取行数 
    size_t rows;
    file.read(reinterpret_cast<char*>(&rows), sizeof(rows));
    data.resize(rows);
    
    // 读取每一行 
    for (size_t i = 0; i < rows; ++i) {
        size_t cols;
        file.read(reinterpret_cast<char*>(&cols), sizeof(cols));
        data[i].resize(cols);
        if (cols > 0) {
            file.read(reinterpret_cast<char*>(data[i].data()), cols * sizeof(ll));
        }
    }
    file.close();
    return data;
}

// 文件类 
struct fs {
    string type; // 类型(文件 or 文件夹)(file or dir)
    string name; // 名称 
    ll id; // 唯一标识符 
    string content = ""; // 内容 
    
    // 序列化函数 
    void serialize(std::ofstream& file) const {
        // 写入 type
        size_t type_len = type.size();
        file.write(reinterpret_cast<const char*>(&type_len), sizeof(type_len));
        file.write(type.c_str(), type_len);
        
        // 写入 name
        size_t name_len = name.size();
        file.write(reinterpret_cast<const char*>(&name_len), sizeof(name_len));
        file.write(name.c_str(), name_len);
        
        // 写入 id
        file.write(reinterpret_cast<const char*>(&id), sizeof(id));
        
        // 写入 content
        size_t content_len = content.size();
        file.write(reinterpret_cast<const char*>(&content_len), sizeof(content_len));
        if (content_len > 0) {
            file.write(content.c_str(), content_len);
        }
    }
    
    // 反序列化函数 
    void deserialize(std::ifstream& file) {
        // 读取 type
        size_t type_len;
        file.read(reinterpret_cast<char*>(&type_len), sizeof(type_len));
        type.resize(type_len);
        if (type_len > 0) {
            file.read(&type[0], type_len);
        }
        
        // 读取 name
        size_t name_len;
        file.read(reinterpret_cast<char*>(&name_len), sizeof(name_len));
        name.resize(name_len);
        if (name_len > 0) {
            file.read(&name[0], name_len);
        }
        
        // 读取 id
        file.read(reinterpret_cast<char*>(&id), sizeof(id));
        
        // 读取 content
        size_t content_len;
        file.read(reinterpret_cast<char*>(&content_len), sizeof(content_len));
        content.resize(content_len);
        if (content_len > 0) {
            file.read(&content[0], content_len);
        }
    }
};

// 保存 vector<fs> 到二进制文件 
void saveVectorBinary(const std::vector<fs>& data, const std::string& filename) {
    std::ofstream file(filename, std::ios::binary);
    if (!file.is_open()) {
        std::cerr << " 无法打开文件: " << filename << std::endl;
        return;
    }
    
    // 先写入元素数量 
    size_t size = data.size();
    file.write(reinterpret_cast<const char*>(&size), sizeof(size));
    
    // 写入所有数据 
    for (const auto& item : data) {
        item.serialize(file);
    }
    file.close();
}

// 从二进制文件读取 vector<fs>
std::vector<fs> loadVectorBinary(const std::string& filename) {
    std::vector<fs> data;
    std::ifstream file(filename, std::ios::binary);
    if (!file.is_open()) {
        std::cerr << " 无法打开文件: " << filename << std::endl;
        return data;
    }
    
    // 读取元素数量 
    size_t size;
    file.read(reinterpret_cast<char*>(&size), sizeof(size));
    data.resize(size);
    
    // 读取所有数据 
    for (size_t i = 0; i < size; ++i) {
        data[i].deserialize(file);
    }
    file.close();
    return data;
}

// 变量定义~
// 主机信息 
string host_name = "syh"; // 主机名 
string now_ip = "localhost"; // 终端连接的主机 IP
string now_user = "root"; // 登录用户 

// 文件系统 
fs root = {"dir", "/", 0}; // 根目录 
vector<fs> file_system; // file_system[i] 表示 ID 为 i 的文件 / 文件夹 
vector<vector<ll>> children; // children[i] 表示 ID 为 i 的文件夹下所有孩子的 id

// 高效获取当前路径 
string path_str = "/"; // 存目前路径的字符串 
vector<fs> path; // 存目前路径的所有文件夹(有序)

// 获取开始时间 
time_t start_time = chrono::system_clock::to_time_t(chrono::system_clock::now()); // 获取当前系统时间 

// 终端样式定义 
const string BD = "\033[1m";
const string NC = "\033[0m"; // 重置颜色 

// 前景色 
const string RED = "\033[0;31m";
const string GREEN = "\033[0;32m";
const string YELLOW = "\033[1;33m";
const string BLUE = "\033[0;34m";
const string PURPLE = "\033[0;35m";
const string CYAN = "\033[0;36m";
const string WHITE = "\033[0;37m";
const string GRAY = "\033[0;90m";

// 背景色 
const string BG_RED = "\033[41m";
const string BG_GREEN = "\033[42m";
const string BG_YELLOW = "\033[43m";
const string BG_BLUE = "\033[44m";
const string BG_MAGENTA = "\033[45m";
const string BG_CYAN = "\033[46m";
const string BG_WHITE = "\033[47m";

// 主题色 
string TC = RED;

// 命令错误的次数 
ll wrong_cnt = 0;

// 分割命令列表 
vector<string> coms;


time_t get_now_time() { // 获取时间 
    return chrono::system_clock::to_time_t(chrono::system_clock::now()) - start_time;
}

string add_define(string original) { // 添加引号 
    char tmp = '"';
    return tmp + original + tmp;
}

string get_theme_input_text(signed last_code) { // 获取主题性输入文本 
    // 直接使用 path_str
    string bg = BG_CYAN;
    string wr = "";
    if (last_code == 1) wr = " " + to_string(wrong_cnt) + "W";
    return RED + BD + bg + wr + "  " + BD + TC + bg + host_name + NC + WHITE + bg + "@" + now_ip + " " + NC + BG_WHITE + " " + path_str + " " + NC + " ";
}

string get_theme_confirm_text(string command) { // 获取主题固着文本 
    return BD + ">" + NC + " " + command;
}

string get_theme_command_not_found_text() { // 获取命令未找到文字 
    return "Command " + add_define(coms[0]) + " Is Undefined!";
}

void output(string output_text = "", string end = "\n") { // 格式化输出 
    cout << output_text << end;
    cout << flush; // 刷新缓冲区,防止内容停在其中 
}

string input(string input_text = "") { // 获取输入 
    output(input_text, "");

    string res;
    getline(cin, res);
    return res;
}

void cls() { // 清屏 
    output("\033[2J\033[1;1H", "");
}

// 转译符号 
map<string, pair<string, string>> translate_log_type = {{"i", {NC, "INFO"}}, {"w", {YELLOW, "WARN"}}, {"e", {RED, "ERROR"}}};
void output_log(string type, string content) { // 输出日志 
    if (translate_log_type[type].second == "") {
        type = add_define(type);
        output_log("w", "Unknown log type: " + type + ".");
        return;
    }

    string color;
    color = translate_log_type[type].first;
    type = translate_log_type[type].second;

    output("[ " + color + BD + type + NC + " ]: ", "");
    output(content);
    // output("[ " + to_string(get_now_time()) + " ]: " + content);
}

void confirm_input(string command) { // 固着输入 
    string res;
    res = get_theme_confirm_text(command);
    output("\033[1A\033[2K"); // 回到并清空上一行 
    output("\033[1A" + res); // 回到上一行输出 
}

void init_system() { // 初始化 
    output_log("i", "Initializing System...");

    output_log("i", "Initializing File System...");
    output_log("i", "Adding Root Section...");
    path.push_back(root);
    vector<ll> root_fs;
    children.push_back(root_fs);
    file_system.push_back(root);
    output_log("i", "Root Section Added.");
    output_log("i", "File System Initialized.");

    output_log("i", "Initialized System.");
}

void load_system() { // 从磁盘上加载文件系统 
    output_log("i", "Loading System...");

    path.push_back(root);

    file_system = loadVectorBinary("fs.fs");
    children = loadVector2DBinary("fs_children.vll");

    output_log("i", "Loaded.");
}

signed save_system() { // 保存系统 
    output_log("i", "Saving System...");

    saveVectorBinary(file_system, "fs.fs");
    saveVector2DBinary(children, "fs_children.vll");

    output_log("i", "Saved.");

    return 0;
}

signed neofetch() { // 系统信息输出 
    string split_str = "";
    string main_str = TC + BD + host_name + NC + "@" + TC + BD + now_ip + NC;
    string main_str2 = host_name + "@" + now_ip;
    for (ll i=1; i <= (ll)main_str2.length(); i++) split_str += "-";

    string colorful_str = "", unit = "   ";
    colorful_str = BG_RED + unit + BG_GREEN + unit + BG_YELLOW + unit + BG_MAGENTA + unit + BG_CYAN + unit + BG_WHITE + unit + NC;

    output("                             .-'''-.                                   " + main_str);
    output("                           .'       `.                                 " + split_str);
    output("                          /           \\                                " + TC + BD + "OS" + NC + ": Fs Operation System");
    output("          " + TC + "_..._" + NC + "          |             |                               " + TC + BD + "Kernel" + NC + ": 1.0.0-test");
    output("       " + TC + ".'     '." + NC + "         |             |        " + TC + ".'     '." + NC + "              " + TC + BD + "Terminal" + NC + ": Fs Bash (Builtin)");
    output("      " + TC + "/  .-''-.  \\" + NC + "        \\            /       " + TC + "/  .-''-.  \\" + NC + "            " + TC + BD + "CPU" + NC + ": Virtual Core 2");
    output("     " + TC + "|  /       \\  |" + NC + "        '-._____.-'       " + TC + "|  /       \\  |" + NC + "          " + TC + BD + "GPU" + NC + ": Builtin");
    output("     " + TC + "| |         | |" + NC + "       _.-'     `-.       " + TC + "| |         | |" + NC + "          " + TC + BD + "Memory" + NC + ": Unknown / Unknown");
    output("      " + TC + "\\ \\       / /" + NC + "      /             \\       " + TC + "\\ \\       / /" + NC + "           ");
    output("       " + TC + "'.`-...-' .'" + NC + "     |               |       " + TC + "'.`-...-' .'" + NC + "           " + colorful_str);
    output("         " + TC + "`.__.'" + NC + "         \\             /           " + TC + "`.__.'" + NC + "               ");
    output("                         '-...___...-'                                 ");

    return 0;
}

void welcome_page() { // 欢迎页 
    cls();
    // 欢迎文字 
    neofetch();
    output("");
    output("Welcome to FsOS!");
    output("");
    output("");
}

void split_command(vector<string> *coms, string command) { // 分割接收到的命令 
    string now_com = "";
    bool in_com = 0;
    bool commed = 0;
    for (auto i : command) {
        if (i == ' ' && !in_com) {
            if (now_com != "" || commed)
                coms->push_back(now_com);
            now_com = "";
            commed = 0;
            continue;
        }
        if (i == '"') {
            in_com = !in_com;
            if (!in_com) commed = 1;
            continue;
        }
        now_com += i;
    }
    if (now_com != "" || commed) coms->push_back(now_com);
}

void help() { // 帮助页 
    output(BD + "help" + NC + ": Show this page.");
    output(BD + "clear" + NC + ": Clear the Content of the Terminal.");
    output(BD + "whoami" + NC + ": Show Your Username.");
    output(BD + "whereami" + NC + ": Show Your Working Directory.");
    output(BD + "ls" + NC + ": List Files and Folders.");
    output(BD + "cd" + NC + ": Change Working Directory.");
    output(BD + "touch" + NC + ": Create Files.");
    output(BD + "mkdir" + NC + ": Create Folders");
    output(BD + "echo" + NC + ": Output the input");
    output(BD + "neofetch" + NC + ": Show System Info.");
    output(BD + "exit" + NC +": Exit the Shell.");
    output("");
    output("Tip: You Can Use " + add_define("[content]")+ " to Input a Space-contained Text.");
    output("");
}

ll get_now_id() { // 获取工作目录 ID
    return path[path.size()-1].id;
}

bool exist_dir(string dirname, ll now_dir_id=get_now_id()) { // 判断文件夹是否存在 
    for (auto i : children[now_dir_id]) {
        if (file_system[i].type == "deleted") continue;
        if (file_system[i].name == dirname && file_system[i].type == "dir") {
            return 1;
        }
    }
    return 0;
}

bool have_space(string x) { // 判断是否有空格 
    for (auto i : x) {
        if (i == ' ') {
            return 1;
        }
    }
    return 0;
}

bool ls_cmp(ll x, ll y) { // 文件列表排序 
    if (file_system[x].type == file_system[y].type) {
        return file_system[x].name < file_system[y].name;
    }
    else {
        if (file_system[x].type == "dir") return 1;
        else return 0;
    }
}

signed ls() { // 浏览当前目录下的文件 
    ll now_dir_id = get_now_id();
    vector<ll> ls_ids;
    for (auto i : children[now_dir_id]) {
        if (file_system[i].type == "deleted") continue;
        ls_ids.push_back(i);
    }
    sort(ls_ids.begin(), ls_ids.end(), ls_cmp); // 排序(文件夹在前,文件在后,字典序)
    for (auto i : ls_ids) {
        fs now_file = file_system[i];
        if (have_space(now_file.name)) now_file.name = add_define(now_file.name);
        if (now_file.type == "dir") output(CYAN + BD, "");
        output(now_file.name, " " + NC);
    }
    if (ls_ids.size() > 0) output();
    return 0;
}

pair<signed, ll> mkdir_re(ll now_dir_id, bool flag, bool loop_make) { // 实际创建目录 
    if (exist_dir(coms[1], now_dir_id)) {
        if (!flag) {
            for (auto i : children[now_dir_id]) {
                if (file_system[i].type == "deleted") continue;
                if (file_system[i].type == "dir" && file_system[i].name == coms[1]) {
                    return {0, file_system[i].id};
                }
            }
        }
        output_log("e", "The dir " + add_define(coms[1]) + " has already existed!");
        return {1, -1};
    }
    if (!loop_make && !flag) { // 中途有一个文件夹不对 
        output_log("e", "The dir " + add_define(coms[1]) + " does not exist!");
        return {1, -1};
    }

    string new_dir_name = coms[1];
    fs new_dir;
    new_dir.id = file_system.size();
    new_dir.name = new_dir_name;
    new_dir.type = "dir";

    file_system.push_back(new_dir);
    children[now_dir_id].push_back(new_dir.id);
    vector<ll> new_children;
    children.push_back(new_children);

    return {0, new_dir.id};
}

vector<string> split_dirs; // 分割目录 
signed split_dir(string dirname) {
    split_dirs.clear();
    string now_str = "";
    for (auto i : dirname) {
        if (i == '/' || i == '\\') {
            if (now_str != "") {
                if (now_str == ".." && split_dirs.size() >= 1) {
                    split_dirs.pop_back();
                }
                else {
                    if (!(now_str == ".")) split_dirs.push_back(now_str);
                }
            }
            now_str = "";
            continue;
        }
        now_str += i;
    }
    if (now_str != "") {
        split_dirs.push_back(now_str);
    }
    return 0;
}

signed mkdir() { // 创建目录 
    if (coms.size() <= 1) {
        output("MKDIR");
        output("    Usage: mkdir [dirname]");
        output("    Create a folder.");
        output("");
        return 0;
    }

    string new_dir_name = coms[1];
    coms[1] = "";

    split_dir(new_dir_name);

    bool loop_make = 0;
    for (ll i=2; i < (ll)coms.size(); i++) {
        if (coms[i] == "-p") {
            loop_make = 1;
        }
    }

    vector<ll> now_dir_id;
    for (auto i : path) {
        now_dir_id.push_back(i.id);
    }
    for (ll j=0; j < (ll)split_dirs.size(); j++) {
        auto i = split_dirs[j];
        coms[1] = i;
        if (coms[1] == "..") {
            now_dir_id.pop_back();
            if (now_dir_id.size() == 0) {
                output_log("e", "The route is out of the root.");
                return 1;
            }
            continue;
        }
        auto code = mkdir_re(now_dir_id[now_dir_id.size()-1], j == (ll)split_dirs.size()-1, loop_make);
        if (code.first == 1) return 1;
        now_dir_id.push_back(code.second);
    }
    now_dir_id.clear();
    return 0;
}

signed cd_re() { // 实际切换目录 
    string cd_name = coms[1];

    if (cd_name == "..") { // 返回上一级目录 
        path_str = path_str.substr(0, path_str.length() - path[path.size()-1].name.length() - 1);
        path.pop_back();
        if (path.size() == 0) {
            output_log("e", "The route is out of the root.");
            return 1;
        }
        return 0;
    }

    if (!exist_dir(cd_name)) {
        output_log("e", "The dir " + add_define(cd_name) + " does not exist!");
        return 1;
    }

    fs cdir;
    ll now_dir_id = get_now_id();
    for (auto i : children[now_dir_id]) {
        if (file_system[i].type == "deleted") continue;
        if (file_system[i].type == "dir" && file_system[i].name == cd_name) {
            cdir = file_system[i];
            break;
        }
    }

    path.push_back(cdir);
    path_str += cdir.name + "/";

    return 0;
}

signed cd() { // 切换目录 
    if (coms.size() == 1) {
        path.clear();
        path.push_back(root);
        path_str = "/";
        return 0;
    }

    string cd_dir_name = coms[1];
    coms[1] = "";

    string bak_path_str = path_str;
    vector<fs> bak_path = path;

    split_dir(cd_dir_name);

    for (auto i : split_dirs) {
        coms[1] = i;
        auto code = cd_re();
        if (code == 1) {
            // 出错了,恢复回去 
            path_str = bak_path_str;
            path = bak_path;
            return 1;
        }
    }
    return 0;
}

signed touch() { // 创建文件 
    if (coms.size() <= 1) {
        output("TOUCH");
        output("    Usage: touch [file_name]");
        output("    Create a file.");
        output("");
        return 0;
    }
    string file_path = coms[1];
    split_dir(file_path);

    string file_name = split_dirs[split_dirs.size() - 1];
    split_dirs.pop_back();

    // 判断文件名中是否只有“.”(不合法)
    bool flag = 1;
    for (auto i : file_name) {
        if (i != '.') {
            flag = 0;
            break;
        }
    }
    if (flag) {
        output_log("e", "The filename " + add_define(file_name) + " is illegal.");
        return 1;
    }

    // 获取文件的路径 
    vector<ll> file_dir_id;
    for (auto i : path) file_dir_id.push_back(i.id);
    for (auto i : split_dirs) {
        if (i == "..") {
            file_dir_id.pop_back();
            if (file_dir_id.size() == 0) {
                output_log("e", "The route is out of the root.");
                return 1;
            }
            continue;
        }
        bool flag = 0;
        for (auto j : children[file_dir_id[file_dir_id.size()-1]]) {
            auto now_f = file_system[j];
            if (now_f.type == "deleted") continue;
            if (now_f.type == "dir" && now_f.name == i) {
                file_dir_id.push_back(now_f.id);
                flag = 1;
                break;
            }
        }
        if (!flag) {
            output_log("e", "The dir " + add_define(i) + " is not exist!");
            return 1;
        }
    }

    // 查看是否已经存在 
    for (auto i : children[file_dir_id[file_dir_id.size()-1]]) {
        auto now_f = file_system[i];
        if (now_f.type == "deleted") continue;
        if (now_f.type == "file" && now_f.name == file_name) {
            return 0;
        }
    }

    fs new_file;
    new_file.name = file_name;
    new_file.type = "file";
    new_file.content = "";
    new_file.id = file_system.size();

    file_system.push_back(new_file);
    children[file_dir_id[file_dir_id.size()-1]].push_back(new_file.id);
    children.push_back(vector<ll>());

    return 0;
}

signed cat() { // 查看文件 
    if (coms.size() <= 1) {
        output("CAT");
        output("    Usage: cat [file_name]");
        output("    view a file.");
        output("");
        return 0;
    }
    string file_path = coms[1];
    split_dir(file_path);

    string file_name = split_dirs[split_dirs.size() - 1];
    split_dirs.pop_back();

    // 判断文件名中是否只有“.”(不合法)
    bool flag = 1;
    for (auto i : file_name) {
        if (i != '.') {
            flag = 0;
            break;
        }
    }
    if (flag) {
        output_log("e", "The filename " + add_define(file_name) + " is illegal.");
        return 1;
    }

    // 获取文件的路径 
    vector<ll> file_dir_id;
    for (auto i : path) file_dir_id.push_back(i.id);
    for (auto i : split_dirs) {
        if (i == "..") {
            file_dir_id.pop_back();
            if (file_dir_id.size() == 0) {
                output_log("e", "The route is out of the root.");
                return 1;
            }
            continue;
        }
        bool flag = 0;
        for (auto j : children[file_dir_id[file_dir_id.size()-1]]) {
            auto now_f = file_system[j];
            if (now_f.type == "deleted") continue;
            if (now_f.type == "dir" && now_f.name == i) {
                file_dir_id.push_back(now_f.id);
                flag = 1;
                break;
            }
        }
        if (!flag) {
            output_log("e", "The dir " + add_define(i) + " is not exist!");
            return 1;
        }
    }

    // 查看是否已经存在 
    fs cat_file;
    flag = 0;
    for (auto i : children[file_dir_id[file_dir_id.size()-1]]) {
        auto now_f = file_system[i];
        if (now_f.type == "deleted") continue;
        if (now_f.type == "file" && now_f.name == file_name) {
            flag = 1;
            cat_file = now_f;
            break;
        }
    }
    if (!flag) { // 找不到 
        output_log("e", "The file " + add_define(file_name) + " is not exist!");
        return 1;
    }

    output(cat_file.content);

    return 0;
}

signed write_file(string filename, string file_content) { // 写入文件 
    split_dir(filename);

    string file_name = split_dirs[split_dirs.size() - 1];
    split_dirs.pop_back();

    // 判断文件名中是否只有“.”(不合法)
    bool flag = 1;
    for (auto i : file_name) {
        if (i != '.') {
            flag = 0;
            break;
        }
    }
    if (flag) {
        output_log("e", "The filename " + add_define(file_name) + " is illegal.");
        return 1;
    }

    // 获取文件的路径 
    vector<ll> file_dir_id;
    for (auto i : path) file_dir_id.push_back(i.id);
    for (auto i : split_dirs) {
        if (i == "..") {
            file_dir_id.pop_back();
            if (file_dir_id.size() == 0) {
                output_log("e", "The route is out of the root.");
                return 1;
            }
            continue;
        }
        bool flag = 0;
        for (auto j : children[file_dir_id[file_dir_id.size()-1]]) {
            auto now_f = file_system[j];
            if (now_f.type == "deleted") continue;
            if (now_f.type == "dir" && now_f.name == i) {
                file_dir_id.push_back(now_f.id);
                flag = 1;
                break;
            }
        }
        if (!flag) {
            output_log("e", "The dir " + add_define(i) + " is not exist!");
            return 1;
        }
    }

    // 查看是否已经存在 
    ll tmp_file;
    flag = 0;
    for (auto i : children[file_dir_id[file_dir_id.size()-1]]) {
        auto now_f = file_system[i];
        if (now_f.type == "deleted") continue;
        if (now_f.type == "file" && now_f.name == file_name) {
            flag = 1;
            tmp_file = now_f.id;
            break;
        }
    }
    if (!flag) { // 找不到 
        output_log("e", "The file " + add_define(file_name) + " is not exist!");
        return 1;
    }

    file_system[tmp_file].content = file_content;

    return 0;
}

signed echo() { // 输出内容 
    if (coms.size() == 1) {
        output("ECHO");
        output("    Usage1: echo [content]");
        output("    Output the Content");
        output("    Usage2: echo [content] > [filename]");
        output("    Output the Content to a File");
        output("");
        return 0;
    }
    if (coms.size() == 2) {
        output(coms[1]);
        return 0;
    }

    if (coms[2] == ">") { // 输出内容至文件 
        if (coms.size() <= 3 || coms[3] == "") {
            output_log("e", "The Pipe Cannot Be Found!");
            return 0;
        }
        return write_file(coms[3], coms[1]);
    }
    else {
        for (ll i=1; i < (ll)coms.size(); i++) {
            output(coms[i], " ");
        }
        output("");
    }

    return 0;
}

ll tree_dir_cnt, tree_file_cnt;
void tree_re(ll now_id, ll tab) { // 实际输出树状目录结构 
    string tabs = ""; // 缩进 
    for (ll i=1; i <= tab; i++) {
        if (i % 4 == 1) tabs += "|";
        tabs += " ";
    }

    vector<ll> ls_ids;
    for (auto i : children[now_id]) {
        if (file_system[i].type == "deleted") continue;
        ls_ids.push_back(i);
    }
    sort(ls_ids.begin(), ls_ids.end(), ls_cmp); // 排序(文件夹在前,文件在后,字典序)
    
    ll tmp_cnt = 0;
    for (auto i : ls_ids) {
        // 格式化输出 
        output(tabs, "");

        if (tmp_cnt == (ll)ls_ids.size() - 1)
            output("`", "");
        else
            output("|", "");

        output("-- ", "");

        fs now_file = file_system[i];
        if (have_space(now_file.name)) now_file.name = add_define(now_file.name);
        if (now_file.type == "dir") output(CYAN + BD, "");
        output(now_file.name + NC);
        
        if (now_file.type == "dir") {
            // 递归输出 
            tree_re(now_file.id, tab + 4);
        }

        if (now_file.type == "dir") tree_dir_cnt++;
        else tree_file_cnt++;
        tmp_cnt++;
    }
}

signed tree() { // 输出树状目录结构 
    tree_dir_cnt = 0;
    tree_file_cnt = 0;

    ll now_dir_id = get_now_id();
    output(CYAN + BD + "." + NC);
    tree_re(now_dir_id, 0);

    output();
    output(to_string(tree_dir_cnt) + " directories, " + to_string(tree_file_cnt) + " files");
    return 0;
}

signed rm_file(string filename) {
    split_dir(filename);

    string file_name = split_dirs[split_dirs.size() - 1];
    split_dirs.pop_back();

    // 判断文件名中是否只有“.”(不合法)
    bool flag = 1;
    for (auto i : file_name) {
        if (i != '.') {
            flag = 0;
            break;
        }
    }
    if (flag) {
        output_log("e", "The filename " + add_define(file_name) + " is illegal.");
        return 1;
    }

    // 获取文件的路径 
    vector<ll> file_dir_id;
    for (auto i : path) file_dir_id.push_back(i.id);
    for (auto i : split_dirs) {
        if (i == "..") {
            file_dir_id.pop_back();
            if (file_dir_id.size() == 0) {
                output_log("e", "The route is out of the root.");
                return 1;
            }
            continue;
        }
        bool flag = 0;
        for (auto j : children[file_dir_id[file_dir_id.size()-1]]) {
            auto now_f = file_system[j];
            if (now_f.type == "deleted") continue;
            if (now_f.type == "dir" && now_f.name == i) {
                file_dir_id.push_back(now_f.id);
                flag = 1;
                break;
            }
        }
        if (!flag) {
            output_log("e", "The dir " + add_define(i) + " is not exist!");
            return 1;
        }
    }

    // 查看是否已经存在 
    ll tmp_file;
    flag = 0;
    for (auto i : children[file_dir_id[file_dir_id.size()-1]]) {
        auto now_f = file_system[i];
        if (now_f.type == "deleted") continue;
        if (now_f.type == "file" && now_f.name == file_name) {
            flag = 1;
            tmp_file = now_f.id;
            break;
        }
    }
    if (!flag) { // 找不到 
        output_log("e", "The file " + add_define(file_name) + " is not exist!");
        return 1;
    }

    file_system[tmp_file].type = "deleted";

    return 0;
}

signed rm_dir(string dirname) {
    split_dir(dirname);

    string dir_name = split_dirs[split_dirs.size() - 1];
    split_dirs.pop_back();

    // 判断文件夹名中是否只有“.”(不合法)
    bool flag = 1;
    for (auto i : dir_name) {
        if (i != '.') {
            flag = 0;
            break;
        }
    }
    if (flag) {
        output_log("e", "The dirname " + add_define(dir_name) + " is illegal.");
        return 1;
    }

    // 获取文件夹的路径 
    vector<ll> file_dir_id;
    for (auto i : path) file_dir_id.push_back(i.id);
    for (auto i : split_dirs) {
        if (i == "..") {
            file_dir_id.pop_back();
            if (file_dir_id.size() == 0) {
                output_log("e", "The route is out of the root.");
                return 1;
            }
            continue;
        }
        bool flag = 0;
        for (auto j : children[file_dir_id[file_dir_id.size()-1]]) {
            auto now_f = file_system[j];
            if (now_f.type == "deleted") continue;
            if (now_f.type == "dir" && now_f.name == i) {
                file_dir_id.push_back(now_f.id);
                flag = 1;
                break;
            }
        }
        if (!flag) {
            output_log("e", "The dir " + add_define(i) + " is not exist!");
            return 1;
        }
    }

    // 查看是否已经存在 
    ll tmp_file;
    flag = 0;
    for (auto i : children[file_dir_id[file_dir_id.size()-1]]) {
        auto now_f = file_system[i];
        if (now_f.type == "deleted") continue;
        if (now_f.type == "dir" && now_f.name == dir_name) {
            flag = 1;
            tmp_file = now_f.id;
            break;
        }
    }
    if (!flag) { // 找不到 
        output_log("e", "The dir " + add_define(dir_name) + " is not exist!");
        return 1;
    }

    file_system[tmp_file].type = "deleted";

    return 0;
}

signed rm() { // 删除文件夹 / 文件 
    if (coms.size() <= 1) {
        output("RM");
        output("    Usage1: rm [filename]");
        output("    Delete a File");
        output("    Usage2: rm [dirname] -r");
        output("    Delete a Folder.");
        output("");
        return 0;
    }
    if (coms.size() == 2) {
        return rm_file(coms[1]);
    }
    if (coms[2] == "-r") {
        return rm_dir(coms[1]);
    }

    return 0;
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    if (fileExists("fs.fs")) {
        load_system();
    }
    else init_system();

    welcome_page();

    signed code = 0;

    while (true) {
        // 输入 
        string command;
        command = input(get_theme_input_text(code));
        confirm_input(command); // 将输出固定 
        
        // 执行码初始化 
        code = 0;

        split_command(&coms, command);

        if (coms.size() > 0) {
            string com_type = coms[0];
            if (com_type == "exit") {
                save_system();
                return 0;
            }
            else if (com_type == "help") {
                help();
            }
            else if (com_type == "whoami") {
                output(now_user);
            }
            else if (com_type == "whereami") {
                output(path_str);
            }
            else if (com_type == "clear") {
                cls();
            }
            else if (com_type == "neofetch") {
                code = neofetch();
            }
            else if (com_type == "ls") {
                code = ls();
            }
            else if (com_type == "mkdir") {
                code = mkdir();
            }
            else if (com_type == "cd") {
                code = cd();
            }
            else if (com_type == "touch") {
                code = touch();
            }
            else if (com_type == "cat") {
                code = cat();
            }
            else if (com_type == "echo") {
                code = echo();
            }
            else if (com_type == "tree") {
                code = tree();
            }
            else if (com_type == "rm") {
                code = rm();
            }
            else {
                output_log("e", get_theme_command_not_found_text());
                code = 1;
            }
        }
        if (code) wrong_cnt++;
        else wrong_cnt = 0;

        coms.clear(); // 释放空间 
    }

    return 0;
}
正文完
 0
syh
版权声明:本站原创文章,由 syh 于2025-10-23发表,共计21029字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(一条评论)
评论达人 LV.1
2025-10-24 14:54:24 回复

看起来报错了……额……直接复制文字好像没问题,避坑!不要点复制按钮!

 Windows  Chrome  中国浙江省宁波市移动
本站总字数:12w