孤问尘
孤问尘
Published on 2025-01-13 / 0 Visits
0
0

创建一个自己的轻型操作系统

创建属于自己的操作系统,拥有自己的命令以及提示

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_FILES 255
#define MAX_OPEN_FILES 10
#define MAX_PATH_LENGTH 1000 // 最大路径长度
#define BLOCK_SIZE 128
#define DISK_ROWS 10
#define DISK_COLS 10
#define DISK_SIZE 1024  // 整个磁盘大小为 1024 块
#define MAX_FILE_NAME 255  // 最大文件名长度


typedef struct {
    char fileName[MAX_FILE_NAME];
    int startBlockRow;
    int startBlockCol;
    int length;
    int isDirectory;
    int startBlock;
} DirectoryEntry;

typedef struct Directory {
    char name[256];
    int entryCount;
    DirectoryEntry entries[MAX_FILES];
    struct Directory *parent;
} Directory;

typedef struct {
    int nextBlockRow;
    int nextBlockCol;
    int nextBlock;
} FATEntry;

typedef struct {
    Directory root;
    Directory rootDirectory;    
    Directory *currentDirectory;
    FATEntry FAT[DISK_ROWS][DISK_COLS];
    int bitMap[DISK_ROWS][DISK_COLS];
    char disk[DISK_ROWS][DISK_COLS][BLOCK_SIZE];
    char currentPath[1024];

} FileSystem;

typedef struct {
    int fileDescriptor;
    char fileName[256];
    int index;
    int position;
} OpenFile;

FileSystem fs;
OpenFile openFiles[MAX_OPEN_FILES];
int openFileCount = 0;

void writeFileData(const char *fileName, const char *data);

void updatePath() {
    // 初始化路径为根目录
    char path[MAX_PATH_LENGTH] = "";

    // 指向当前目录的指针
    Directory *currentDir = fs.currentDirectory;

    // 从当前目录向上遍历,直到根目录
    while (currentDir->parent != NULL) {
        // 临时字符串用于拼接路径
        char temp[MAX_PATH_LENGTH];
        strcpy(temp, "/");
        strcat(temp, currentDir->name);
        strcat(temp, path);
        strcpy(path, temp);
        currentDir = currentDir->parent;
    }

    // 如果当前路径是根目录,直接设置为"/"
    if (strcmp(path, "") == 0) {
        strcpy(path, "/");
    }

    strcpy(fs.currentPath, path);
}



void printPrompt() {
    printf("fs %s > ", fs.currentPath);
    fflush(stdout);
}

void format() {
    fs.root.entryCount = 0;
    fs.root.parent = NULL;
    strcpy(fs.root.name, "");
    fs.currentDirectory = &fs.root;
    memset(fs.FAT, -1, sizeof(fs.FAT));
    memset(fs.bitMap, 0, sizeof(fs.bitMap));
    updatePath();
}

void mkdir(const char *dirName) {
    if (!dirName) {
        printf("Directory name not provided.\n");
        printPrompt();
        return;
    }

    if (fs.currentDirectory->entryCount >= MAX_FILES) {
        printf("Directory limit reached.\n");
        printPrompt();
        return;
    }

    for (int i = 0; i < fs.currentDirectory->entryCount; i++) {
        if (strcmp(fs.currentDirectory->entries[i].fileName, dirName) == 0 && fs.currentDirectory->entries[i].isDirectory) {
            printf("Directory already exists: %s\n", dirName);
            printPrompt();
            return;
        }
    }

    DirectoryEntry newEntry;
    strcpy(newEntry.fileName, dirName);
    newEntry.startBlockRow = -1;
    newEntry.startBlockCol = -1;
    newEntry.length = 0;
    newEntry.isDirectory = 1;
    fs.currentDirectory->entries[fs.currentDirectory->entryCount++] = newEntry;
    printf("Directory created: %s\n", dirName);
    printPrompt();
}

void rmdir(const char *dirName) {
    if (!dirName) {
        printf("Directory name not provided.\n");
        printPrompt();
        return;
    }

    for (int i = 0; i < fs.currentDirectory->entryCount; i++) {
        if (strcmp(fs.currentDirectory->entries[i].fileName, dirName) == 0 && fs.currentDirectory->entries[i].isDirectory) {
            for (int j = i; j < fs.currentDirectory->entryCount - 1; j++) {
                fs.currentDirectory->entries[j] = fs.currentDirectory->entries[j + 1];
            }
            fs.currentDirectory->entryCount--;
            printf("Directory deleted: %s\n", dirName);
            printPrompt();
            return;
        }
    }

    printf("Directory not found: %s\n", dirName);
    printPrompt();
}

