#include "ramfs.h"
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define MAX_NUM 4097
typedef struct node {
char filename[40];
char *data;
unsigned long offset;
unsigned long data_len;
unsigned long max_len;
enum {
DIR_NODE,
FILE_NODE
} flag;
struct node *child, *brother, *parent;
} file;
typedef struct list {
file *pointer;
int status; //atcwr
} List;
file *head;
List file_list[MAX_NUM];
int file_counter;
file *g_parent; // 备用
file *search(const char *pathname);
int get_flag(int flag);
int is_legal(const char *pathname);
void get_file_name(const char *pathname, int flag, char *dest);
int push_file(file *file, int flag);
int ropen(const char *pathname, int flags) {
int is_dir = is_legal(pathname);
switch (is_dir) {
case 0: {
file *f = search(pathname);
int f_flag = get_flag(flags);
if (f == NULL && ((f_flag >> 2) & 1)) {
file *parent_folder = g_parent;
if (parent_folder == NULL || parent_folder->flag == 1)
return -1;
else {
char name[40];
get_file_name(pathname, 0, name);
file *temp = malloc(sizeof(file));
memset(temp, 0, sizeof(file));
temp->flag = FILE_NODE;
temp->parent = g_parent;
strcpy(temp->filename, name);
if (parent_folder->child == NULL)
parent_folder->child = temp;
else {
parent_folder = parent_folder->child;
while (parent_folder->brother != NULL)
parent_folder = parent_folder->brother;
parent_folder->brother = temp;
}
return push_file(temp, f_flag);
}
} else if (f == NULL)
return -1;
else if (f->data == NULL)
return push_file(f, f_flag);
else if ((f_flag >> 3) & 1) {
free(f->data);
f->data = NULL;
f->offset = 0;
f->data_len = 0;
f->max_len = 0;
}
if ((f_flag >> 4) & 1) //append
f->offset = f->data_len;
else
f->offset = 0;
return push_file(f, f_flag);
}
case 1: {
file *f = search(pathname);
if (f != NULL && f->flag == 0) {
int temp = 0;
return push_file(f, temp);
} else
return -1;
}
default:
return -1;
}
}
int rclose(int fd) {
if (fd < 0 || fd >= MAX_NUM || file_list[fd].pointer == NULL)
return -1;
memset(&file_list[fd], 0, sizeof(List));
return 0;
}
ssize_t rwrite(int fd, const void *buf, size_t count) {
if (fd < 0 || fd >= MAX_NUM)
return -1;
file *f = file_list[fd].pointer;
if (f == NULL || !f->flag || !((file_list[fd].status >> 1) & 1))
return -1;
unsigned long len = count + f->offset;
if (len > f->max_len) {
f->data = realloc(f->data, len);
if (f->offset > f->data_len) {
memset(f->data + f->data_len, 0, f->offset - f->data_len);
}
f->max_len = len;
}
memcpy(f->data + f->offset, buf, count);
f->offset += count;
if (f->offset > f->data_len)
f->data_len = f->offset;
return count;
}
ssize_t rread(int fd, void *buf, size_t count) {
if (fd < 0 || fd >= MAX_NUM)
return -1;
file *f = file_list[fd].pointer;
if (f == NULL || !f->flag || !(file_list[fd].status & 1))
return -1;
if (f->data == NULL)
return 0;
unsigned int len = f->offset + count;
if (len > f->data_len)
len = f->data_len;
ssize_t n = len - f->offset;
if (n <= 0)
return 0;
memcpy(buf, f->data + f->offset, n);
f->offset += n;
return n;
}
off_t rseek(int fd, off_t offset, int whence) {
if (fd < 0 || fd >= MAX_NUM)
return -1;
file *f = file_list[fd].pointer;
if (f == NULL || f->flag == 0)
return -1;
unsigned int temp = f->offset;
switch (whence) {
case 0: {
f->offset = offset;
break;
}
case 1: {
f->offset = f->offset + offset;
break;
}
case 2: {
f->offset = f->data_len + offset;
break;
}
default:
return -1;
}
if (f->offset < 0) {
f->offset = temp;
return -1;
}
return f->offset;
}
int rmkdir(const char *pathname) {
if (is_legal(pathname) == -1)
return -1;
file *f = search(pathname);
file *p = g_parent;
if (f != NULL || g_parent == NULL || g_parent->flag == FILE_NODE)
return -1;
file *temp = malloc(sizeof(file));
memset(temp, 0, sizeof(file));
get_file_name(pathname, 0, temp->filename);
temp->parent = g_parent;
if (p->child == NULL) {
p->child = temp;
return 0;
}
p = p->child;
while (p->brother != NULL)
p = p->brother;
p->brother = temp;
return 0;
}
int rrmdir(const char *pathname) {
if (is_legal(pathname) == -1)
return -1;
file *f = search(pathname);
if (f == NULL || f->flag == 1 || f->child != NULL || f == head)
return -1;
file *p = f->parent;
if (f->parent->child != f) {
p = p->child;
while (p->brother != f)
p = p->brother;
p->brother = f->brother;
} else
p->child = f->brother;
free(f);
return 0;
}
int runlink(const char *pathname) {
int flag = is_legal(pathname);
if (flag == -1 || flag == 1)
return -1;
file *f = search(pathname);
if (f == NULL || f->flag == 0)
return -1;
file *p = f->parent;
if (f->parent->child != f) {
p = p->child;
while (p->brother != f)
p = p->brother;
p->brother = f->brother;
} else
p->child = f->brother;
if (f->data != NULL)
free(f->data);
free(f);
return 0;
}
void init_ramfs() {
head = malloc(sizeof(file));
memset(head, 0, sizeof(file));
}
file *search(const char *pathname) {
const char *p1 = pathname;
file *p2 = head;
for (; *p1 == '/'; p1++);
while (*p1 != '\0') {
char *next_p = strchr(p1, '/');
g_parent = p2;
if (p2->child == NULL) {
if (next_p == NULL) return NULL;
p1 = next_p;
for (; *p1 == '/'; p1++);
if (p1 != pathname + strlen(pathname)) g_parent = NULL;
return NULL;
}
p2 = p2->child;
if (next_p == NULL) {
while (strcmp(p2->filename, p1) != 0) {
if (p2->brother == NULL)
return NULL;
p2 = p2->brother;
}
return p2;
} else {
char str[40];
sscanf(p1, "%[^/]", str);
while (strcmp(p2->filename, str) != 0) {
if (p2->brother == NULL) {
p1 = next_p;
for (; *p1 == '/'; p1++);
if (p1 != pathname + strlen(pathname)) g_parent = NULL;
return NULL;
}
p2 = p2->brother;
}
p1 = next_p;
for (; *p1 == '/'; p1++);
}
}
return p2;
}
int get_flag(int flag) {
int ans = 0;
if (flag & 1) {
ans |= 0b10; //is_write
} else {
ans |= 0b1; //is_read
if ((flag >> 1) & 1) //is_write
ans |= 0b10;
}
int temp = flag >> 6;
if (temp & 1) //is_create
ans |= 0b100;
temp = temp >> 3;
if ((temp & 1) && ((ans >> 1) & 0b1)) //is_trunc
ans |= 0b1000;
if ((temp >> 1) & 1) //is_append
ans |= 0b10000;
return ans;
}
int is_legal(const char *pathname) {
int len = strlen(pathname);
int is_dir = 0;
int counter = 0;
if (*pathname != '/')
return -1;
if (*(pathname + len - 1) == '/')
is_dir = 1;
for (const char *i = pathname; i < pathname + len; ++i) {
char c = *i;
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') || c == '.')
counter++;
else if (c == '/') {
if (counter > 32) return -1;
counter = 0;
} else
return -1;
}
if (counter > 32) return -1;
return is_dir;
}
void get_file_name(const char *pathname, int flag, char *dest) {
char *temp = malloc(1030);
memset(temp, 0, 1030);
strcpy(temp, pathname);
char *parent, *child, *pointer;
parent = malloc(40);
child = malloc(40);
memset(parent, 0, 40);
memset(child, 0, 40);
pointer = strtok(temp, "/");
while (pointer != NULL) {
strcpy(parent, child);
strcpy(child, pointer);
pointer = strtok(NULL, "/");
}
if (flag == 0)
strcpy(dest, child);
else
strcpy(dest, parent);
}
int push_file(file *file, int flag) {
while (file_list[file_counter].pointer != NULL) {
file_counter++;
if (file_counter >= MAX_NUM)
file_counter -= MAX_NUM;
}
file_list[file_counter].pointer = file;
file_list[file_counter].status = flag;
return file_counter;
}
这段代码是一个 RAM 文件系统的实现,它包含了一些用于文件操作的函数和数据结构。
首先,代码中引用了一些标准库的头文件,包括<malloc.h>、<stdlib.h>、<string.h>和<stdio.h>等。
接下来,定义了一些常量,包括MAX_NUM,它表示文件系统最大支持的文件数量。
然后,定义了两个结构体:file和List。
1.file结构体表示文件系统中的一个文件或目录节点,包含了以下成员:
2.filename:文件名或目录名,长度为40字节;
3.data:文件数据的指针,指向文件存储的内容;
4.offset:数据在文件中的偏移量;
5.data_len:数据的长度;
6.max_len:文件的最大长度;
7.flag:文件标识,是一个枚举类型,表示节点类型,可以是目录节点(DIR_NODE)或文件节点(FILE_NODE);
8.child、brother、parent:指向子节点、兄弟节点和父节点的指针。
9.List结构体表示文件列表中的一个条目,包含了以下成员:
10.pointer:指向文件的指针;
11.status:文件的状态,可能是atcwr等值。
接下来,定义了一些全局变量,包括:
12.head:文件系统中的根节点;
13.file_list:文件列表数组,用于存储文件条目的信息;
14.file_counter:文件计数器,用于记录文件的数量;
15.g_parent:备用的父节点指针。
然后,声明了一些函数的原型,这些函数用于实现文件的打开、搜索、标识等操作。
最后,定义了ropen函数,用于打开一个文件。该函数首先通过调用is_legal函数判断路径是否合法,然后调用search函数搜索文件,根据返回结果和参数的标志信息进行判断和操作,并最终返回相应的结果。
总体来说,这段代码实现了一个简单的 RAM 文件系统,包含了文件的打开、搜索、标识等基本操作。具体的文件操作细节需要结合其他部分的代码来理解。