文件系统(含源码)

实验内容

(1)在内存中开辟一个虚拟磁盘空间作为文件存储器, 在其上实现一个简单单用户文件系统。 在退出这个文件系统时,应将改虚拟文件系统保存到磁盘上, 以便下次可以将其恢复到内存的虚拟空间中。

(2)要求提供有关操作:format, create, rm, mkdir, rmdir, ls…

format:对文件存储器进行格式化,即按照文件系统对结构对虚拟磁盘空间进行布局,并在其上创建根目录以及用于管理文件存储空间等的数据结构。

mkdir:用于创建子目录;

rmdir:用于删除目录;

ls:用于显示目录;

cd:用于更改当前目录;

create:用于创建文件;

open:用于打开文件;

close:用于关闭文件;

write:用于写文件;

read:用于读文件

rm:用于删除文件。

实验原理

磁盘分区方式:

superblock super; // 超级块

FAT fat;           // FAT 表

bitmap bm;         // 磁盘块的位识图

inodemap im;       // 索引节点的位示图

inode inodes[INODE_SUM]; // 索引节点

inode root;               // 根目录的索引节点

block blocks[BLOCK_SUM]; // 其他索引节点

文件管理系统数据成员:

disk *diskptr;                          // 管理的虚拟磁盘

char *filepath;                         // 虚拟磁盘保存的位置

Buf wdir;                               // 工作目录

Buf wfile;                              // 文件操作缓冲区

Filebuf wprt[10];                       // 读写指针

int cur_blockid = 0;                    // 当前工作目录下的第一个盘块

int cur_inode = -1;                     // 当前工作目录下的索引节点

string workpath;

算法思路

用FAT表对磁盘块进行链接存储,索引节点和磁盘块均采用位示图的方式进行管理和分配根节点的索引节点号为 -1。

对文件或者目录进行修改删除时,均先切换到对应得目录下再进行操作,执行完毕后再返回原来得工作目录。

程序退出时先将虚拟磁盘写回到目录再退出。

编译执行命令: g++ -o main *.cpp && ./main

效果展示
 

列出当前目录项得文件和文件夹

72570cecc9874a5bbb5bb64fe5751e78.png

查看文件内容

50faf7640f1c4380af4b967be5e42c50.png

创建文件夹

841b6ed5610643638252ad8cf6823813.png

删除文件夹

1f938540c0e847c9bda8718bd1f73c0c.png

创建文件,并读写文件

02e54b2738e7494f89f0d8b6d980bafb.png

程序退出时保存原来的磁盘情况

fbee2c9dd7cd43a3aaba649bdfb946d6.png

保存的磁盘文件 16进制展示

超级块和部分FAT表

b3407737b9b74427af4f73d6383da5fd.png

部分根目录:

68aa6922e5e54ab79167608db4aeec9d.png

保存的部分文件内容

d865391f7a034249be6be7bbec8fc5d1.png

保存的磁盘文件大小:

dd57db7275244710835276cf3c7d095d.png

源文件

data.hpp

#pragma once
#define BLOCK_SIZE 512      // 磁盘块大小 512 B
#define ENTRIES_PER_BLOCK 4 // 每个磁盘块最多 4 个目录项
#define BLOCK_SUM 2048      // 磁盘块数
#define INODE_SUM 2048      // 索引节点数
#define DIRSTY 0            // 目录
#define FILESTY 1           // 普通文件
#define READ 1              // 读权限
#define WRITE 2             // 写权限

disk.hpp 

#pragma once
#include "data.hpp"

class superblock
{
public:
    int block_sum; // 盘块的数量
    int inode_sum; // 索引节点的数量
    superblock();
};

class FAT
{
public:
    int next[BLOCK_SUM]; // 链表法
    FAT();
};

class bitmap
{
public:
    char map[BLOCK_SUM / 8]; // 位示图
    bool empty(int no);      // 判断磁盘块是否分配
    void set(int);           // 将磁盘块置为已分配
    void free(int);          // 回收磁盘块
    bitmap();                // 初始化,全部为未分配
    int get();               // 申请一个磁盘块,成功则返回磁盘块号,否则返回 -1
};

