【操作系统】实验五:文件管理

实验五:文件管理(8学时)

目录

实验五:文件管理(8学时)

实验要点:

实验要求:

流程图

源程序


实验要点:

Linux系统文件调用的使用

    设计一个二级目录的树形文件系统程序

实验要求:

利用C语言实现一个简单的文件系统,能完成目录和文件的创建、删除、空间分配,能实现两级目录。 要求设计一个 5个用户的文件系统,每次用户可保存5个文件,用户在一次运行中只能打开一个文件,对文件必须设置保护措施,且至少有Create、delete、open、close、read、write等命令。

提交内容:

流程图

源程序

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

#define MAX_USERS 5
#define MAX_FILES_PER_USER 5
#define MAX_FILENAME_LEN 20
#define MAX_CONTENT_LEN 100
#define FILE_SYSTEM_FILE "filesystem.dat"

enum ProtectionLevel {
    PRIVATE,
    PUBLIC
};

struct File {
    char filename[MAX_FILENAME_LEN];
    char content[MAX_CONTENT_LEN];
    enum ProtectionLevel protection;
    int isOpen;  // 用于标记文件是否已经被打开
    int ownerId;  // 保存创建文件的用户 ID
};

struct Directory {
    char dirname[MAX_FILENAME_LEN];
    struct File files[MAX_FILES_PER_USER];
    int fileCount;
};

struct User {
    char username[MAX_FILENAME_LEN];
    int userId;
};

struct FileSystem {
    struct Directory userDirs[MAX_USERS];
    struct File* openedFile;  // 用于记录当前打开的文件
};

void createDirectory(struct Directory* parentDir, char* dirname) {
    struct Directory newDir;
    strcpy(newDir.dirname, dirname);
    newDir.fileCount = 0;
    *parentDir = newDir;
}

void deleteDirectory(struct Directory* parentDir, char* dirname) {
    // 删除目录的逻辑
}

void createFile(struct FileSystem* fs, struct Directory* dir, char* filename, enum ProtectionLevel protection, int ownerId) {
    if (dir->fileCount < MAX_FILES_PER_USER) {
        struct File newFile;
        strcpy(newFile.filename, filename);
        newFile.protection = protection;
        newFile.isOpen = 0;  // 文件创建时默认未打开

        // 设置 ownerId 为无效值,表示文件的拥有者是所有用户
        newFile.ownerId = (protection == PUBLIC) ? -1 : ownerId;

        dir->files[dir->fileCount++] = newFile;

        // 如果是公共文件,将其添加到所有用户的目录中
        if (protection == PUBLIC) {
            for (int i = 0; i < MAX_USERS; ++i) {
                if (i != ownerId - 1) {
                    struct Directory* otherDir = &fs->userDirs[i];
                    otherDir->files[otherDir->fileCount++] = newFile;
                }
            }
        }

        printf("File '%s' created with protection level %s.\n", filename, (protection == PRIVATE) ? "PRIVATE" : "PUBLIC");
    } else {
        printf("Cannot create more files in this directory.\n");
    }
}



void deleteFile(struct Directory* dir, char* filename) {
    int i;
    for (i = 0; i < dir->fileCount; ++i) {
        if (strcmp(dir->files[i].filename, filename) == 0) {
            // 如果文件是共享文件,将 ownerId 设置为无效值
            if (dir->files[i].protection == PUBLIC) {
                dir->files[i].ownerId = -1;
            }

            memmove(&dir->files[i], &dir->files[i + 1], (dir->fileCount - i - 1) * sizeof(struct File));
            dir->fileCount--;
            printf("File '%s' deleted.\n", filename);
            return;
        }
    }
    printf("File '%s' not found.\n", filename);
}

struct File* openFile(struct Directory* dir, char* filename, int userId, struct FileSystem* fs) {
    // 检查是否已经有文件打开
    if (fs->openedFile != NULL) {
        printf("Another file is already open. Close it before opening a new one.\n");
        return NULL;
    }

    // 寻找文件并进行相关操作
    for (int i = 0; i < dir->fileCount; ++i) {
        if (strcmp(dir->files[i].filename, filename) == 0) {
            // 检查权限
            if ((dir->files[i].protection == PRIVATE && dir->files[i].ownerId == userId) ||
                (dir->files[i].protection == PUBLIC)) {
                // 私有文件只能被所有者打开,公共文件可以被任何用户打开
                if (!dir->files[i].isOpen) {
                    dir->files[i].isOpen = 1;
                    printf("File '%s' opened with protection level %s.\n", filename, (dir->files[i].protection == PRIVATE) ? "PRIVATE" : "PUBLIC");
                    return &dir->files[i];
                } else {
                    printf("File '%s' is already open.\n", filename);
                    return NULL;
                }
            } else {
                printf("Invalid protection level for file '%s'.\n", filename);
                return NULL;
            }
        }
    }

    printf("File '%s' not found.\n", filename);
    return NULL;
}



