MFS File System Functions: Write, Inode Retrieval, and Directory Operations
MFS File System Functions
mfs_write
Function
Function Signature: int mfs_write(int fd, void *buf, size_t count)
This function writes data to a file within the MFS file system. It takes a file descriptor fd
, a buffer buf
containing the data to write, and the number of bytes count
to write.
Functionality:
- Checks if the file descriptor is valid.
- Verifies if the file is opened.
- Adjusts the write count if it exceeds the file’s remaining capacity.
- Calculates the starting position and block number for writing.
- Iterates through the data, writing to blocks.
- Handles partial block writes by reading, modifying, and writing back.
- Updates the file position and size if necessary.
int mfs_write(int fd, void *buf, size_t count) {
int start, not_done, num_block;
char block[fs->sb.block_size];
char *next;
if (fd < 0 || fd >= row_num) return -1;
if (fs->file[fd].num == -1) {
printf("Trying to write unopened fd \n");
return -1;
}
if (count > fs->file[fd].ino.e.size * fs->sb.block_size - fs->file[fd].pos)
count = fs->file[fd].ino.e.size * fs->sb.block_size - fs->file[fd].pos;
start = fs->file[fd].pos % fs->sb.block_size;
num_block = (fs->file[fd].pos / fs->sb.block_size) + fs->file[fd].ino.e.start;
not_done = count;
next = buf;
while (not_done) {
int len;
if (not_done > fs->sb.block_size - start)
len = fs->sb.block_size - start;
else
len = not_done;
if (len != fs->sb.block_size) {
data_read(fs, block, num_block);
memcpy(block + start, next, len);
data_write(fs, block, num_block);
} else {
data_write(fs, next, num_block);
}
num_block++;
not_done -= len;
next += len;
start = 0;
}
fs->file[fd].pos += count;
if (fs->file[fd].pos > fs->file[fd].ino.size) {
fs->file[fd].ino.size = fs->file[fd].pos;
inode_write(fs, &fs->file[fd].ino, fs->file[fd].num);
}
return count;
}
get_inodo_previo
Function
Function Signature: static int get_inodo_previo(struct file_system *fs, const char *path)
This function retrieves the inode of the parent directory given a full path.
Functionality:
- Parses the path to extract directory names.
- Iterates through the path components to find the parent inode.
- Handles cases where the path does not exist.
static int get_inodo_previo(struct file_system *fs, const char *path) {
int i = 0, j = 0, inode = -1, inodo_anterior = -1, con_dir = -1;
int path_len = strlen(path);
char *rest = malloc(sizeof(char) * path_len);
char *name = malloc(sizeof(char) * path_len);
disk_inode struct ino;
while (path[i] != '\0' && path[i] != '/') {
name[i] = path[i];
i++;
if (path[i] == '/') con_dir = 0;
name[i] = '\0';
}
i++;
while (i < strlen(path)) {
rest[j] = path[i];
i++;
j++;
rest[j] = '\0';
if (path[i] == '\0') break;
}
inode = namei(fs, &(fs->root), name);
if (con_dir == -1) return 0;
inodo_anterior = inode;
if (inode == -1) return -1;
else
while (inode != -1) {
i = 0, j = 0;
con_dir = -1;
inode_read(fs, &ino, inode);
while (rest[i] != '\0' && rest[i] != '/') {
name[i] = rest[i];
i++;
if (rest[i] == '/') con_dir = 0;
name[i] = '\0';
}
i++;
while (i < strlen(rest)) {
rest[j] = rest[i];
i++;
j++;
if (rest[i] == '\0') break;
}
rest[j] = '\0';
inodo_anterior = inode;
inode = namei(fs, &ino, name);
if (con_dir == 0) continue;
else
return inodo_anterior;
}
return inode;
}
get_inodo
Function
Function Signature: static int get_inodo(struct file_system *fs, const char *path)
This function retrieves the inode of a file or directory given its full path.
Functionality:
- Parses the path to extract directory and file names.
- Iterates through the path components to find the target inode.
- Handles special cases like “..” for parent directory traversal.
static int get_inodo(struct file_system *fs, const char *path) {
int i = 0, j = 0, s = 0, inode = -1, inodo_anterior = -1, con_dir = -1;
int path_len = strlen(path);
char *rest = malloc(sizeof(char) * path_len);
char *name = malloc(sizeof(char) * path_len);
char *dir_anterior = malloc(sizeof(char) * path_len);
disk_inode struct ino;
while (path[i] != '\0' && path[i] != '/') {
name[i] = path[i];
i++;
if (path[i] == '/') con_dir = 0;
name[i] = '\0';
}
i++;
while (i < strlen(path)) {
rest[j] = path[i];
i++;
j++;
rest[j] = '\0';
if (path[i] == '\0') break;
}
if (strcmp(name, "..") == 0) return 0;
inode = namei(fs, &(fs->root), name);
if (con_dir == -1) return inode;
inodo_anterior = inode;
if (inode == -1) return -1;
else
while (inode != -1) {
i = 0, j = 0;
con_dir = -1;
inode_read(fs, &ino, inode);
while (rest[i] != '\0' && rest[i] != '/') {
name[i] = rest[i];
i++;
if (rest[i] == '/') con_dir = 0;
name[i] = '\0';
}
i++;
while (i < strlen(rest)) {
rest[j] = rest[i];
i++;
j++;
if (rest[i] == '\0') break;
}
rest[j] = '\0';
inodo_anterior = inode;
inode = namei(fs, &ino, name);
if (name[0] == '.' && name[1] == '.') {
for (s = 0; s < strlen(path); s++) {
if ((path[s] == '/') && (path[s + 1] == '.') && (path[s + 2] == '.'))
return get_inodo_previo(fs, dir_anterior);
dir_anterior[s] = path[s];
}
}
if (name[0] == '.' && name[1] == '\0') return inodo_anterior;
if (con_dir == 0) continue;
else
return inode;
}
return inode;
}
is_dir
Function
Function Signature: static int is_dir(struct file_system *fs, struct disk_inode *d, const char *directory)
This function checks if a given name is a directory within the current inode’s directory entries.
Functionality:
- Reads the directory entries from the inode.
- Compares the given name with the directory entries.
- Returns 1 if the name is a directory, 0 otherwise.
static int is_dir(struct file_system *fs, struct disk_inode *d, const char *directory) {
char block[fs->sb.block_size];
struct entry *dir = (struct entry *)block;
int r = 0, i, j;
if (directory[0] == '.' && directory[1] == '\0') return 1;
for (i = 0; i < d->e.size; i++) {
data_read(fs, block, d->e.start + i);
for (j = 0; j < fs->sb.block_size / sizeof(struct entry); j++) {
if (dir[j].inode != -1 &&
strncmp(directory, dir[j].name, ENTRY_SIZE) == 0) {
if (dir[j].is_dir == 0) r = 1;
}
}
}
return r;
}
mfs_opendir
Function
Function Signature: struct mfs_dir *mfs_opendir(const char *name)
This function opens a directory by name and initializes the directory structure.
Functionality:
- Initializes the file system if it’s not already initialized.
- Handles the root directory case.
- Retrieves the inode of the directory.
- Initializes the directory structure for subsequent reads.
struct mfs_dir *mfs_opendir(const char *name) {
if (fs == NULL) fs_init();
int num_inodo;
printf("\t\tExploring directory: '%s'\n", name);
if (name[0] == '.' && name[1] == '\0') {
if (fs->dir.num_inodo == -1) {
inode_read(fs, &fs->dir.inodo, fs->sb.root_inode);
fs->dir.num_inodo = fs->sb.root_inode;
fs->dir.pos = 0;
fs->dir.pos_block = 0;
strcpy(fs->dir.path, name);
} else
return NULL;
} else {
if (fs->dir.num_inodo == -1) {
num_inodo = get_inodo(fs, name);
if (num_inodo == -1) return NULL;
inode_read(fs, &fs->dir.inodo, num_inodo);
fs->dir.num_inodo = num_inodo;
fs->dir.pos = 0;
fs->dir.pos_block = 0;
strcpy(fs->dir.path, name);
} else
return NULL;
}
return &fs->dir;
}
mfs_readdir
Function
Function Signature: struct dirent *mfs_readdir(MFS_DIR *dir)
This function reads directory entries from an opened directory.
Functionality:
- Reads the block corresponding to the directory’s inode.
- Checks if the current position is valid.
- Allocates memory for a directory entry.
- Copies the name of the entry.
struct dirent *mfs_readdir(MFS_DIR *dir) {
char block[fs->sb.block_size];
struct dirent *entry = NULL;
struct entry *ent = (struct entry *)block;
struct disk_inode ino_previo;
int num_inodo_root, inodo_root_previo, root_is_dir = 1, i = 0;
printf("int [dir->pos].name%s\n", ent[dir->pos].name);
printf("int [dir->pos].inode%d\n", ent[dir->pos].inode);
printf("dir->inodo.e.start%d\n", dir->inodo.e.start);
printf("dir->pos%d\n", dir->pos);
data_read(fs, block, dir->inodo.e.start + i);
if (dir->pos != -1) {
if (ent[dir->pos].inode != -1) {
printf("dir->num_inodo%d\n", dir->num_inodo);
printf("get_inodo_previo(fs, dir->path)%d\n",
get_inodo_previo(fs, dir->path));
entry = malloc(sizeof(struct dirent));
strcpy(entry->d_name, ent[dir->pos].name);
num_inodo_root = dir->num_inodo;
}
}
return entry;
}