class inodemap
{
public:
    char map[INODE_SUM / 8];
    bool empty(int no); // 返回当前节点是否为空
    void set(int);
    void free(int);
    inodemap(); // 初始化位示图
    int get();
};

class inode
{
public:
    int firstblock; // 第一个盘块号
    int type;       // 文件类型
};

class entry
{
public:
    bool flag;      // 目录项是否有效
    char name[123]; // 文件名
    int node;       // 索引节点号
    entry();
};

union block // 磁盘块,有两种组织形式,普通文件目录的形式
{
public:
    char data[BLOCK_SIZE];
    entry entries[ENTRIES_PER_BLOCK];
    block();
};

class disk
{
public:
    superblock super;
    FAT fat;
    bitmap bm;
    inodemap im;
    inode inodes[INODE_SUM];
    inode root;
    block blocks[BLOCK_SUM];
    disk();
};

FS.hpp

#pragma once
#include <string>
#include "disk.hpp"
using std::string;

union Buf // 缓存区,主要用于将目录、文件放到缓冲区处理
{
    entry entries[4096];
    char data[524288];
    block blocks[512];
    Buf();
};

class Filebuf // 读文件工作区,保存已经打开的文件及权限
{
public:
    bool flag = false;
    inode fnode;
    char mod = 0;
    char name[123];
    int fafblock; // 父目录的第一个盘块
};

class FS
{
    disk *diskptr;                          // 管理的虚拟磁盘
    char *filepath;                         // 虚拟磁盘保存的位置
    Buf wdir;                               // 工作目录
    Buf wfile;                              // 文件操作缓冲区
    Filebuf wprt[10];                       // 读写指针
    int cur_blockid = 0;                    // 当前工作目录下的第一个盘块
    int cur_inode = -1;                     // 当前工作目录下的索引节点
    void loadbuf(int firstblock, Buf &buf); // 载入缓冲区,可以执行工作目录和文件操作缓冲区的加载
    void writebackdir(int firstblock);      // 写回目录,常常在切换工作目录时写回
    void writebackfile(int firstblock);     // 写回文件,完成写文件后写回
    void delfile(int firstblock);           // 删除文件,包括目录和普通文件

    /*------------------ 原子操作(只允许在当前目录下操作) --------------------------------------*/
    int cd(const char *);      // 切换目录,原子操作,返回 1 表示没有该目录
    void create(const char *); // 创建文件
    void rmdir(const char *);  // 删除文件
    void mkdir(const char *);  // 创建目录
    void ls();                 // 列出当前目录下的文件和文件夹

    string getfolerpath(string);
    string getfilename(string);

public:
    string workpath;
    FS(char *file); // 对磁盘格式化,或导入已有的磁盘文件
    ~FS();          // 写回磁盘并保存

    /*------------------ 原子操作(只允许在当前目录下操作) --------------------------------------*/
    int open(const char *, char mod); // 返回一个 wptr,只能打开当前目录的文件
    void write(int, const char *);    // 写文件,第一个参数为写指针,第二个参数为写的内容
    void close(int);                  // 关闭文件
    void read(int);                   // 读文件,参数为读指针
    void rm(int);                     // 删除文件,需要先打开文件才能删除

    /*--------------------- 允许任何在路径下操作(只有changedir 会改变工作路径)------------------------------*/
    int changedir(const char *);                // 切换工作目录
    void createfile(const char *);              // 创建文件,参数为文件路径
    void removedir(const char *);               // 删除文件夹,参数为文件夹路径
    void list(const char *);                    // 列出指定目录下的文件和文件夹
    void makedir(const char *);                 // 创建文件夹,参数为文件夹路径
    int openfile(const char *, char);           // 打开指定文件,第二个参数为读写权限,返回读写指针
    void writefile(const char *, const char *); // 写文件,第一个参数为文件路径,第二个为写入内容
    void readfile(const char *);                // 读文件
    void removefile(const char *);              // 删除文件
};

