1427 lines
37 KiB
C
1427 lines
37 KiB
C
#include "vfs.h"
|
|
#include "multiboot.h"
|
|
#include "memory.h"
|
|
#include "string.h"
|
|
#include "fat.h"
|
|
#include "schedule.h"
|
|
#include "sfs.h"
|
|
#include "tty_fs.h"
|
|
#include "console.h"
|
|
#include "minix.h"
|
|
|
|
#define SEEK_SET 0
|
|
#define SEEK_CUR 1
|
|
#define SEEK_END 2
|
|
|
|
extern struct task_t *current_task;
|
|
|
|
struct vfs_device_t **vfs_devices;
|
|
int vfs_device_count;
|
|
|
|
struct quinn_pipe_t **vfs_pipes;
|
|
int vfs_pipe_count;
|
|
|
|
|
|
int vfs_stat_dev(struct vfs_device_t *device, char *path, struct stat *s);
|
|
int vfs_open_file_dev(struct vfs_device_t *device, char *path, int flags, int mode);
|
|
char * vfs_read_entire_file_dev(struct vfs_device_t *device, char *path, char **buffer);
|
|
int vfs_mkdir_dev(struct vfs_device_t *device, char *path);
|
|
int vfs_change_directory_dev(struct vfs_device_t *device, char *path);
|
|
int vfs_unlink_dev(struct vfs_device_t *device, char *path);
|
|
|
|
void init_vfs(void) {
|
|
int i;
|
|
vfs_devices = (struct vfs_device_t **)0;
|
|
vfs_device_count = 0;
|
|
vfs_pipes = (struct quinn_pipe_t **)0;
|
|
vfs_pipe_count = 0;
|
|
}
|
|
|
|
int vfs_lseek(int fileno, unsigned long long offset, int whence) {
|
|
if (fileno > 255 || fileno < 0) {
|
|
return -1;
|
|
}
|
|
if (current_task->filehandles[fileno].free == 1) {
|
|
return -1;
|
|
}
|
|
switch (whence) {
|
|
case SEEK_SET:
|
|
current_task->filehandles[fileno].info->position = offset;
|
|
return current_task->filehandles[fileno].info->position;
|
|
case SEEK_CUR:
|
|
current_task->filehandles[fileno].info->position += offset;
|
|
return current_task->filehandles[fileno].info->position;
|
|
case SEEK_END:
|
|
current_task->filehandles[fileno].info->position = current_task->filehandles[fileno].info->size + offset;
|
|
return current_task->filehandles[fileno].info->position;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
struct vfs_device_t * vfs_register_device(unsigned int device, char *name, unsigned char fstype) {
|
|
struct vfs_device_t *new_device;
|
|
int ret;
|
|
|
|
new_device = (struct vfs_device_t *)malloc(sizeof(struct vfs_device_t));
|
|
|
|
new_device->device = device;
|
|
strcpy(new_device->name, name);
|
|
new_device->fs = fstype;
|
|
new_device->cwd = (char *)malloc(sizeof(char) * 2);
|
|
strcpy(new_device->cwd, "/");
|
|
switch (fstype) {
|
|
case 0:
|
|
ret = tty_init(new_device);
|
|
break;
|
|
case 1:
|
|
ret = sfs_load_superblock(new_device);
|
|
break;
|
|
case 2:
|
|
ret = fat_load_superblock(new_device);
|
|
break;
|
|
case 3:
|
|
ret = minix_load_superblock(new_device);
|
|
break;
|
|
}
|
|
|
|
if (ret == 0) {
|
|
free(new_device);
|
|
return NULL;
|
|
}
|
|
|
|
if (vfs_device_count == 0) {
|
|
vfs_devices = (struct vfs_device_t **)malloc(sizeof(struct vfs_device_t *));
|
|
} else {
|
|
vfs_devices = (struct vfs_device_t **)realloc(vfs_devices, sizeof(struct vfs_device_t *) * (vfs_device_count + 1));
|
|
}
|
|
|
|
vfs_devices[vfs_device_count] = new_device;
|
|
|
|
vfs_device_count ++;
|
|
|
|
kprintf("VFS: Registered %s\n", name);
|
|
|
|
return new_device;
|
|
}
|
|
|
|
int vfs_unlink(char *path) {
|
|
int i;
|
|
char *device_ptr;
|
|
char *path_ptr;
|
|
char *path_copy;
|
|
|
|
int ret;
|
|
|
|
path_copy = (char *)malloc(strlen(path) + 1);
|
|
|
|
strcpy(path_copy, path);
|
|
|
|
device_ptr = path_copy;
|
|
|
|
for (i=0;i<strlen(path_copy);i++) {
|
|
if (path_copy[i] == ':') {
|
|
path_copy[i] = '\0';
|
|
path_ptr = &path_copy[i+1];
|
|
|
|
for (i=0;i<vfs_device_count;i++) {
|
|
if (strcmp(vfs_devices[i]->name, device_ptr) == 0) {
|
|
if (path_ptr[strlen(path_ptr) - 1] == '/') {
|
|
path_ptr[strlen(path_ptr) - 1] = '\0';
|
|
}
|
|
vfs_select_device(vfs_devices[i]->name);
|
|
ret = vfs_unlink_dev(vfs_devices[i], path_ptr);
|
|
free(path_copy);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
if (path_copy[i] == '/') {
|
|
break;
|
|
}
|
|
}
|
|
if (path_copy[strlen(path_copy) - 1] == '/') {
|
|
path_copy[strlen(path_copy) - 1] = '\0';
|
|
}
|
|
ret = vfs_unlink_dev(current_task->selected_device, path_copy);
|
|
free(path_copy);
|
|
return ret;
|
|
}
|
|
|
|
|
|
int vfs_unlink_dev(struct vfs_device_t *device, char *path) {
|
|
char *temppath;
|
|
int ret = -1;
|
|
if (path[0] != '/') {
|
|
temppath = (char *)malloc(strlen(device->cwd) + strlen(path) + 2);
|
|
memset(temppath, 0, strlen(device->cwd) + strlen(path) + 2);
|
|
|
|
if (device->cwd[1] == '\0') {
|
|
temppath[0] = '/';
|
|
memcpy(&temppath[1], path, strlen(path));
|
|
} else {
|
|
memcpy(temppath, device->cwd, strlen(device->cwd));
|
|
temppath[strlen(device->cwd)] = '/';
|
|
memcpy(&temppath[strlen(device->cwd) + 1], path, strlen(path));
|
|
}
|
|
} else {
|
|
|
|
temppath = (char *)malloc(strlen(path) + 1);
|
|
|
|
strcpy(temppath, path);
|
|
}
|
|
|
|
switch(device->fs) {
|
|
case 1:
|
|
|
|
break;
|
|
case 2:
|
|
ret= fat_delete_file(device, temppath);
|
|
break;
|
|
case 3:
|
|
ret = minix_unlink_file(device, temppath);
|
|
break;
|
|
|
|
}
|
|
free(temppath);
|
|
return ret;
|
|
}
|
|
|
|
int vfs_change_directory(char *path) {
|
|
int i;
|
|
char *device_ptr;
|
|
char *path_ptr;
|
|
char *path_copy;
|
|
|
|
int ret;
|
|
|
|
path_copy = (char *)malloc(strlen(path) + 1);
|
|
|
|
strcpy(path_copy, path);
|
|
|
|
device_ptr = path_copy;
|
|
|
|
for (i=0;i<strlen(path_copy);i++) {
|
|
if (path_copy[i] == ':') {
|
|
path_copy[i] = '\0';
|
|
path_ptr = &path_copy[i+1];
|
|
|
|
for (i=0;i<vfs_device_count;i++) {
|
|
if (strcmp(vfs_devices[i]->name, device_ptr) == 0) {
|
|
if (path_ptr[strlen(path_ptr) - 1] == '/') {
|
|
path_ptr[strlen(path_ptr) - 1] = '\0';
|
|
}
|
|
vfs_select_device(vfs_devices[i]->name);
|
|
ret = vfs_change_directory_dev(vfs_devices[i], path_ptr);
|
|
free(path_copy);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
if (path_copy[i] == '/') {
|
|
break;
|
|
}
|
|
}
|
|
if (path_copy[strlen(path_copy) - 1] == '/') {
|
|
path_copy[strlen(path_copy) - 1] = '\0';
|
|
}
|
|
ret = vfs_change_directory_dev(current_task->selected_device, path_copy);
|
|
free(path_copy);
|
|
return ret;
|
|
}
|
|
|
|
int vfs_change_directory_dev(struct vfs_device_t *device, char *path) {
|
|
switch(device->fs) {
|
|
case 1:
|
|
if (sfs_change_directory(device, path)) {
|
|
free(device->cwd);
|
|
device->cwd = malloc(sizeof(char) * (strlen(path) + 1));
|
|
strcpy(device->cwd, path);
|
|
}
|
|
break;
|
|
case 2:
|
|
if (fat_change_directory(device, path)) {
|
|
free(device->cwd);
|
|
device->cwd = malloc(sizeof(char) * (strlen(path) + 1));
|
|
strcpy(device->cwd, path);
|
|
}
|
|
break;
|
|
case 3:
|
|
if (minix_change_directory(device, path)) {
|
|
free(device->cwd);
|
|
device->cwd = malloc(sizeof(char) * (strlen(path) + 1));
|
|
strcpy(device->cwd, path);
|
|
}
|
|
break;
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int vfs_write_file(int fileno, char *buffer, int len) {
|
|
int count;
|
|
|
|
if (fileno < 0 || fileno >= 256) {
|
|
return -1;
|
|
}
|
|
|
|
if (current_task->filehandles[fileno].free) {
|
|
return -1;
|
|
}
|
|
|
|
if (current_task->filehandles[fileno].device == (void *)0) {
|
|
if (strcmp(current_task->filehandles[fileno].filepath, "PIPE") == 0) {
|
|
struct quinn_pipe_t *pipe = (struct quinn_pipe_t *)current_task->filehandles[fileno].fs_specific;
|
|
|
|
|
|
if (pipe->buffer_size == 0) {
|
|
pipe->buffer = (char *)malloc(len);
|
|
} else {
|
|
pipe->buffer = (char *)dbrealloc(pipe->buffer, pipe->buffer_size + len, "pipe write file");
|
|
}
|
|
|
|
if (!pipe->buffer) {
|
|
pipe->buffer_size = 0;
|
|
return -1;
|
|
}
|
|
|
|
memcpy(&pipe->buffer[pipe->buffer_size], buffer, len);
|
|
|
|
pipe->buffer_size += len;
|
|
|
|
return len;
|
|
}
|
|
} else {
|
|
switch (current_task->filehandles[fileno].device->fs) {
|
|
case 0:
|
|
count = tty_write_data(current_task->filehandles[fileno].device, buffer, len, 0);
|
|
return count;
|
|
case 1:
|
|
return -1;
|
|
case 2:
|
|
count = fat_write_data(current_task->filehandles[fileno].device, (struct fat_file_info *)current_task->filehandles[fileno].fs_specific, current_task->filehandles[fileno].filepath, buffer, len, current_task->filehandles[fileno].info->position);
|
|
current_task->filehandles[fileno].info->position += count;
|
|
return count;
|
|
case 3:
|
|
count = minix_write_data(current_task->filehandles[fileno].device, (struct minix_file_info *)current_task->filehandles[fileno].fs_specific, current_task->filehandles[fileno].filepath, buffer, len, current_task->filehandles[fileno].info->position);
|
|
current_task->filehandles[fileno].info->position += count;
|
|
return count;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
int vfs_read_file(int fileno, char *buffer, int len) {
|
|
int count;
|
|
if (fileno < 0 || fileno >= 256) {
|
|
return -1;
|
|
}
|
|
|
|
if (current_task->filehandles[fileno].free) {
|
|
return -1;
|
|
}
|
|
|
|
if (current_task->filehandles[fileno].device == (void *)0) {
|
|
if (strcmp(current_task->filehandles[fileno].filepath, "PIPE") == 0) {
|
|
struct quinn_pipe_t *pipe = (struct quinn_pipe_t *)current_task->filehandles[fileno].fs_specific;
|
|
|
|
if (pipe->buffer_size == 0 && pipe->ref > 1) {
|
|
return -2;
|
|
} else if (pipe->buffer_size == 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (len > pipe->buffer_size) {
|
|
len = pipe->buffer_size;
|
|
}
|
|
|
|
memcpy(buffer, pipe->buffer, len);
|
|
|
|
if (len < pipe->buffer_size) {
|
|
char *buffer2 = (char *)malloc(pipe->buffer_size - len);
|
|
memcpy(buffer2, &pipe->buffer[len], pipe->buffer_size - len);
|
|
free(pipe->buffer);
|
|
pipe->buffer = buffer2;
|
|
} else {
|
|
free(pipe->buffer);
|
|
}
|
|
|
|
pipe->buffer_size -= len;
|
|
|
|
return len;
|
|
|
|
}
|
|
} else {
|
|
switch (current_task->filehandles[fileno].device->fs) {
|
|
case 0:
|
|
count = tty_read_data(current_task->filehandles[fileno].device, buffer, len, 0);
|
|
return count;
|
|
case 1:
|
|
count = sfs_read_data(current_task->filehandles[fileno].device, current_task->filehandles[fileno].filepath, buffer, len, current_task->filehandles[fileno].info->position);
|
|
current_task->filehandles[fileno].info->position += count;
|
|
return count;
|
|
case 2:
|
|
count = fat_read_data(current_task->filehandles[fileno].device, (struct fat_file_info *)current_task->filehandles[fileno].fs_specific, buffer, len, current_task->filehandles[fileno].info->position);
|
|
current_task->filehandles[fileno].info->position += count;
|
|
return count;
|
|
case 3:
|
|
count = minix_read_data(current_task->filehandles[fileno].device, (struct minix_file_info *)current_task->filehandles[fileno].fs_specific, buffer, len, current_task->filehandles[fileno].info->position);
|
|
current_task->filehandles[fileno].info->position += count;
|
|
return count;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void vfs_close_file(int fno) {
|
|
if (fno < 0 || fno >= 256) {
|
|
return;
|
|
}
|
|
|
|
if (current_task->filehandles[fno].free == 1) {
|
|
return;
|
|
}
|
|
|
|
if (current_task->filehandles[fno].device == (void *)0) {
|
|
if (strcmp(current_task->filehandles[fno].filepath, "PIPE") == 0) {
|
|
struct quinn_pipe_t *pipe = (struct quinn_pipe_t *)current_task->filehandles[fno].fs_specific;
|
|
|
|
pipe->ref--;
|
|
|
|
if (pipe->ref == 0) {
|
|
for (int i=0;i<vfs_pipe_count;i++) {
|
|
if (vfs_pipes[i] == pipe) {
|
|
for (int j=i;j<vfs_pipe_count-1;j++) {
|
|
vfs_pipes[j] = vfs_pipes[j+1];
|
|
}
|
|
|
|
vfs_pipe_count--;
|
|
|
|
if (vfs_pipe_count == 0) {
|
|
free(vfs_pipes);
|
|
} else {
|
|
vfs_pipes = (struct quinn_pipe_t **)dbrealloc(vfs_pipes, sizeof(struct quinn_pipe_t *) * vfs_pipe_count, "pipe close");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
} else {
|
|
switch(current_task->filehandles[fno].device->fs) {
|
|
case 0:
|
|
current_task->filehandles[fno].free = 1;
|
|
current_task->filehandles[fno].info->ref--;
|
|
if (current_task->filehandles[fno].info->ref == 0) {
|
|
free(current_task->filehandles[fno].info);
|
|
}
|
|
current_task->filehandles[fno].device = (void *)0;
|
|
break;
|
|
case 1:
|
|
current_task->filehandles[fno].free = 1;
|
|
free(current_task->filehandles[fno].filepath);
|
|
break;
|
|
case 2:
|
|
{
|
|
struct fat_file_info *info = (struct fat_file_info *)current_task->filehandles[fno].fs_specific;
|
|
struct fat_data *data = (struct fat_data *)current_task->filehandles[fno].device->fs_data;
|
|
int i;
|
|
|
|
if (info->dirty == 1) {
|
|
fat_update_dentry(current_task->filehandles[fno].device, info, current_task->filehandles[fno].filepath);
|
|
}
|
|
|
|
if (info->clusterchain != (void *)0) {
|
|
free(info->clusterchain);
|
|
}
|
|
|
|
if ((current_task->filehandles[fno].device->device & 0xff00) == 0x100) {
|
|
hd_sync(current_task->filehandles[fno].device->device & 0xff);
|
|
}
|
|
|
|
free(current_task->filehandles[fno].fs_specific);
|
|
free(current_task->filehandles[fno].filepath);
|
|
current_task->filehandles[fno].info->ref--;
|
|
if (current_task->filehandles[fno].info->ref == 0) {
|
|
free(current_task->filehandles[fno].info);
|
|
}
|
|
current_task->filehandles[fno].free = 1;
|
|
}
|
|
break;
|
|
case 3:
|
|
if ((current_task->filehandles[fno].device->device & 0xff00) == 0x100) {
|
|
hd_sync(current_task->filehandles[fno].device->device & 0xff);
|
|
}
|
|
|
|
current_task->filehandles[fno].info->ref--;
|
|
if (current_task->filehandles[fno].info->ref == 0) {
|
|
free(current_task->filehandles[fno].info);
|
|
}
|
|
free(current_task->filehandles[fno].filepath);
|
|
free(current_task->filehandles[fno].fs_specific);
|
|
current_task->filehandles[fno].free = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void vfs_close_all() {
|
|
int i;
|
|
for (i=0;i<256;i++) {
|
|
if (current_task->filehandles[i].free == 0) {
|
|
vfs_close_file(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void vfs_sync_all() {
|
|
for (int i = 0; i< vfs_device_count; i++) {
|
|
if ((vfs_devices[i]->device & 0xff00) == 0x100) {
|
|
hd_sync(vfs_devices[i]->device & 0xff);
|
|
}
|
|
}
|
|
}
|
|
|
|
int vfs_link(char *src, char *dest) {
|
|
char *copy_1;
|
|
char *copy_2;
|
|
char *path_1;
|
|
char *path_2;
|
|
char *sel_dev1 = (void *)0;
|
|
char *sel_dev2 = (void *)0;
|
|
|
|
if (current_task->selected_device != (void *)0) {
|
|
sel_dev1 = current_task->selected_device->name;
|
|
sel_dev2 = current_task->selected_device->name;
|
|
}
|
|
|
|
char *disk_1 = current_task->selected_device;
|
|
|
|
copy_1 = malloc(strlen(src) + 1);
|
|
if (!copy_1) {
|
|
return -1;
|
|
}
|
|
|
|
strcpy(copy_1, src);
|
|
|
|
copy_2 = malloc(strlen(dest) + 1);
|
|
if (!copy_2) {
|
|
free(copy_1);
|
|
return -1;
|
|
}
|
|
|
|
strcpy(copy_2, dest);
|
|
path_1 = copy_1;
|
|
path_2 = copy_2;
|
|
|
|
for (int i = 0; i < strlen(copy_1); i++) {
|
|
if (copy_1[i] == ':') {
|
|
copy_1[i] = '\0';
|
|
sel_dev1 = copy_1;
|
|
path_1 = ©_1[i+1];
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < strlen(copy_2); i++) {
|
|
if (copy_2[i] == ':') {
|
|
copy_2[i] = '\0';
|
|
sel_dev2 = copy_2;
|
|
path_2 = ©_2[i+1];
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if (sel_dev1 == (void *)0 || strcmp(sel_dev2, sel_dev1) != 0) {
|
|
free(copy_1);
|
|
free(copy_2);
|
|
return -2;
|
|
}
|
|
|
|
int ret = -1;
|
|
|
|
for (int i = 0; i < vfs_device_count; i++) {
|
|
if (strcmp(sel_dev1, vfs_devices[i]->name) == 0) {
|
|
ret = vfs_link_dev(vfs_devices[i], path_1, path_2);
|
|
break;
|
|
}
|
|
}
|
|
free(copy_1);
|
|
free(copy_2);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int vfs_link_dev(struct vfs_device_t *device, char *src, char *dest) {
|
|
char *temppath1;
|
|
char *temppath2;
|
|
|
|
if (src[0] != '/') {
|
|
temppath1 = (char *)malloc(strlen(device->cwd) + strlen(src) + 2);
|
|
memset(temppath1, 0, strlen(device->cwd) + strlen(src) + 2);
|
|
|
|
if (device->cwd[1] == '\0') {
|
|
temppath1[0] = '/';
|
|
memcpy(&temppath1[1], src, strlen(src));
|
|
} else {
|
|
memcpy(temppath1, device->cwd, strlen(device->cwd));
|
|
temppath1[strlen(device->cwd)] = '/';
|
|
memcpy(&temppath1[strlen(device->cwd) + 1], src, strlen(src));
|
|
}
|
|
} else {
|
|
|
|
temppath1 = (char *)malloc(strlen(src) + 1);
|
|
|
|
strcpy(temppath1, src);
|
|
}
|
|
|
|
if (dest[0] != '/') {
|
|
temppath2 = (char *)malloc(strlen(device->cwd) + strlen(dest) + 2);
|
|
memset(temppath2, 0, strlen(device->cwd) + strlen(dest) + 2);
|
|
|
|
if (device->cwd[1] == '\0') {
|
|
temppath2[0] = '/';
|
|
memcpy(&temppath2[1], dest, strlen(dest));
|
|
} else {
|
|
memcpy(temppath2, device->cwd, strlen(device->cwd));
|
|
temppath2[strlen(device->cwd)] = '/';
|
|
memcpy(&temppath2[strlen(device->cwd) + 1], dest, strlen(dest));
|
|
}
|
|
} else {
|
|
|
|
temppath2 = (char *)malloc(strlen(dest) + 1);
|
|
|
|
strcpy(temppath2, dest);
|
|
}
|
|
|
|
|
|
switch(device->fs) {
|
|
case 1:
|
|
break;
|
|
case 2:
|
|
break;
|
|
case 3:
|
|
{
|
|
int res = minix_link_file(device, temppath1, temppath2);
|
|
free(temppath1);
|
|
free(temppath2);
|
|
return res;
|
|
}
|
|
break;
|
|
}
|
|
free(temppath1);
|
|
free(temppath2);
|
|
return -1;
|
|
}
|
|
|
|
int vfs_mkdir(char *path) {
|
|
int i;
|
|
char *device_ptr;
|
|
char *path_ptr;
|
|
char *path_copy;
|
|
|
|
int ret;
|
|
|
|
path_copy = (char *)malloc(strlen(path) + 1);
|
|
|
|
strcpy(path_copy, path);
|
|
|
|
device_ptr = path_copy;
|
|
|
|
for (i=0;i<strlen(path_copy);i++) {
|
|
if (path_copy[i] == ':') {
|
|
path_copy[i] = '\0';
|
|
path_ptr = &path_copy[i+1];
|
|
|
|
for (i=0;i<vfs_device_count;i++) {
|
|
if (strcmp(vfs_devices[i]->name, device_ptr) == 0) {
|
|
ret = vfs_mkdir_dev(vfs_devices[i], path_ptr);
|
|
free(path_copy);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
if (path_copy[i] == '/') {
|
|
break;
|
|
}
|
|
}
|
|
|
|
ret = vfs_mkdir_dev(current_task->selected_device, path);
|
|
free(path_copy);
|
|
return ret;
|
|
}
|
|
|
|
int vfs_mkdir_dev(struct vfs_device_t *device, char *path) {
|
|
char *temppath;
|
|
|
|
|
|
if (strcmp(path, ".") == 0 || strcmp(path, "..") == 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (path[0] != '/') {
|
|
temppath = (char *)malloc(strlen(device->cwd) + strlen(path) + 2);
|
|
memset(temppath, 0, strlen(device->cwd) + strlen(path) + 2);
|
|
|
|
if (device->cwd[1] == '\0') {
|
|
temppath[0] = '/';
|
|
memcpy(&temppath[1], path, strlen(path));
|
|
} else {
|
|
memcpy(temppath, device->cwd, strlen(device->cwd));
|
|
temppath[strlen(device->cwd)] = '/';
|
|
memcpy(&temppath[strlen(device->cwd) + 1], path, strlen(path));
|
|
}
|
|
} else {
|
|
|
|
temppath = (char *)malloc(strlen(path) + 1);
|
|
|
|
strcpy(temppath, path);
|
|
}
|
|
|
|
|
|
switch(device->fs) {
|
|
case 1:
|
|
break;
|
|
case 2:
|
|
{
|
|
int res = fat_create_directory(device, temppath);
|
|
free(temppath);
|
|
return res;
|
|
}
|
|
break;
|
|
case 3:
|
|
{
|
|
int res = minix_create_directory(device, temppath);
|
|
free(temppath);
|
|
return res;
|
|
}
|
|
break;
|
|
}
|
|
free(temppath);
|
|
return -1;
|
|
}
|
|
|
|
char *vfs_read_entire_file(char *path, char **buffer) {
|
|
int i;
|
|
char *device_ptr;
|
|
char *path_ptr;
|
|
char *path_copy;
|
|
|
|
char *ret;
|
|
|
|
path_copy = (char *)dbmalloc(strlen(path) + 1, "read_entire_file malloc");
|
|
|
|
strcpy(path_copy, path);
|
|
|
|
device_ptr = path_copy;
|
|
|
|
for (i=0;i<strlen(path_copy);i++) {
|
|
if (path_copy[i] == ':') {
|
|
path_copy[i] = '\0';
|
|
path_ptr = &path_copy[i+1];
|
|
|
|
for (i=0;i<vfs_device_count;i++) {
|
|
if (strcmp(vfs_devices[i]->name, device_ptr) == 0) {
|
|
ret = vfs_read_entire_file_dev(vfs_devices[i], path_ptr, buffer);
|
|
dbfree(path_copy, "read_entire_file free");
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
if (path_copy[i] == '/') {
|
|
break;
|
|
}
|
|
}
|
|
|
|
ret = vfs_read_entire_file_dev(current_task->selected_device, path, buffer);
|
|
dbfree(path_copy, "read_entire_file free 2");
|
|
return ret;
|
|
}
|
|
|
|
char * vfs_read_entire_file_dev(struct vfs_device_t *device, char *path, char **buffer) {
|
|
int i;
|
|
|
|
char *temppath;
|
|
|
|
if (path[0] != '/') {
|
|
temppath = (char *)malloc(strlen(device->cwd) + strlen(path) + 2);
|
|
memset(temppath, 0, strlen(device->cwd) + strlen(path) + 2);
|
|
|
|
if (device->cwd[1] == '\0') {
|
|
temppath[0] = '/';
|
|
memcpy(&temppath[1], path, strlen(path));
|
|
} else {
|
|
memcpy(temppath, device->cwd, strlen(device->cwd));
|
|
temppath[strlen(device->cwd)] = '/';
|
|
memcpy(&temppath[strlen(device->cwd) + 1], path, strlen(path));
|
|
}
|
|
} else {
|
|
temppath = (char *)malloc(strlen(path) + 1);
|
|
strcpy(temppath, path);
|
|
}
|
|
|
|
switch(device->fs) {
|
|
case 1:
|
|
break;
|
|
case 2:
|
|
{
|
|
struct fat_file_info *info = fat_check_if_exists(device, temppath, 1);
|
|
if (!info) {
|
|
free(temppath);
|
|
return (void *)0;
|
|
}
|
|
fat_read_entire_file(device, info->start_cluster, buffer);
|
|
free(temppath);
|
|
free(info);
|
|
return *buffer;
|
|
}
|
|
break;
|
|
case 3:
|
|
{
|
|
struct minix_file_info *info = minix_check_if_exists(device, temppath, 1);
|
|
if (!info) {
|
|
free(temppath);
|
|
return (void *)0;
|
|
}
|
|
struct minix_inode *inode = minix_get_inode(device, info->inode);
|
|
minix_read_entire_file(device, inode, buffer);
|
|
free(inode);
|
|
free(temppath);
|
|
free(info);
|
|
return *buffer;
|
|
|
|
}
|
|
break;
|
|
}
|
|
free(temppath);
|
|
return (void *)0;
|
|
}
|
|
|
|
int vfs_open_file(char *path, int flags, int mode) {
|
|
int i;
|
|
char *device_ptr;
|
|
char *path_ptr;
|
|
char *path_copy;
|
|
int ret;
|
|
|
|
path_copy = (char *)malloc(strlen(path) + 1);
|
|
strcpy(path_copy, path);
|
|
device_ptr = path_copy;
|
|
|
|
for (i=0;i<strlen(path_copy);i++) {
|
|
if (path_copy[i] == ':') {
|
|
path_copy[i] = '\0';
|
|
path_ptr = &path_copy[i+1];
|
|
|
|
for (i=0;i<vfs_device_count;i++) {
|
|
if (strcmp(vfs_devices[i]->name, device_ptr) == 0) {
|
|
ret = vfs_open_file_dev(vfs_devices[i], path_ptr, flags, mode);
|
|
free(path_copy);
|
|
return ret;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
if (path_copy[i] == '/') {
|
|
break;
|
|
}
|
|
}
|
|
|
|
ret = vfs_open_file_dev(current_task->selected_device, path_copy, flags, mode);
|
|
free(path_copy);
|
|
return ret;
|
|
}
|
|
|
|
int vfs_open_file_dev(struct vfs_device_t *device, char *path, int flags, int mode) {
|
|
int i;
|
|
|
|
char *temppath;
|
|
if (path[0] != '/') {
|
|
temppath = (char *)malloc(strlen(device->cwd) + strlen(path) + 2);
|
|
memset(temppath, 0, strlen(device->cwd) + strlen(path) + 2);
|
|
|
|
if (device->cwd[1] == '\0') {
|
|
temppath[0] = '/';
|
|
memcpy(&temppath[1], path, strlen(path));
|
|
} else {
|
|
memcpy(temppath, device->cwd, strlen(device->cwd));
|
|
temppath[strlen(device->cwd)] = '/';
|
|
memcpy(&temppath[strlen(device->cwd) + 1], path, strlen(path));
|
|
}
|
|
} else {
|
|
|
|
temppath = (char *)malloc(strlen(path) + 1);
|
|
|
|
strcpy(temppath, path);
|
|
|
|
|
|
}
|
|
|
|
|
|
switch(device->fs) {
|
|
case 0:
|
|
for (i=0;i<256;i++) {
|
|
if (current_task->filehandles[i].free) {
|
|
break;
|
|
}
|
|
}
|
|
if (i==256) {
|
|
return -1;
|
|
}
|
|
|
|
current_task->filehandles[i].free = 0;
|
|
current_task->filehandles[i].device = device;
|
|
current_task->filehandles[i].filepath = (void *)0;
|
|
current_task->filehandles[i].info = (struct vfs_file_handle_info_t *)malloc(sizeof(struct vfs_file_handle_info_t));
|
|
current_task->filehandles[i].info->position = 0;
|
|
current_task->filehandles[i].info->size = 0;
|
|
current_task->filehandles[i].info->ref = 1;
|
|
|
|
free(temppath);
|
|
return i;
|
|
case 1:
|
|
if (sfs_check_if_exists(device, path, 1)) {
|
|
for (i=0;i<256;i++) {
|
|
if (current_task->filehandles[i].free) {
|
|
break;
|
|
}
|
|
}
|
|
if (i==256) {
|
|
free(temppath);
|
|
return -1;
|
|
}
|
|
|
|
current_task->filehandles[i].free = 0;
|
|
current_task->filehandles[i].device = device;
|
|
current_task->filehandles[i].filepath = (char *)malloc(sizeof(char) * (strlen(temppath) + 1));
|
|
strcpy(current_task->filehandles[i].filepath, temppath);
|
|
current_task->filehandles[i].info = (struct vfs_file_handle_info_t *)malloc(sizeof(struct vfs_file_handle_info_t));
|
|
current_task->filehandles[i].info->position = 0;
|
|
current_task->filehandles[i].info->size = 0;
|
|
current_task->filehandles[i].info->ref = 1;
|
|
free(temppath);
|
|
return i;
|
|
} else {
|
|
if (flags & O_CREAT) {
|
|
// create file....
|
|
|
|
}
|
|
return -1; // ENOENT
|
|
}
|
|
break;
|
|
case 2:
|
|
{
|
|
unsigned int cluster;
|
|
struct fat_file_info *info = fat_check_if_exists(device, temppath, -1);
|
|
if (info != NULL) {
|
|
for (i=0;i<256;i++) {
|
|
if (current_task->filehandles[i].free) {
|
|
break;
|
|
}
|
|
}
|
|
if (i==256) {
|
|
free(info);
|
|
free(temppath);
|
|
return -1;
|
|
}
|
|
|
|
if (flags & O_TRUNC) {
|
|
if (info->file_size > 0) {
|
|
fat_trunc_file(device, info, temppath);
|
|
info->file_size = 0;
|
|
}
|
|
}
|
|
current_task->filehandles[i].free = 0;
|
|
current_task->filehandles[i].device = device;
|
|
current_task->filehandles[i].filepath = (char *)malloc(sizeof(char) * (strlen(temppath) + 1));
|
|
strcpy(current_task->filehandles[i].filepath, temppath);
|
|
current_task->filehandles[i].info = (struct vfs_file_handle_info_t *)malloc(sizeof(struct vfs_file_handle_info_t));
|
|
current_task->filehandles[i].info->position = 0;
|
|
current_task->filehandles[i].info->size = info->file_size;
|
|
current_task->filehandles[i].info->ref = 1;
|
|
current_task->filehandles[i].fs_specific = (void *)info;
|
|
dbfree(temppath, "temppath");
|
|
return i;
|
|
} else {
|
|
if (flags & O_CREAT) {
|
|
fat_create_file(device, temppath);
|
|
info = fat_check_if_exists(device, temppath, -1);
|
|
if (info != NULL) {
|
|
for (i=0;i<256;i++) {
|
|
if (current_task->filehandles[i].free) {
|
|
break;
|
|
}
|
|
}
|
|
if (i==256) {
|
|
free(temppath);
|
|
return -1;
|
|
}
|
|
|
|
current_task->filehandles[i].free = 0;
|
|
current_task->filehandles[i].device = device;
|
|
current_task->filehandles[i].filepath = (char *)malloc(sizeof(char) * (strlen(temppath) + 1));
|
|
strcpy(current_task->filehandles[i].filepath, temppath);
|
|
current_task->filehandles[i].info = (struct vfs_file_handle_info_t *)malloc(sizeof(struct vfs_file_handle_info_t));
|
|
current_task->filehandles[i].info->position = 0;
|
|
current_task->filehandles[i].info->size = info->file_size;
|
|
current_task->filehandles[i].info->ref = 1;
|
|
current_task->filehandles[i].fs_specific = (void *)info;
|
|
free(temppath);
|
|
return i;
|
|
}
|
|
}
|
|
free(temppath);
|
|
return -1; // ENOENT
|
|
}
|
|
}
|
|
break;
|
|
case 3:
|
|
{
|
|
struct minix_file_info *info = minix_check_if_exists(device, temppath, -1);
|
|
if (info != NULL) {
|
|
for (i=0;i<256;i++) {
|
|
if (current_task->filehandles[i].free) {
|
|
break;
|
|
}
|
|
}
|
|
if (i==256) {
|
|
free(temppath);
|
|
return -1;
|
|
}
|
|
|
|
if (flags & O_TRUNC) {
|
|
if (info->file_size > 0) {
|
|
minix_trunc_file(device, info);
|
|
info->file_size = 0;
|
|
}
|
|
}
|
|
|
|
current_task->filehandles[i].free = 0;
|
|
current_task->filehandles[i].device = device;
|
|
current_task->filehandles[i].filepath = (char *)malloc(sizeof(char) * (strlen(temppath) + 1));
|
|
strcpy(current_task->filehandles[i].filepath, temppath);
|
|
current_task->filehandles[i].info = (struct vfs_file_handle_info_t *)malloc(sizeof(struct vfs_file_handle_info_t));
|
|
current_task->filehandles[i].info->position = 0;
|
|
current_task->filehandles[i].info->size = info->file_size;
|
|
current_task->filehandles[i].info->ref = 1;
|
|
current_task->filehandles[i].fs_specific = (void *)info;
|
|
free(temppath);
|
|
return i;
|
|
} else {
|
|
if (flags & O_CREAT) {
|
|
if (minix_create_file(device, temppath) == 0) kprintf("Create File Successful\n");
|
|
info = minix_check_if_exists(device, temppath, -1);
|
|
if (info != NULL) {
|
|
for (i=0;i<256;i++) {
|
|
if (current_task->filehandles[i].free) {
|
|
break;
|
|
}
|
|
}
|
|
if (i==256) {
|
|
free(temppath);
|
|
return -1;
|
|
}
|
|
|
|
current_task->filehandles[i].free = 0;
|
|
current_task->filehandles[i].device = device;
|
|
current_task->filehandles[i].filepath = (char *)malloc(sizeof(char) * (strlen(temppath) + 1));
|
|
strcpy(current_task->filehandles[i].filepath, temppath);
|
|
current_task->filehandles[i].info = (struct vfs_file_handle_info_t *)malloc(sizeof(struct vfs_file_handle_info_t));
|
|
current_task->filehandles[i].info->position = 0;
|
|
current_task->filehandles[i].info->size = info->file_size;
|
|
current_task->filehandles[i].info->ref = 1;
|
|
current_task->filehandles[i].fs_specific = (void *)info;
|
|
free(temppath);
|
|
return i;
|
|
}
|
|
}
|
|
free(temppath);
|
|
return -1; // ENOENT
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
free(temppath);
|
|
return -1;
|
|
}
|
|
|
|
unsigned char vfs_select_device(char *name) {
|
|
int i;
|
|
for (i=0;i<vfs_device_count;i++) {
|
|
if (strcmp(vfs_devices[i]->name, name) == 0) {
|
|
current_task->selected_device = vfs_devices[i];
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int vfs_getdents(int fileno, char *buffer, int count) {
|
|
int len;
|
|
|
|
if (fileno < 0 || fileno >=256) {
|
|
return -1;
|
|
}
|
|
|
|
if (current_task->filehandles[fileno].free) {
|
|
return -1;
|
|
}
|
|
|
|
switch (current_task->filehandles[fileno].device->fs) {
|
|
case 0:
|
|
return 0;
|
|
case 1:
|
|
return 0;
|
|
case 2:
|
|
{
|
|
unsigned long long newoffset;
|
|
len = fat_get_dents(current_task->filehandles[fileno].device, (struct fat_file_info *)current_task->filehandles[fileno].fs_specific, buffer, count, current_task->filehandles[fileno].info->position, &newoffset);
|
|
current_task->filehandles[fileno].info->position = newoffset;
|
|
return len;
|
|
}
|
|
case 3:
|
|
{
|
|
unsigned long long newoff;
|
|
len = minix_get_dents(current_task->filehandles[fileno].device, (struct minix_file_info *)current_task->filehandles[fileno].fs_specific, buffer, count, current_task->filehandles[fileno].info->position, &newoff);
|
|
current_task->filehandles[fileno].info->position += newoff;
|
|
return len;
|
|
}
|
|
}
|
|
}
|
|
|
|
int vfs_fstat(int fileno, struct stat *s) {
|
|
if (fileno < 0 || fileno >=256) {
|
|
return -1;
|
|
}
|
|
|
|
if (current_task->filehandles[fileno].free) {
|
|
return -1;
|
|
}
|
|
|
|
switch (current_task->filehandles[fileno].device->fs) {
|
|
case 0:
|
|
s->st_dev = current_task->filehandles[fileno].device->device; //ID of device containing file
|
|
s->st_ino = 0; //file serial number
|
|
s->st_mode = S_IFCHR; //mode of file (see below)
|
|
s->st_nlink = 0; //number of links to the file
|
|
s->st_uid = 0; //user ID of file
|
|
s->st_gid = 0; //group ID of file
|
|
s->st_rdev = 0; //device ID (if file is character or block special)
|
|
s->st_size = 0; //file size in bytes (if file is a regular file)
|
|
s->st_atime = 0; //time of last access
|
|
s->st_mtime = 0; //time of last data modification
|
|
s->st_ctime = 0; //time of last status change
|
|
s->st_blksize = 0; //a filesystem-specific preferred I/O block size for
|
|
s->st_blocks = 0; //number of blocks allocated for this object
|
|
break;
|
|
case 1:
|
|
return -1;
|
|
case 2:
|
|
{
|
|
struct fat_data *data = (struct fat_data *)current_task->filehandles[fileno].device->fs_data;
|
|
struct fat_file_info *info = (struct fat_file_info *)current_task->filehandles[fileno].fs_specific;
|
|
s->st_dev = current_task->filehandles[fileno].device->device;
|
|
s->st_ino = info->start_cluster;
|
|
s->st_mode = (info->type == 0 ? S_IFDIR : S_IFREG);
|
|
s->st_nlink = 1;
|
|
s->st_uid = 0;
|
|
s->st_gid = 0;
|
|
s->st_rdev = 0;
|
|
s->st_size = info->file_size;
|
|
s->st_atime = info->atime;
|
|
s->st_mtime = info->mtime;
|
|
s->st_ctime = info->ctime;
|
|
s->st_blksize = data->superblock.BPB_BytesPerSec;
|
|
s->st_blocks = info->file_size / data->superblock.BPB_BytesPerSec;
|
|
if (info->file_size % data->superblock.BPB_BytesPerSec) s->st_blocks++;
|
|
}
|
|
break;
|
|
case 3:
|
|
{
|
|
struct minix_data *data = (struct minix_data *)current_task->filehandles[fileno].device->fs_data;
|
|
struct minix_file_info *info = (struct minix_file_info *)current_task->filehandles[fileno].fs_specific;
|
|
s->st_dev = current_task->filehandles[fileno].device->device;
|
|
s->st_ino = info->inode;
|
|
s->st_mode = (info->type == 0 ? S_IFDIR : S_IFREG);
|
|
s->st_nlink = 1;
|
|
s->st_uid = 0;
|
|
s->st_gid = 0;
|
|
s->st_rdev = 0;
|
|
s->st_size = info->file_size;
|
|
s->st_atime = info->atime;
|
|
s->st_mtime = info->mtime;
|
|
s->st_ctime = info->ctime;
|
|
s->st_blksize = data->sb.s_blocksize;
|
|
s->st_blocks = info->file_size / data->sb.s_blocksize;
|
|
if (info->file_size % data->sb.s_blocksize) s->st_blocks++;
|
|
}
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int vfs_pipe(int *pipe) {
|
|
int i, j;
|
|
|
|
for (i=0;i<256;i++) {
|
|
if (current_task->filehandles[i].free) {
|
|
break;
|
|
}
|
|
}
|
|
if (i==256) {
|
|
return -1;
|
|
}
|
|
|
|
current_task->filehandles[i].free = 0;
|
|
|
|
for (j=0;j<256;j++) {
|
|
if (current_task->filehandles[j].free) {
|
|
break;
|
|
}
|
|
}
|
|
if (j==256) {
|
|
current_task->filehandles[i].free = 1;
|
|
return -1;
|
|
}
|
|
current_task->filehandles[j].free = 0;
|
|
|
|
struct quinn_pipe_t *pipe_ptr = (struct quinn_pipe_t *)malloc(sizeof(struct quinn_pipe_t));
|
|
|
|
if (!pipe_ptr) {
|
|
current_task->filehandles[i].free = 1;
|
|
current_task->filehandles[j].free = 1;
|
|
return -1;
|
|
}
|
|
|
|
pipe_ptr->in_fno = i;
|
|
pipe_ptr->out_fno = j;
|
|
pipe_ptr->buffer_size = 0;
|
|
pipe_ptr->ref = 2;
|
|
current_task->filehandles[i].filepath = (char *)malloc(5);
|
|
strcpy(current_task->filehandles[i].filepath, "PIPE");
|
|
|
|
current_task->filehandles[i].device = (void *)0;
|
|
current_task->filehandles[i].info = (struct vfs_file_handle_info_t *)malloc(sizeof(struct vfs_file_handle_info_t));
|
|
current_task->filehandles[i].info->position = 0;
|
|
current_task->filehandles[i].info->size = 0;
|
|
current_task->filehandles[i].info->ref = 1;
|
|
current_task->filehandles[i].fs_specific = pipe_ptr;
|
|
|
|
current_task->filehandles[j].filepath = (char *)malloc(5);
|
|
strcpy(current_task->filehandles[j].filepath, "PIPE");
|
|
|
|
current_task->filehandles[j].device = (void *)0;
|
|
current_task->filehandles[j].info = (struct vfs_file_handle_info_t *)malloc(sizeof(struct vfs_file_handle_info_t));
|
|
current_task->filehandles[j].info->position = 0;
|
|
current_task->filehandles[j].info->size = 0;
|
|
current_task->filehandles[j].info->ref = 1;
|
|
current_task->filehandles[j].fs_specific = pipe_ptr;
|
|
|
|
if (vfs_pipe_count == 0) {
|
|
vfs_pipes = (struct quinn_pipe_t **)malloc(sizeof(struct quinn_pipe_t *));
|
|
} else {
|
|
vfs_pipes = (struct quinn_pipe_t **)dbrealloc(vfs_pipes, sizeof(struct quinn_pipe_t *) * (vfs_pipe_count + 1), "pipe pipe");
|
|
}
|
|
|
|
vfs_pipes[vfs_pipe_count] = pipe_ptr;
|
|
vfs_pipe_count++;
|
|
|
|
pipe[0] = pipe_ptr->out_fno;
|
|
pipe[1] = pipe_ptr->in_fno;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int vfs_stat(char *path, struct stat *s) {
|
|
int i;
|
|
char *device_ptr;
|
|
char *path_ptr;
|
|
char *path_copy;
|
|
int ret;
|
|
|
|
path_copy = (char *)malloc(strlen(path) + 1);
|
|
|
|
strcpy(path_copy, path);
|
|
|
|
device_ptr = path_copy;
|
|
|
|
for (i=0;i<strlen(path_copy);i++) {
|
|
if (path_copy[i] == ':') {
|
|
path_copy[i] = '\0';
|
|
path_ptr = &path_copy[i+1];
|
|
|
|
for (i=0;i<vfs_device_count;i++) {
|
|
if (strcmp(vfs_devices[i]->name, device_ptr) == 0) {
|
|
|
|
ret = vfs_stat_dev(vfs_devices[i], path_ptr, s);
|
|
|
|
dbfree(path_copy, "path_copy");
|
|
|
|
return ret;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
if (path_copy[i] == '/') {
|
|
break;
|
|
}
|
|
}
|
|
|
|
ret = vfs_stat_dev(current_task->selected_device, path_copy, s);
|
|
free(path_copy);
|
|
return ret;
|
|
}
|
|
|
|
int vfs_stat_dev(struct vfs_device_t *device, char *path, struct stat *s) {
|
|
char *temppath;
|
|
if (path[0] != '/') {
|
|
temppath = (char *)malloc(strlen(device->cwd) + strlen(path) + 2);
|
|
memset(temppath, 0, strlen(device->cwd) + strlen(path) + 2);
|
|
|
|
if (device->cwd[1] == '\0') {
|
|
temppath[0] = '/';
|
|
memcpy(&temppath[1], path, strlen(path));
|
|
} else {
|
|
memcpy(temppath, device->cwd, strlen(device->cwd));
|
|
temppath[strlen(device->cwd)] = '/';
|
|
memcpy(&temppath[strlen(device->cwd) + 1], path, strlen(path));
|
|
}
|
|
} else {
|
|
|
|
temppath = (char *)malloc(strlen(path) + 1);
|
|
|
|
strcpy(temppath, path);
|
|
}
|
|
switch(device->fs) {
|
|
case 0:
|
|
s->st_dev = device->device; //ID of device containing file
|
|
s->st_ino = 0; //file serial number
|
|
s->st_mode = S_IFCHR; //mode of file (see below)
|
|
s->st_nlink = 0; //number of links to the file
|
|
s->st_uid = 0; //user ID of file
|
|
s->st_gid = 0; //group ID of file
|
|
s->st_rdev = 0; //device ID (if file is character or block special)
|
|
s->st_size = 0; //file size in bytes (if file is a regular file)
|
|
s->st_atime = 0; //time of last access
|
|
s->st_mtime = 0; //time of last data modification
|
|
s->st_ctime = 0; //time of last status change
|
|
s->st_blksize = 0; //a filesystem-specific preferred I/O block size for
|
|
s->st_blocks = 0; //number of blocks allocated for this object
|
|
break;
|
|
case 1:
|
|
free(temppath);
|
|
return 0;
|
|
case 2:
|
|
{
|
|
struct fat_file_info *info = fat_check_if_exists(device, temppath, -1);
|
|
struct fat_data *data = (struct fat_data *)device->fs_data;
|
|
|
|
if (info != NULL) {
|
|
s->st_dev = device->device;
|
|
s->st_ino = info->start_cluster;
|
|
s->st_mode = (info->type == 0 ? S_IFDIR : S_IFREG);
|
|
s->st_nlink = 1;
|
|
s->st_uid = 0;
|
|
s->st_gid = 0;
|
|
s->st_rdev = 0;
|
|
s->st_size = info->file_size;
|
|
s->st_atime = info->atime;
|
|
s->st_mtime = info->mtime;
|
|
s->st_ctime = info->ctime;
|
|
s->st_blksize = data->superblock.BPB_BytesPerSec;
|
|
s->st_blocks = info->file_size / data->superblock.BPB_BytesPerSec;
|
|
if (info->file_size % data->superblock.BPB_BytesPerSec) s->st_blocks++;
|
|
} else {
|
|
free(temppath);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
case 3:
|
|
{
|
|
struct minix_file_info *info = minix_check_if_exists(device, path, -1);
|
|
struct minix_data *data = (struct minix_data *)device->fs_data;
|
|
if (info != NULL) {
|
|
s->st_dev = device->device;
|
|
s->st_ino = info->inode;
|
|
s->st_mode = (info->type == 0 ? S_IFDIR : S_IFREG);
|
|
s->st_nlink = 1;
|
|
s->st_uid = 0;
|
|
s->st_gid = 0;
|
|
s->st_rdev = 0;
|
|
s->st_size = info->file_size;
|
|
s->st_atime = info->atime;
|
|
s->st_mtime = info->mtime;
|
|
s->st_ctime = info->ctime;
|
|
s->st_blksize = data->sb.s_blocksize;
|
|
s->st_blocks = info->file_size / data->sb.s_blocksize;
|
|
if (info->file_size % data->sb.s_blocksize) s->st_blocks++;
|
|
} else {
|
|
free(temppath);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
free(temppath);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int vfs_dup(int fno) {
|
|
int i;
|
|
|
|
if (current_task->filehandles[fno].device != (void *)0) {
|
|
// only works for pipes atm.
|
|
return -1;
|
|
}
|
|
|
|
if (fno < 0 || fno >= 256) {
|
|
return -1;
|
|
}
|
|
|
|
if (current_task->filehandles[fno].free == 1) {
|
|
return -1;
|
|
}
|
|
|
|
for (i=0;i<256;i++) {
|
|
if (current_task->filehandles[i].free) {
|
|
break;
|
|
}
|
|
}
|
|
if (i==256) {
|
|
return -1;
|
|
}
|
|
|
|
current_task->filehandles[i].free = 0;
|
|
current_task->filehandles[i].filepath = (char *)malloc(strlen(current_task->filehandles[fno].filepath) + 1);
|
|
strcpy(current_task->filehandles[i].filepath, current_task->filehandles[fno].filepath);
|
|
current_task->filehandles[i].device = current_task->filehandles[fno].device;
|
|
current_task->filehandles[i].info = current_task->filehandles[fno].info;
|
|
current_task->filehandles[i].info->ref++;
|
|
current_task->filehandles[i].fs_specific = current_task->filehandles[fno].fs_specific;
|
|
|
|
struct quinn_pipe_t *pipe = (struct quinn_pipe_t *)current_task->filehandles[i].fs_specific;
|
|
|
|
pipe->ref++;
|
|
|
|
|
|
return i;
|
|
}
|