void ls() {
    // Print special directories . and ..
    printf(".\n");
    printf("..\n");

    // Print regular directory entries
    for (int i = 0; i < fs.currentDirectory->entryCount; i++) {
        if (fs.currentDirectory->entries[i].isDirectory) {
            printf("DIR ");
        } else {
            printf("FILE ");
        }
        printf("%s\n", fs.currentDirectory->entries[i].fileName);
    }
    printPrompt();
}


void cd(const char *dirName) {
    if (!dirName) {
        printf("Directory name not provided.\n");
        printPrompt();
        return;
    }

    if (strcmp(dirName, "..") == 0) {
        if (fs.currentDirectory->parent != NULL) {
            fs.currentDirectory = fs.currentDirectory->parent;
        }
        updatePath();
        printPrompt();
        return;
    }

    for (int i = 0; i < fs.currentDirectory->entryCount; i++) {
        if (strcmp(fs.currentDirectory->entries[i].fileName, dirName) == 0 && fs.currentDirectory->entries[i].isDirectory) {
            Directory *subDir = (Directory *)malloc(sizeof(Directory));
            if (subDir == NULL) {
                printf("Memory allocation failed.\n");
                return;
            }
            subDir->entryCount = 0;
            subDir->parent = fs.currentDirectory;
            strcpy(subDir->name, dirName);
            fs.currentDirectory = subDir;
            updatePath();
            printPrompt();
            return;
        }
    }

    printf("Directory not found: %s\n", dirName);
    printPrompt();
}

void create(const char *fileName) {
    if (!fileName) {
        printf("File name not provided.\n");
        printPrompt();
        return;
    }

    if (fs.currentDirectory->entryCount >= MAX_FILES) {
        printf("Directory limit reached.\n");
        printPrompt();
        return;
    }

    for (int i = 0; i < fs.currentDirectory->entryCount; i++) {
        if (strcmp(fs.currentDirectory->entries[i].fileName, fileName) == 0) {
            printf("File already exists: %s\n", fileName);
            printPrompt();
            return;
        }
    }

    DirectoryEntry newEntry;
    strcpy(newEntry.fileName, fileName);
    newEntry.startBlockRow = -1;
    newEntry.startBlockCol = -1;
    newEntry.length = 0;
    newEntry.isDirectory = 0;
    fs.currentDirectory->entries[fs.currentDirectory->entryCount++] = newEntry;
    printf("File created: %s\n", fileName);
    printPrompt();
}

void rm(const char *fileName) {
    if (!fileName) {
        printf("File name not provided.\n");
        printPrompt();
        return;
    }

    for (int i = 0; i < fs.currentDirectory->entryCount; i++) {
        if (strcmp(fs.currentDirectory->entries[i].fileName, fileName) == 0 && !fs.currentDirectory->entries[i].isDirectory) {
            int currentBlockRow = fs.currentDirectory->entries[i].startBlockRow;
            int currentBlockCol = fs.currentDirectory->entries[i].startBlockCol;
            while (currentBlockRow != -1 && currentBlockCol != -1) {
                int nextBlockRow = fs.FAT[currentBlockRow][currentBlockCol].nextBlockRow;
                int nextBlockCol = fs.FAT[currentBlockRow][currentBlockCol].nextBlockCol;
                fs.bitMap[currentBlockRow][currentBlockCol] = 0;
                currentBlockRow = nextBlockRow;
                currentBlockCol = nextBlockCol;
            }

            for (int j = i; j < fs.currentDirectory->entryCount - 1; j++) {
                fs.currentDirectory->entries[j] = fs.currentDirectory->entries[j + 1];
            }
            fs.currentDirectory->entryCount--;
            printf("File deleted: %s\n", fileName);
            printPrompt();
            return;
        }
    }

    printf("File not found or not a file: %s\n", fileName);
    printPrompt();
}