disk.cpp 

#include "disk.hpp"
#include <cstring>
#include <iostream>
using namespace std;

bitmap::bitmap()
{
    memset(this->map, 0, sizeof(this->map));
}

bool bitmap::empty(int no)
{
    int k = no / 8;
    int i = no % 8;
    char binary = (1 << i);
    return (this->map[k] & binary) == 0;
}

void bitmap::set(int no)
{
    int k = no / 8;
    int i = no % 8;
    char binary = (1 << i);
    this->map[k] = this->map[k] | binary;
}

void bitmap::free(int no)
{
    int k = no / 8;
    int i = no % 8;
    char binary = (char(0xff) ^ (1 << i));
    this->map[k] = this->map[k] & binary;
}

int bitmap::get()
{
    for (int i = 0; i < INODE_SUM; i++)
    {
        if (this->empty(i))
        {
            this->set(i);
            return i;
        }
    }
    return -1;
}

inodemap::inodemap()
{
    memset(this->map, 0, sizeof(this->map));
}

void inodemap::set(int no)
{
    int k = no / 8;
    int i = no % 8;
    char binary = (1 << i);
    this->map[k] = this->map[k] | binary;
}

void inodemap::free(int no)
{
    int k = no / 8;
    int i = no % 8;
    char binary = (char(0xff) ^ (1 << i));
    this->map[k] = this->map[k] & binary;
}

int inodemap::get()
{
    for (int i = 0; i < INODE_SUM; i++)
    {
        if (this->empty(i))
        {
            this->set(i);
            return i;
        }
    }
    return -1;
}
bool inodemap::empty(int no)
{
    int k = no / 8;
    int i = no % 8;
    char binary = (1 << i);
    return (this->map[k] & binary) == 0;
}

superblock::superblock()
{
    this->block_sum = BLOCK_SUM;
    this->inode_sum = INODE_SUM;
}

FAT::FAT()
{
    memset(this->next, -1, sizeof(this->next));
}

disk::disk() // 初始化,主要初始化根目录
{
    char fname[] = "..";
    char curname[] = ".";
    this->root.firstblock = 0;
    this->root.type = DIRSTY;
    this->blocks[0].entries[1].flag = true;
    strcpy(this->blocks[0].entries[1].name, fname); // 根目录的父亲节点
    this->blocks[0].entries[1].node = -1;
    this->blocks[0].entries[0].flag = true;
    strcpy(this->blocks[0].entries[0].name, curname); // 当前目录
    this->blocks[0].entries[0].node = -1;
    this->blocks[0].entries[2].flag = false;
    this->bm.set(0);
    this->fat.next[0] = -1;
}

entry::entry()
{
    this->flag = false;
}

block::block()
{
    memset(this, 0, sizeof(block));
}

FS.cpp 

#include "FS.hpp"
#include <fstream>
#include <cstring>
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;

FS::FS(char *file)
{
    this->filepath = new char[1024];
    strcpy(this->filepath, file); // 保存磁盘路径
    this->diskptr = new disk;
    this->cur_blockid = this->diskptr->root.firstblock;
    this->cur_inode = -1;
    this->loadbuf(this->cur_blockid, wdir);
    this->workpath = "/";

    ifstream f1("file.txt", ios::in); // 初始化文件系统
    string path;
    while (f1 >> path)
    {
        this->makedir(path.c_str());
    }
    f1.close();
    path = "Documents/text.txt";
    this->createfile(path.c_str());
    f1.open("doc.txt", ios::in);
    char line[524288];
    string contxt = "";
    f1.getline(line, 524288, '\n');
    f1.clear();
    while (string(line) != "EOF")
    {
        contxt += string(line) + '\n';
        f1.getline(line, 1024, '\n');
        f1.clear();
    }

    this->writefile(path.c_str(), contxt.c_str());
    f1.close();
    ifstream fin(file, ios::in | ios::binary);
    if (!(fin.fail()))
    {
        fin.read((char *)(this->diskptr), sizeof(disk)); // 导入已有磁盘内容
    }
    fin.close();
    this->cur_blockid = this->diskptr->root.firstblock;
    this->cur_inode = -1;
    this->loadbuf(this->cur_blockid, wdir);
    this->workpath = "/"; // 切换到根目录
}