void closeFile(struct File* file, struct FileSystem* fs) {
    file->isOpen = 0;
    fs->openedFile = NULL;  // 清除当前打开的文件
    printf("File '%s' closed.\n", file->filename);
}


void readFile(struct File* file) {
    printf("File content:\n%s\n", file->content);
}

void writeFile(struct File* file, char* content) {
    strcpy(file->content, content);
    printf("File '%s' written.\n", file->filename);
}
void saveUserDirectory(struct Directory* userDir, FILE* file) {
    // 写入用户目录信息
    fwrite(userDir, sizeof(struct Directory), 1, file);

    // 写入用户目录中每个文件的信息
    fwrite(userDir->files, sizeof(struct File), userDir->fileCount, file);
}

// 在保存文件系统时添加调试输出
void saveFileSystem(struct FileSystem* fs) {
    FILE* file = fopen(FILE_SYSTEM_FILE, "wb");
    if (file == NULL) {
        perror("Error opening file for writing");
        exit(EXIT_FAILURE);
    }

    // 写入文件系统信息
    fwrite(fs, sizeof(struct FileSystem), 1, file);

    // 写入每个用户的文件信息
    for (int i = 0; i < MAX_USERS; ++i) {
        // 写入用户目录信息
        fwrite(&fs->userDirs[i], sizeof(struct Directory), 1, file);

        // 写入用户目录中每个文件的信息
        fwrite(fs->userDirs[i].files, sizeof(struct File), fs->userDirs[i].fileCount, file);
    }

    

    // 调试输出
    printf("Saved file system:\n");
    for (int i = 0; i < MAX_USERS; ++i) {
        printf("User %d files:\n", i + 1);
        for (int j = 0; j < fs->userDirs[i].fileCount; ++j) {
            printf("File %d: %s\n", j + 1, fs->userDirs[i].files[j].filename);
        }
    }
    fclose(file);
}

void loadFileSystem(struct FileSystem* fs) {
    system("pwd");  // 输出当前工作目录

    FILE* file = fopen(FILE_SYSTEM_FILE, "rb");
    if (file == NULL) {
        perror("Error opening file for reading");
        exit(EXIT_FAILURE);
    }

    // 读取文件系统信息
    fread(fs, sizeof(struct FileSystem), 1, file);

    // 读取每个用户的文件信息
    for (int i = 0; i < MAX_USERS; ++i) {
        fread(&fs->userDirs[i], sizeof(struct Directory), 1, file);

        // 读取用户目录中每个文件的信息
        fread(fs->userDirs[i].files, sizeof(struct File), fs->userDirs[i].fileCount, file);

        // 处理无效的 ownerId(-1)并设置为当前用户 ID
        for (int j = 0; j < fs->userDirs[i].fileCount; ++j) {
            if (fs->userDirs[i].files[j].ownerId == -1) {
                fs->userDirs[i].files[j].ownerId = i + 1;
            }
        }
    }

    fclose(file);

    // 调试输出
    printf("Loaded file system:\n");
    //for (int i = 0; i < MAX_USERS; ++i) {
        //printf("User %d files:\n", i + 1);
        //for (int j = 0; j < fs->userDirs[i].fileCount; ++j) {
            //printf("File %d: %s\n", j + 1, fs->userDirs[i].files[j].filename);
        //}
    //}
}



void parseCommand(struct FileSystem* fs, struct User* user, char* command) {
    char cmd[10];
    char arg[20];

    if (sscanf(command, "%9s %19[^\n]", cmd, arg) != 2) {
        printf("Invalid command format.\n");
        return;
    }

    if (strcmp(cmd, "exit") == 0) {
        saveFileSystem(fs);  // 用户退出时保存文件系统状态
        printf("User %s exited.\n", user->username);
        exit(EXIT_SUCCESS);  // 确保退出程序
    }

    if (strcmp(cmd, "create") == 0) {
        if (strlen(arg) > 0) {
            char protectionStr[10];
            printf("Enter protection level (private/public): ");
            scanf("%s", protectionStr);

            int protection;
            if (strcmp(protectionStr, "private") == 0) {
                protection = PRIVATE;
            } else if (strcmp(protectionStr, "public") == 0) {
                protection = PUBLIC;
            } else {
                printf("Invalid protection level. Defaulting to PRIVATE.\n");
                protection = PRIVATE;
            }

            createFile(fs, &fs->userDirs[user->userId - 1], arg, protection, user->userId);
        } else {
            printf("Usage: create <filename>\n");
        }
    } else if (strcmp(cmd, "delete") == 0) {
        deleteFile(&fs->userDirs[user->userId - 1], arg);
    } else if (strcmp(cmd, "open") == 0) {
        openFile(&fs->userDirs[user->userId - 1], arg, user->userId, fs);
    } else if (strcmp(cmd, "close") == 0) {
        int index = atoi(arg) - 1;  // 获取索引
        if (index >= 0 && index < fs->userDirs[user->userId - 1].fileCount) {
            closeFile(&fs->userDirs[user->userId - 1].files[index], fs);
        } else {
            printf("Invalid file index.\n");
        }
    } else if (strcmp(cmd, "read") == 0) {
        int index = atoi(arg) - 1;  // 获取索引
        if (index >= 0 && index < fs->userDirs[user->userId - 1].fileCount) {
            readFile(&fs->userDirs[user->userId - 1].files[index]);
        } else {
            printf("Invalid file index.\n");
        }
    } else if (strcmp(cmd, "write") == 0) {
        int index = atoi(arg) - 1;  // 获取索引
        if (index >= 0 && index < fs->userDirs[user->userId - 1].fileCount) {
            char content[MAX_CONTENT_LEN];
            printf("Enter content:\n");
            scanf(" %[^\n]", content);
            writeFile(&fs->userDirs[user->userId - 1].files[index], content);
        } else {
            printf("Invalid file index.\n");
        }
    } else {
        printf("Invalid command.\n");
    }
}