void openFileFunc(const char *fileName) {
    if (!fileName) {
        printf("File name not provided.\n");
        return;
    }

    if (openFileCount >= MAX_OPEN_FILES) {
        printf("Maximum open files limit reached.\n");
        return;
    }

    for (int i = 0; i < fs.currentDirectory->entryCount; i++) {
        if (strcmp(fs.currentDirectory->entries[i].fileName, fileName) == 0 && !fs.currentDirectory->entries[i].isDirectory) {
            for (int j = 0; j < openFileCount; j++) {
                if (strcmp(openFiles[j].fileName, fileName) == 0) {
                    printf("File already open: %s\n", fileName);
                    return;
                }
            }
            OpenFile openFile;
            openFile.fileDescriptor = openFileCount;
            strcpy(openFile.fileName, fileName);
            openFile.index = i;
            openFile.position = 0;
            openFiles[openFileCount++] = openFile;
            printf("File opened: %s\n", fileName);
            printPrompt();
            return;
        }
    }

    printf("File not found or is a directory: %s\n", fileName);
    printPrompt();
}

void closeFile(const char *fileName) {
    if (!fileName) {
        printf("File name not provided.\n");
        return;
    }

    for (int i = 0; i < openFileCount; i++) {
        if (strcmp(openFiles[i].fileName, fileName) == 0) {
            for (int j = i; j < openFileCount - 1; j++) {
                openFiles[j] = openFiles[j + 1];
            }
            openFileCount--;
            printf("File closed: %s\n", fileName);
            printPrompt();
            return;
        }
    }

    printf("File not open: %s\n", fileName);
    printPrompt();
}

void readFile(const char *fileName) {
    if (!fileName) {
        printf("File name not provided.\n");
        return;
    }

    for (int i = 0; i < openFileCount; i++) {
        if (strcmp(openFiles[i].fileName, fileName) == 0) {
            int currentBlockRow = fs.currentDirectory->entries[openFiles[i].index].startBlockRow;
            int currentBlockCol = fs.currentDirectory->entries[openFiles[i].index].startBlockCol;
            if (currentBlockRow == -1 || currentBlockCol == -1) {
                printf("File is empty.\n");
                printPrompt();
                return;
            }
            printf("Contents of %s:\n", fileName);
            while (currentBlockRow != -1 && currentBlockCol != -1) {
                printf("%s", fs.disk[currentBlockRow][currentBlockCol]);
                int nextBlockRow = fs.FAT[currentBlockRow][currentBlockCol].nextBlockRow;
                int nextBlockCol = fs.FAT[currentBlockRow][currentBlockCol].nextBlockCol;
                currentBlockRow = nextBlockRow;
                currentBlockCol = nextBlockCol;
            }
            printf("\n");
            printPrompt();
            return;
        }
    }

    printf("File not open: %s\n", fileName);
    printPrompt();
}
void writeFile(const char *fileName) {
    if (!fileName) {
        printf("File name not provided.\n");
        return;
    }

    // 提示用户输入数据
    printf("Please enter the data below. Type 'wq!' to save and 'q!' to cancel.\n");

    // 初始化用于存储用户输入的数据缓冲区
    char data[DISK_SIZE * BLOCK_SIZE];
    data[0] = '\0';  // Initialize data buffer
    char line[BLOCK_SIZE];
    
    // 不断读取用户输入,直到用户输入 'wq!' 或 'q!'
    while (1) {
        fgets(line, BLOCK_SIZE, stdin);

        // 去掉换行符
        line[strcspn(line, "\n")] = '\0';

        // 检查用户是否输入 'wq!' 或 'q!'
        if (strcmp(line, "wq!") == 0) {
            break;
        } else if (strcmp(line, "q!") == 0) {
            printf("Write operation cancelled.\n");
            return;
        }

        // 将当前行追加到数据缓冲区
        strcat(data, line);
        strcat(data, "\n");
    }

    // 调用写入文件函数,将文件名和用户输入的数据传递给 writeFileData
    writeFileData(fileName, data);
}