FS::~FS()
{
    this->writebackdir(this->cur_blockid);
    ofstream fout(this->filepath, ios::out | ios::binary);
    if (fout.fail())
    {
        cout << "fail";
    }
    else
        fout.write((char *)(this->diskptr), sizeof(disk)); // 写回磁盘文件保存
    fout.close();
    delete[] this->filepath;
    delete this->diskptr;
}

void FS::loadbuf(int firstblock, Buf &buf)
{
    int i = 0;
    int cur = firstblock;
    while (cur != -1)
    {
        memcpy(&(buf.blocks[i]), &(this->diskptr->blocks[cur]), sizeof(block)); // 将文件读入缓冲区
        cur = this->diskptr->fat.next[cur];
        i++;
    }
}

void FS::ls()
{
    cout.setf(ios::left);
    cout << setw(46) << setfill('-') << "" << '\n';
    cout << setfill(' ') << setw(30) << "| name" << setw(15) << "| type"
         << "|" << '\n';
    cout << setw(46) << setfill('-') << "" << '\n';
    for (int i = 2; i < 4096; i++)
    {
        if (this->wdir.entries[i].flag) // 输出有效目录项
        {
            cout << setfill(' ') << "| ";
            cout << setw(28) << this->wdir.entries[i].name;
            cout << "| ";
            cout << setw(13);
            if (this->diskptr->inodes[this->wdir.entries[i].node].type == DIRSTY)
            {
                cout << "directory"
                     << "|" << '\n';
            }
            else
            {
                cout << "file"
                     << "|" << '\n';
            }
            cout << setw(46) << setfill('-') << "" << '\n';
        }
    }
}

void FS::mkdir(const char *dirname)
{
    for (int i = 0; i < 4096; i++)
    {
        if (this->wdir.entries[i].flag && this->diskptr->inodes[this->wdir.entries[i].node].type == DIRSTY)
        {
            if (strcmp(dirname, this->wdir.entries[i].name) == 0)
            {
                return;
            }
        }
    }
    char fname[] = "..";
    char curname[] = ".";
    int i = 0;
    for (i = 0; this->wdir.entries[i].flag; i++)
        ;
    this->wdir.entries[i].node = this->diskptr->im.get(); // 申请索引节点
    int tmpi = this->wdir.entries[i].node;
    if (tmpi == -1)
    {
        cout << "make directory err\n";
        return;
    }
    this->diskptr->inodes[tmpi].firstblock = this->diskptr->bm.get(); // 申请磁盘块
    int tmpb = this->diskptr->inodes[tmpi].firstblock;
    if (tmpb == -1)
    {
        this->diskptr->im.free(tmpi);
        cout << "make directory err\n";
        return;
    }
    this->wdir.entries[i].flag = true; // 创建目录项
    strcpy(this->wdir.entries[i].name, dirname);
    this->diskptr->inodes[tmpi].type = DIRSTY;
    this->diskptr->blocks[tmpb].entries[1].flag = true;
    strcpy(this->diskptr->blocks[tmpb].entries[1].name, fname); // 创建父目录
    this->diskptr->blocks[tmpb].entries[1].node = this->cur_inode;
    this->diskptr->blocks[tmpb].entries[0].flag = true;
    strcpy(this->diskptr->blocks[tmpb].entries[0].name, curname); // 创建当前目录
    this->diskptr->blocks[tmpb].entries[0].node = tmpi;
    this->diskptr->blocks[tmpb].entries[2].flag = false;
}

Buf::Buf()
{
    memset(this, 0, sizeof(Buf));
}

