Linux文件系统树模拟器

Linux文件系统的逻辑结构体是一个普通的树。假设文件系统只有目录DIR和普通文件FILE。DIR可拥有可变数量子节点。同一父亲节点称为兄弟节点。路径以/开头为绝对路径。否则是以当前目录(CWD)的相对路径。
可以用二叉树来实现普通的树

#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libgen.h>
typedef struct Node{
    char name[64];
    char type;
    struct Node *childPtr, *siblingPtr, *parentPtr;
}Node;
static Node *root, *cwd;
bool ap = false;
int deep = 0;
int num = 0;
static char line[128];
char command[16], pathname[64];
char dname[64], bname[64];
int mkdir_(),rmdir_(),cd(), ls(),pwd(),creat_(),rm(),save(),reload(),menu(),quit();
char *commad_list[] = {"mkdir", "rmdir", "cd", "ls", "pwd", "creat", "rm", "save", "reload", "menu", "quit", NULL};
int (*f_ptr[])() = { (int (*)())mkdir_, rmdir_, cd, ls, pwd, creat_, rm, save, reload, menu, quit };
void get_dir_base(){
    char temp[128];
    ap = false;
    if(pathname[0] == '/') ap = true;
    strcpy(temp, pathname);
    strcpy(dname, dirname(temp));
    strcpy(temp, pathname);
    strcpy(bname, basename(temp));
}
void initialie(){
    root = (Node*)malloc(sizeof(Node));
    root->siblingPtr = root;
    root->parentPtr = root;
    root->childPtr = NULL;
    root->name[0] = '/';
    root->name[1] = '\0';
    root->type = 'D';
    cwd = root;
}
int findCommand(){
    int i = 0;
    while(commad_list[i]){
        if(!strcmp(command, commad_list[i])) return i;
        i++;
    }
    return -1;
}
void getCommand(){
    bzero(line, 128);
    read(STDIN_FILENO, line, 128);
    bzero(command, 128);
    line[strlen(line) - 1] = '\0';//kill \n
    sscanf(line, "%s %s", command, pathname);
    int idx = findCommand();
    if(idx == -1) return;
    f_ptr[idx]();
}
Node* mk_Node(char type){
    Node *p = (Node*)malloc(sizeof(Node));
    strcpy(p->name, bname);
    p->type = type;
    p->childPtr = NULL;
    p->siblingPtr = NULL;
    return p;
}
Node* find_d(){
    get_dir_base();
    char *s;
    Node* per ;
    per = cwd;
    if(ap) per = root;
    Node* cur = per->childPtr;
    if(strcmp(dname, ".")){
    s = strtok(dname, "/");
    while(s){
        while(cur){
            if(!strcmp(s, cur->name) && cur->type == 'D'){
                per = cur;
                break;
            };
            cur = cur->siblingPtr;
        }
            if(cur == NULL) return NULL;
            cur = per->childPtr;
            s = strtok(NULL, "/");
        }
    }
    return per;
}
int _pwd(Node* p, int fd){
    char *s[deep];
    char tmp[1024];
    bzero(tmp, 1024);
    Node* cur = p;
    int i = 0;
    int off = 0;
    for(;i < deep && cur != root; i++){
        s[i] = cur->name;
        cur = cur->parentPtr;
    }
    tmp[off++] = '/';
    while(i--){
        int size = strlen(s[i]);
        memcpy(tmp + off, s[i], size);
        off += size;
        if(i) tmp[off++] = '/';
    }
    tmp[off++] = '\n';
    tmp[off] = '\0';
    write(fd, tmp, strlen(tmp));
    return 0;
}
int pwd(){
    return _pwd(cwd, STDOUT_FILENO);
}
int save(){
    int fd = open(pathname, O_RDWR|O_CREAT|O_TRUNC, 0666);
    Node *stack[num];
    Node* cur = root->childPtr;
    if(cur == NULL) return -1;
    int i = 0;
    stack[i++] = cur;
    while(i > 0){
        cur = stack[--i];
        write(fd, &cur->type, 1);
        write(fd, "  ", 2);
        _pwd(cur, fd);
        if(cur->siblingPtr) stack[i++] = cur->siblingPtr;
        if(cur->childPtr) stack[i++] = cur->childPtr;
    }
    close(fd);
    return 0;
}
int cd(){
    Node* per = find_d();
    Node* cur = per->childPtr;
    while(cur){
         if(!strcmp(bname, cur->name) && cur->type == 'D') break;
         cur = cur->siblingPtr;
    }
    if(cur == NULL) return -1;
    cwd = cur;
    return 0;
}
int _rmdf(char type){
    Node* per = find_d();
    Node* cur = per->childPtr;
    while(cur){
         if(!strcmp(bname, cur->name) && cur->type == type) break;
         per = cur;
         cur = cur->siblingPtr;
    }
    if(cur == NULL) return -1; 
    if(type == 'D' && cur->childPtr != NULL) return -1;
    if(per->childPtr == cur){
         free(cur);
         per->childPtr = NULL;
    }else{
        per->siblingPtr = cur->siblingPtr;
        free(cur);
    }
    return 0;
}
int ls(){
    Node* per = find_d();
    if(per == NULL) return -1;
    Node* cur = per->childPtr;
    while(cur){
        printf("type : %c name : %s \n", cur->type, cur->name);
        cur = cur->siblingPtr;
    }
    return 0;
}
int rmdir_(){
    if(!_rmdf('D')){
        deep--;
        return 0;
    }
    return -1;
}
int rm(){
    return _rmdf('F');
}
int _mkdf(char type){
    Node* per = find_d();
    if(per == NULL) return -1;
    Node* cur = per->childPtr;
    if(cur == NULL){
            per->childPtr = mk_Node(type);
            per->childPtr->parentPtr = per;
            num++;
            return 0;
    }
     while(cur){
         if(!strcmp(bname, cur->name) && cur->type == 'D') return -1;
         per = cur;
         cur = cur->siblingPtr;
    }
        per->siblingPtr = mk_Node(type);
        per->siblingPtr->parentPtr = per->parentPtr;
        num++;
        return 0;
}
int reload(){
    struct stat st;
    if(stat(pathname, &st) == -1) return -1;
    int fd = open(pathname, O_RDONLY);
    char buf[st.st_size];
    char tmp[128];
    char type;
    int i = 0;
    int off = 0;
    while((i = read(fd, buf + off, st.st_size - off)) > 0){
        off += i;
    }
    close(fd);
    i = 0;
    int j = 0;
    while(i < off){
        if(buf[i] != '\n') i++;
        else{
            bzero(tmp, 128);
            memcpy(tmp, buf + j, i - j);
            sscanf(tmp, "%c %s",&type , pathname);
            if(type == 'D') mkdir_();
            else if(type == 'F') creat_();
            else return -1;
            j = ++i;
        }
    }
    return 0;
}
int menu(){
    printf("mkdir  dirpath\n");
    printf("rmdir  dirpath\n");
    printf("cd     dirpath\n");
    printf("ls     dirname\n");
    printf("pwd \n");
    printf("cteat  filepath\n");
    printf("rm     filepath\n");
    printf("save   filepath\n");
    printf("reload filepath\n");
    printf("quit\n");
    return 0;
}
int creat_(){
    return  _mkdf('F');
}
int mkdir_(){
    if(!_mkdf('D')){
        deep++;
        return 0;
    }
    return -1;
}
int quit(){
    sprintf(pathname, "text.txt");
    save();
    exit(0);
    return 0;
}
void show(){
    printf("welcom to !\n");
    printf("command menu show commands\n");
}
int main()
{
    //scanf("%*[^\n]%*c");
    initialie();
    show();
    while(1){
        //fflush(stdin);
        getCommand();
    }
    return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值