void writeFileData(const char *fileName, const char *data) {
    if (!fileName || !data) {
        printf("File name or data not provided.\n");
        return;
    }

    int fileIndex = -1;
    for (int i = 0; i < fs.currentDirectory->entryCount; i++) {
        if (strcmp(fs.currentDirectory->entries[i].fileName, fileName) == 0 && !fs.currentDirectory->entries[i].isDirectory) {
            fileIndex = i;
            break;
        }
    }

    if (fileIndex == -1) {
        if (fs.currentDirectory->entryCount >= MAX_FILES) {
            printf("Directory limit reached.\n");
            return;
        }
        DirectoryEntry newEntry;
        strcpy(newEntry.fileName, fileName);
        newEntry.startBlock = -1;
        newEntry.length = 0;
        newEntry.isDirectory = 0;
        fs.currentDirectory->entries[fs.currentDirectory->entryCount++] = newEntry;
        fileIndex = fs.currentDirectory->entryCount - 1;
    }

    int currentBlock = fs.currentDirectory->entries[fileIndex].startBlock;
    if (currentBlock == -1) {
        for (int j = 0; j < DISK_ROWS; j++) {
            for (int k = 0; k < DISK_COLS; k++) {
                if (fs.bitMap[j][k] == 0) {
                    currentBlock = j * DISK_COLS + k;
                    fs.bitMap[j][k] = 1;
                    fs.currentDirectory->entries[fileIndex].startBlock = currentBlock;
                    break;
                }
            }
        }
    }

    int pos = 0;
    int dataLen = strlen(data);
    while (pos < dataLen) {
        if (currentBlock == -1) {
            printf("No enough space.\n");
            return;
        }
        int row = currentBlock / DISK_COLS;
        int col = currentBlock % DISK_COLS;
        int bytesToWrite = dataLen - pos > BLOCK_SIZE ? BLOCK_SIZE : dataLen - pos;
        memcpy(fs.disk[row][col], data + pos, bytesToWrite);
        pos += bytesToWrite;
        int nextBlock = -1;
        if (pos < dataLen) {
            for (int j = 0; j < DISK_ROWS; j++) {
                for (int k = 0; k < DISK_COLS; k++) {
                    if (fs.bitMap[j][k] == 0) {
                        nextBlock = j * DISK_COLS + k;
                        fs.bitMap[j][k] = 1;
                        fs.FAT[row][col].nextBlock = nextBlock;
                        break;
                    }
                }
            }
        }
        currentBlock = nextBlock;
    }

    fs.currentDirectory->entries[fileIndex].length = dataLen;
    printf("Data written to %s\n", fileName);
}
void initializeFileSystem() {
    memset(&fs, 0, sizeof(FileSystem));
    fs.currentDirectory = &fs.rootDirectory;
    strcpy(fs.currentPath, "/");
}

void executeCommand(const char *command) {
    char cmd[256];
    char arg1[256];

    if (sscanf(command, "%s %s", cmd, arg1) < 1) {
        return;
    }

    if (strcmp(cmd, "format") == 0) {
        format();
    } else if (strcmp(cmd, "mkdir") == 0) {
        mkdir(arg1);
    } else if (strcmp(cmd, "rmdir") == 0) {
        rmdir(arg1);
    } else if (strcmp(cmd, "ls") == 0) {
        ls();
    } else if (strcmp(cmd, "cd") == 0) {
        cd(arg1);
    } else if (strcmp(cmd, "create") == 0) {
        create(arg1);
    } else if (strcmp(cmd, "rm") == 0) {
        rm(arg1);
    } else if (strcmp(cmd, "open") == 0) {
        openFileFunc(arg1);
    } else if (strcmp(cmd, "close") == 0) {
        closeFile(arg1);
    } else if (strcmp(cmd, "read") == 0) {
        readFile(arg1);
    } else if (strcmp(cmd, "write") == 0) {
        printf("Please enter the data below. Type 'wq!' to save and 'q!' to cancel.\n");
        char data[DISK_SIZE * BLOCK_SIZE];
        data[0] = '\0';  // Initialize data buffer
        char line[BLOCK_SIZE];

        while (1) {
            fgets(line, BLOCK_SIZE, stdin);
            line[strcspn(line, "\n")] = '\0';  // Remove trailing newline

            if (strcmp(line, "wq!") == 0) {
                break;
            } else if (strcmp(line, "q!") == 0) {
                printf("Write operation cancelled.\n");
                return;
            }

            strcat(data, line);
            strcat(data, "\n");
        }

        writeFileData(arg1, data);
    } else if (strcmp(cmd, "exit") == 0) {
        printf("Exiting the file system.\n");
        exit(0);
    } else {
        printf("Unknown command: %s\n", cmd);
        printPrompt();
    }
}


int main() {
    initializeFileSystem();
    format();
    printPrompt();

    char command[1024];

    while (1) {
        if (fgets(command, sizeof(command), stdin) != NULL) {
            command[strcspn(command, "\n")] = '\0';  // Remove trailing newline
            executeCommand(command);
        }
    }

    return 0;
}


Comment