void FS::writebackdir(int firstblock)
{
    int cur = firstblock;
    int k = 0;
    for (int i = 0; i < 4096; i++)
    {
        if (this->wdir.entries[i].flag) // 将有效目录项写回
        {
            if (k < ENTRIES_PER_BLOCK)
            {
                this->diskptr->blocks[cur].entries[k] = this->wdir.entries[i];
            }
            else
            {
                if (this->diskptr->fat.next[cur] != -1)
                {
                    cur = this->diskptr->fat.next[cur];
                    k = 0;
                    this->diskptr->blocks[cur].entries[k] = this->wdir.entries[i];
                }
                else
                {
                    this->diskptr->fat.next[cur] = this->diskptr->bm.get(); // 空间不足申请新的磁盘块
                    if (this->diskptr->fat.next[cur] == -1)                 // 磁盘已满
                    {
                        cout << "write back err!\n";
                        return;
                    }
                    cur = this->diskptr->fat.next[cur];
                    memset((this->diskptr->blocks[cur].data), 0, sizeof(block));
                    k = 0;
                    this->diskptr->blocks[cur].entries[k] = this->wdir.entries[i];
                }
            }
            k++;
        }
    }
    for (; k < ENTRIES_PER_BLOCK; k++) // 删除剩余无效目录项
    {
        this->diskptr->blocks[cur].entries[k].flag = false;
    }
    cur = this->diskptr->fat.next[cur];
    while (cur != -1) // 释放多余的磁盘块
    {
        int nxt = this->diskptr->fat.next[cur];
        this->diskptr->bm.free(cur);
        this->diskptr->fat.next[cur] = -1;
        cur = nxt;
    }
}

void FS::writebackfile(int firstblock)
{
    int cur = firstblock;
    int len = strlen(wfile.data) + 1;
    for (int i = 0; i < (len + BLOCK_SIZE) / BLOCK_SIZE; i++)
    {
        memcpy(this->diskptr->blocks[cur].data, &(wfile.blocks[i]), sizeof(block));
        int tmp = this->diskptr->fat.next[cur];
        // cout << tmp << '\n';
        if (tmp == -1)
        {
            this->diskptr->fat.next[cur] = this->diskptr->bm.get();
            cur = this->diskptr->fat.next[cur];
        }
        else
        {
            cur = tmp;
        }
        // cout << cur << '\n';
    }
    while (cur != -1)
    {
        int nxt = this->diskptr->fat.next[cur];
        this->diskptr->bm.free(cur);
        this->diskptr->fat.next[cur] = -1;
        cur = nxt;
    }
}

void FS::delfile(int firstblock) // 释放磁盘块
{
    int cur = firstblock;
    while (cur != -1)
    {
        int nxt = this->diskptr->fat.next[cur];
        this->diskptr->fat.next[cur] = -1;
        this->diskptr->bm.free(cur);
        cur = nxt;
    }
}

void FS::rmdir(const char *file)
{
    for (int i = 2; i < 4096; i++)
    {
        if (!(this->wdir.entries[i].flag))
            continue;
        if (strcmp(file, this->wdir.entries[i].name) == 0 && this->diskptr->inodes[this->wdir.entries[i].node].type == DIRSTY)
        {
            this->delfile(this->diskptr->inodes[this->wdir.entries[i].node].firstblock); // 释放磁盘块
            this->wdir.entries[i].flag = false;                                          // 将目录项置为无效
            return;
        }
    }
    if (file != "." && file != "..")
        cout << "no such dir:" << this->workpath << "/" << file << '\n';
}

int FS::cd(const char *file)
{
    this->writebackdir(this->cur_blockid);
    for (int i = 0; i < 4096; i++)
    {
        if (!(this->wdir.entries[i].flag))
            continue;
        if (strcmp(file, this->wdir.entries[i].name) == 0 && this->diskptr->inodes[this->wdir.entries[i].node].type == DIRSTY)
        {
            this->cur_inode = this->wdir.entries[i].node;
            if (this->cur_inode != -1)
            {
                this->cur_blockid = this->diskptr->inodes[this->cur_inode].firstblock;
            }
            else
            {
                this->cur_blockid = this->diskptr->root.firstblock;
            }
            memset(this->wdir.data, 0, sizeof(this->wdir));
            this->loadbuf(this->cur_blockid, this->wdir);
            return 0;
        }
    }
    return 1;
}