void initFileSystem(struct FileSystem* fs) {
    FILE* file = fopen(FILE_SYSTEM_FILE, "rb");
    if (file == NULL) {
        // 文件不存在,创建一个新文件
        printf("Error opening file for reading: %s\n", strerror(errno));
        
        // 创建一个新的文件系统
        for (int i = 0; i < MAX_USERS; ++i) {
            strcpy(fs->userDirs[i].dirname, "home");
            fs->userDirs[i].fileCount = 0;
        }

        // 保存新的文件系统状态
        saveFileSystem(fs);
    } else {
        // 文件存在,加载文件系统状态
        fclose(file);  // 关闭文件描述符
        loadFileSystem(fs);
    }
}

void userInterface(struct FileSystem* fs, struct User* user) {
    char command[100];

    printf("Welcome, %s!\n", user->username);
    loadFileSystem(fs);  // 在用户登录时加载文件系统状态
    while (1) {
        printf("Enter command (create/delete/open/close/read/write/exit): ");
        scanf(" %[^\n]", command);
        if (strcmp(command, "exit") == 0) {
            saveFileSystem(fs);  // 在用户退出时保存文件系统状态
            printf("User %s exited.\n", user->username);
            break;
        }
        parseCommand(fs, user, command);
    }

    // 用户退出时,确保关闭所有用户打开的文件
    int i;
    for (i = 0; i < MAX_FILES_PER_USER; ++i) {
        if (fs->userDirs[user->userId - 1].files[i].isOpen) {
            closeFile(&fs->userDirs[user->userId - 1].files[i], fs);
        }
    }
}


int main() {
    struct FileSystem fs;
    initFileSystem(&fs);

    struct User users[MAX_USERS];
    for (int i = 0; i < MAX_USERS; ++i) {
        sprintf(users[i].username, "User%d", i + 1);
        users[i].userId = i + 1;
    }

    int userId;
    do {
        printf("Enter user ID (1 to %d, 0 to exit): ", MAX_USERS);
        scanf("%d", &userId);

        if (userId < 0 || userId > MAX_USERS) {
            printf("Invalid user ID.\n");
            continue;
        }

        if (userId == 0) {
            printf("Exiting the file system.\n");
            break;  // 退出主程序循环
        }

        userInterface(&fs, &users[userId - 1]);

    } while (1);  // 主程序循环

    return 0;
}

用户1创建一个个人文件

其他用户无法对其进行打开和其他操作

用户1创建一个共享文件

其他用户可以对其进行任意操作

一次只能打开一个文件

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
实验目的】 1. 了解文件系统的原理; 2. 用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程。从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。 【实验准备】 1.文件的逻辑结构  顺序文件  索引文件  索引顺序文件  直接文件和哈希文件 2.外存分配方式  连续分配  链接分配  索引分配 【实验内容】 1. 实验要求 要求设计一个 n个用户的文件系统,每次用户可保存m个文件,用户在一次运行中只能打开一个文件,对文件必须设置保护措施,且至少有Create、delete、open、close、read、write等命令。 2. 实验题目  设计一个10个用户的文件系统,每次用户可保存10个文件,一次运行用户可以打开5个文件。  程序采用二级文件目录(即设置主目录[MFD])和用户文件目录(UED)。另外,为打开文件设置了运行文件目录(AFD)。  为了便于实现,对文件的读写作了简化,在执行读写命令时,只需改读写指针,并不进行实际的读写操作。 因系统小,文件目录的检索使用了简单的线性搜索。文件保护简单使用了三位保护码:允许读写执行、对应位为 1,对应位为0,则表示不允许读写、执行。程序中使用的主要设计结构如下:主文件目录和用户文件目录( MFD、UFD)打开文件目录( AFD)(即运行文件目录)。 M D F 用户名 文件目录指针 用户名 文件目录指针 U F D 文件名 保护码 文件长度 文件名 A F D 打开文件名 打开保护码 读写指针

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亿巫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值