创建属于自己的操作系统,拥有自己的命令以及提示
#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;
}