void FS::create(const char *file)
{
    for (int i = 0; i < 4096; i++)
    {
        if (!(this->wdir.entries[i].flag))
            continue;
        if (strcmp(file, this->wdir.entries[i].name) == 0 && this->diskptr->inodes[this->wdir.entries[i].node].type == FILESTY)
        {
            cout << "It is already exit the file:";
            if (this->workpath != "/")
                cout << this->workpath;
            cout << "/" << file << '\n';
            return;
        }
    }
    for (int i = 0; i < 4096; i++)
    {
        if (!(this->wdir.entries[i].flag))
        {
            this->wdir.entries[i].node = this->diskptr->im.get();
            if (this->wdir.entries[i].node == -1)
            {
                cout << "create file err\n";
                return;
            }
            this->diskptr->inodes[this->wdir.entries[i].node].firstblock = this->diskptr->bm.get();
            if (this->diskptr->inodes[this->wdir.entries[i].node].firstblock == -1)
            {
                this->diskptr->im.free(this->wdir.entries[i].node);
                cout << "create file err\n";
                return;
            }
            this->wdir.entries[i].flag = true;
            strcpy(this->wdir.entries[i].name, file);
            this->diskptr->inodes[this->wdir.entries[i].node].type = FILESTY;
            return;
        }
    }
}

int FS::open(const char *file, char mod)
{
    int fb = -1;
    for (int i = 0; i < 4096; i++)
    {
        if (!(this->wdir.entries[i].flag))
            continue;
        if (strcmp(file, this->wdir.entries[i].name) == 0 && this->diskptr->inodes[this->wdir.entries[i].node].type == FILESTY)
        {
            fb = this->wdir.entries[i].node;
            break;
        }
    }
    if (fb == -1) // 没有找到文件
    {
        cout << "no such file:";
        if (this->workpath != "/")
            cout << this->workpath;
        cout << "/" << file << '\n';
        return -1;
    }
    for (int i = 0; i < 10; i++) // 检查文件是否已打开
    {
        if (this->wprt[i].flag)
        {
            if (strcmp(this->wprt[i].name, file) == 0)
            {
                this->wprt[i].mod = mod;
                return i;
            }
        }
    }
    for (int i = 0; i < 10; i++)
    {
        if (!(this->wprt[i].flag))
        {
            this->wprt[i].flag = true;
            this->wprt[i].fnode = this->diskptr->inodes[fb];
            this->wprt[i].mod = mod;
            this->wprt[i].fafblock = this->cur_blockid;
            strcpy(this->wprt[i].name, file);
            return i;
        }
    }
    return -1; // 读写指针已满
}

void FS::close(int wprtid)
{
    if (!(this->wprt[wprtid].flag))
        return;
    this->writebackfile(this->wprt[wprtid].fnode.firstblock); // 写回文件
    this->wprt[wprtid].flag = false;                          // 删除读写指针
}

void FS::write(int wptrid, const char *str)
{
    if (!(this->wprt[wptrid].flag))
        return;
    if ((this->wprt[wptrid].mod & WRITE) == 0)
        return;
    strcpy(this->wfile.data, str);
    // cout << this->wfile.data;
    this->writebackfile(this->wprt[wptrid].fnode.firstblock);
}

void FS::read(int wptrid)
{
    if (!(this->wprt[wptrid].flag))
        return;
    if ((this->wprt[wptrid].mod & READ) == 0)
        return;
    this->loadbuf(this->wprt[wptrid].fnode.firstblock, this->wfile); // 读入缓冲区
    cout << wfile.data;
}

void FS::rm(int wptrid)
{
    if (!(this->wprt[wptrid].flag))
        return;
    this->writebackdir(this->cur_blockid);
    this->loadbuf(this->wprt[wptrid].fafblock, this->wdir);
    int i;
    for (i = 0; i < 4096; i++)
    {
        if (!(this->wdir.entries[i].flag))
            continue;
        if (strcmp(this->wprt[wptrid].name, this->wdir.entries[i].name) == 0 && this->diskptr->inodes[this->wdir.entries[i].node].type == FILESTY)
        {
            this->wdir.entries[i].flag = false;                 // 删除目录项
            this->delfile(this->wprt[wptrid].fnode.firstblock); // 释放磁盘块
            this->diskptr->im.free(this->wdir.entries[i].node); // 释放索引节点
            break;
        }
    }
    this->writebackdir(this->wprt[wptrid].fafblock);
    this->loadbuf(this->cur_blockid, this->wdir);
    this->wprt[wptrid].flag = false;
}

int FS::changedir(const char *path)
{
    string tmppath = this->workpath;
    if (path[0] == '/') // 判断是否是根目录
    {
        this->writebackdir(this->cur_blockid);
        this->cur_blockid = this->diskptr->root.firstblock;
        this->cur_inode = -1;
        this->loadbuf(this->diskptr->root.firstblock, this->wdir);
        this->workpath = "/";
    }
    char pattern[] = "/";
    char tmpath[200];
    strcpy(tmpath, path);
    char *p = strtok(tmpath, pattern);
    char fname[] = "..";
    char curname[] = ".";
    while (p)
    {
        if (cd(p))
        {
            cout << "no such file or dirctory :" << path << '\n';
            changedir(tmppath.c_str());
            return 1;
        }
        else // 更新工作路径
        {
            if (strcmp(p, fname) == 0) // 父目录
            {
                int index = this->workpath.find_last_of("/");
                this->workpath = this->workpath.substr(0, index);
            }
            else if (strcmp(p, curname) != 0) // 切换到子目录
            {
                if (this->workpath.length() > 1)
                    this->workpath += "/";
                this->workpath += p;
            }
            if (this->cur_inode == -1) // 根目录
            {
                this->workpath = "/";
            }
        }
        p = strtok(NULL, pattern); // 依次进入各个文件路径的分量
    }
    return 0;
}

void FS::createfile(const char *file)
{
    string tmppath = this->workpath;
    string filepath = file;
    string folderpath = getfolerpath(filepath);
    if (changedir(folderpath.c_str())) // 切换到文件所在目录
    {
        return;
    }
    string filename = getfilename(filepath);
    create(filename.c_str());   // 创建文件
    changedir(tmppath.c_str()); // 返回原来的工作路径
}

void FS::removedir(const char *path)
{
    string tmppath = this->workpath;
    string filepath = path;
    if (changedir(path)) // 切换到要删除的文件下
    {
        return;
    }
    if (this->workpath != tmppath.substr(0, this->workpath.size())) // 判断是否是原来工作路径的父目录或者当前目录,有点粗糙但安全
    {
        for (int i = 2; i < 4096; i++)
        {
            if (this->wdir.entries[i].flag)
            {
                if (this->diskptr->inodes[this->wdir.entries[i].node].type == DIRSTY)
                    removedir((string(".") + "/" + this->wdir.entries[i].name).c_str());
                else
                {
                    removefile((string(".") + "/" + this->wdir.entries[i].name).c_str());
                }
            }
        }
        changedir(tmppath.c_str());
        string folderpath = getfolerpath(filepath);
        if (changedir(folderpath.c_str())) // 进入父目录
        {
            return;
        }
        string subpname = getfilename(filepath);
        rmdir(subpname.c_str()); // 删除文件夹
    }
    else
    {
        cout << "can't not remove the father directory or current path!\n";
    }
    changedir(tmppath.c_str()); // 切换回原来的工作路径
}

void FS::list(const char *path)
{
    string tmppath = this->workpath;
    if (changedir(path))
    {
        return;
    }
    ls();
    changedir(tmppath.c_str());
}

void FS::makedir(const char *path)
{
    string tmppath = this->workpath;
    string filepath = path;
    string folderpath = getfolerpath(filepath);
    if (changedir(folderpath.c_str()))
    {
        return;
    }
    string subpname = getfilename(filepath);
    mkdir(subpname.c_str());
    changedir(tmppath.c_str());
}

int FS::openfile(const char *path, char mod)
{
    string tmppath = this->workpath;
    string filepath = path;
    string folderpath = getfolerpath(filepath);
    if (changedir(folderpath.c_str()))
    {
        return -1;
    }
    string filename = getfilename(filepath);
    int wptr = open(filename.c_str(), mod);
    changedir(tmppath.c_str());
    return wptr;
}

void FS::writefile(const char *path, const char *context)
{
    string tmppath = this->workpath;
    string filepath = path;
    string folderpath = getfolerpath(filepath);
    if (changedir(folderpath.c_str()))
    {
        return;
    }
    string subpname = getfilename(filepath);
    int wptr = open(subpname.c_str(), WRITE);
    write(wptr, context);
    close(wptr);
    changedir(tmppath.c_str());
}

void FS::readfile(const char *path)
{
    string tmppath = this->workpath;
    string filepath = path;
    string folderpath = getfolerpath(filepath);
    if (changedir(folderpath.c_str()))
    {
        return;
    }
    string subpname = getfilename(filepath);
    int wptr = open(subpname.c_str(), READ);
    read(wptr);
    close(wptr);
    changedir(tmppath.c_str());
}

void FS::removefile(const char *path)
{
    string tmppath = this->workpath;
    string filepath = path;
    string folderpath = getfolerpath(filepath);
    if (changedir(folderpath.c_str()))
    {
        return;
    }
    string subpname = getfilename(filepath);
    int wptr = open(subpname.c_str(), WRITE);
    if (wptr == -1)
    {
        cout << "open file err\n";
        return;
    }
    rm(wptr);
    changedir(tmppath.c_str());
}

string FS::getfolerpath(string path)
{
    int index = path.find_last_of("/");
    string folderPath = "";
    if (path[0] != '/' || path[0] != '.')
    {
        folderPath = ".";
    }
    if (index < path.length() || path[index - 1] == '.')
    {
        folderPath += "/";
        folderPath += path.substr(0, index);
    }
    return folderPath;
}

string FS::getfilename(string path)
{
    int index = path.find_last_of("/");
    return path.substr(index + 1, -1);
}

main.cpp

#include <iostream>
#include <string>
#include "FS.hpp"
using namespace std;

char file[] = "./FileSys";
FS fs(file);

int main()
{
    cout << "/>";
    string op;
    string contxt;
    string par;
    int wptr;
    while (cin >> op)
    {
        if (op == "ls")
        {
            char a = getchar();
            if (a == '\n')
            {
                char path[] = ".";
                fs.list(path);
            }
            else
            {
                cin >> par;
                fs.list(par.c_str());
            }
        }
        if (op == "cd")
        {
            cin >> par;
            fs.changedir(par.c_str());
        }
        if (op == "touch")
        {
            cin >> par;
            fs.createfile(par.c_str());
        }
        if (op == "mkdir")
        {
            cin >> par;
            fs.makedir(par.c_str());
        }
        if (op == "rmdir")
        {
            cin >> par;
            fs.removedir(par.c_str());
        }
        if (op == "open")
        {
            cin >> par;
            wptr = fs.openfile(par.c_str(), READ | WRITE);
        }
        if (op == "write")
        {
            cin >> par;
            char line[524288];
            contxt = "";
            cin.get();
            cin.getline(line, 524288, '\n');
            cin.clear();
            while (string(line) != "EOF")
            {
                contxt += string(line) + '\n';
                cin.getline(line, 524288, '\n');
                cin.clear();
            }
            // cout << contxt;
            fs.writefile(par.c_str(), contxt.c_str());
        }
        if (op == "cat")
        {
            cin >> par;
            fs.readfile(par.c_str());
        }
        if (op == "rm")
        {
            cin >> par;
            fs.removefile(par.c_str());
        }
        if (op == "quit")
            break;
        if (op == "close")
        {
            fs.close(wptr);
        }
        cout << fs.workpath << ">";
    }
}

程序在大文件链接时又点问题,欢迎自行优化

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值