265 lines
7.5 KiB
C
265 lines
7.5 KiB
C
#include "leanfs.h"
|
|
|
|
unsigned int leanfs_compute_checksum(const void *data, unsigned int size) {
|
|
unsigned int res = 0;
|
|
const unsigned int* d = (const unsigned int*)(data);
|
|
size /= sizeof(unsigned int);
|
|
for (unsigned i = 1; i != size; ++i) res = (res << 31) + (res >> 1) + d[i];
|
|
return res;
|
|
}
|
|
|
|
int leanfs_load_superblock(struct vfs_device_t *device) {
|
|
int i;
|
|
struct leanfs_data *data = (struct leanfs_data *)malloc(sizeof(struct leanfs_data));
|
|
if (!data) {
|
|
kprintf("Out of memory!\n");
|
|
return 0;
|
|
}
|
|
|
|
for (i=1;i<=maxSuperblockSector;i++) {
|
|
if (device->device == 1) {
|
|
ramdisk_read_block(i, &data->sb, 512);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), i, &data->sb, 512);
|
|
}
|
|
|
|
if (data->sb.magic == superblockMagic) {
|
|
if (data->sb.primary_super == i && data->sb.checksum == leanfs_compute_checksum(&data->sb, sizeof(struct leanfs_superblock))) {
|
|
// it's a lean fs filesystem
|
|
if (data->sb.fs_version != fsVersion) {
|
|
kprintf("LeanFS: Unsupported version\n");
|
|
free(data);
|
|
return 0;
|
|
}
|
|
data->sectors_per_band = 1 << data->sb.log_sectors_per_band;
|
|
data->band_bitmap_size_ = data->sectors_per_band >> (3 + logSectorSize);
|
|
data->band_count = (data->sb.sector_count + data->sectors_per_band - 1) >> data->sb.log_sectors_per_band;
|
|
|
|
device->fs_data = data;
|
|
|
|
kprintf("LeanFS: Recognised Filesystem\n");
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
free(data);
|
|
return 0;
|
|
}
|
|
|
|
unsigned long long leanfs_read_entire_file(struct vfs_device_t *device, leanfs_file_info *info, char **buffer) {
|
|
*buffer = (char *)malloc(info->inode->file_size - (sizeof(struct leanfs_inode)));
|
|
|
|
int bytes_read;
|
|
int extent_blocks;
|
|
char *extent;
|
|
char *buffer_loc;
|
|
char indirect_buffer[512];
|
|
|
|
if (!*buffer) {
|
|
return 0;
|
|
}
|
|
|
|
buffer_loc = *buffer;
|
|
|
|
for (i=0;i<info->inode->extent_count;i++) {
|
|
extent_blocks = info->inode->extent_sizes[i] / 512;
|
|
if (info->inode->extent_sizes[i] % 512) {
|
|
extent_blocks += 1;
|
|
}
|
|
|
|
extent = (char *)malloc(extent_blocks * 512);
|
|
|
|
if (device->device == 1) {
|
|
ramdisk_read_blocks(info->inode->extent_starts[i], extent_blocks, extent, 512);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), info->inode->extent_starts[i], extent_blocks, extent, 512);
|
|
}
|
|
|
|
|
|
|
|
|
|
if (i==0) {
|
|
memcpy(buffer_loc, &extent[sizeof(struct leanfs_inode)], info->inode->extent_sizes[i] - sizeof(struct leanfs_inode));
|
|
} else {
|
|
memcpy(&buffer_loc[bytes_read - sizeof(struct leanfs_inode)], extent, info->inode->extent_sizes[i]);
|
|
}
|
|
free(extent);
|
|
bytes_read += info->inode->extent_sizes[i];
|
|
}
|
|
|
|
|
|
unsigned long long indirect;
|
|
struct leanfs_indirect *indirect_s;
|
|
|
|
for (i=0;i<info->indirect_count;i++) {
|
|
if (i==0) {
|
|
indirect = info->inode->first_indirect;
|
|
} else {
|
|
indirect = indirect_d->next_indirect;
|
|
}
|
|
if (device->device == 1) {
|
|
ramdisk_read_block(indirect, indirect_buffer, 512);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), indirect, indirect_buffer, 512);
|
|
}
|
|
indirect_s = (struct leanfs_indirect *)indirect_buffer;
|
|
|
|
for (j=0;j<indirect_s->extent_count;j++) {
|
|
extent_blocks = indirect_s->extent_sizes[j] / 512;
|
|
if (indirect_s->extent_sizes[j] % 512) {
|
|
extent_blocks += 1;
|
|
}
|
|
|
|
extent = (char *)malloc(extent_blocks * 512);
|
|
|
|
if (device->device == 1) {
|
|
ramdisk_read_blocks(indirect_s->extent_starts[j], extent_blocks, extent, 512);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), indirect_s->extent_starts[j], extent_blocks, extent, 512);
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(&buffer_loc[bytes_read - sizeof(struct leanfs_inode)], extent, info->inode->extent_sizes[j]);
|
|
|
|
free(extent);
|
|
bytes_read += indirect_s->extent_sizes[j];
|
|
}
|
|
|
|
}
|
|
|
|
return (bytes_read - sizeof(struct leanfs_inode));
|
|
}
|
|
|
|
struct leanfs_file_info *leanfs_find_sub_entry(struct vfs_device_t *device, struct leanfs_file_info *info, char **ptr, int part, int parts, int type) {
|
|
|
|
}
|
|
|
|
struct leanfs_file_info *leanfs_check_if_exists(struct vfs_device_t *device, char *path, int type) {
|
|
struct leanfs_data *data = (struct leanfs_data *)device->fs_data;
|
|
struct leanfs_file_info *info;
|
|
unsigned long long len;
|
|
char *buffer2;
|
|
|
|
// load root directory
|
|
char buffer[512];
|
|
|
|
if (device->device == 1) {
|
|
ramdisk_read_block(data->sb.root_inode, buffer, 512);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), data->sb.root_inode, buffer, 512);
|
|
}
|
|
|
|
info = (struct leanfs_file_info *)malloc(sizeof(struct leanfs_file_info));
|
|
info->ino = data->sb.root_inode;
|
|
info->inode = (struct leanfs_inode *)malloc(sizeof(struct leanfs_inode));
|
|
|
|
memcpy(info->inode, buffer, sizeof(struct leanfs_inode));
|
|
|
|
if (strcmp(path, "/") == 0) {
|
|
return info;
|
|
}
|
|
|
|
// info contains root inode...
|
|
// load info into buffer
|
|
len = leanfs_read_entire_file(device, info, &buffer2);
|
|
|
|
free(info->inode);
|
|
free(info);
|
|
|
|
// buffer2 contains the root directory contents...
|
|
int i;
|
|
int parts = 0;
|
|
char *path_copy = (char *)dbmalloc(strlen(path) + 1, "leanfs_check_if_exists");
|
|
|
|
strcpy(path_copy, path);
|
|
|
|
if (path_copy[strlen(path_copy) - 1] == '/') {
|
|
path_copy[strlen(path_copy) - 1] = '\0';
|
|
}
|
|
parts = 1;
|
|
|
|
for (i=1;i<strlen(path_copy);i++) {
|
|
if (path_copy[i] == '/') {
|
|
parts++;
|
|
}
|
|
}
|
|
|
|
char **ptr = (char **)dbmalloc(sizeof(char *) * parts , "leanfs_check_if_exists");
|
|
|
|
ptr[0] = &path_copy[1];
|
|
int j = 0;
|
|
int k = strlen(path_copy);
|
|
for (i=1;i<k;i++) {
|
|
if (path_copy[i] == '/') {
|
|
ptr[++j] = &path_copy[i+1];
|
|
path_copy[i] = '\0';
|
|
}
|
|
}
|
|
|
|
struct leanfs_direntry *lfs_dir = (struct leanfs_direntry *)buffer2;
|
|
|
|
while (lfs_dir != (void *)0) {
|
|
if (strncmp(ptr[0], lfs_dir->name, lfs_dir->name_len) == 0) {
|
|
if (device->device == 1) {
|
|
ramdisk_read_block(lfs_dir->inode, buffer, 512);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), lfs_dir->inode, buffer, 512);
|
|
}
|
|
|
|
info = (struct leanfs_file_info *)malloc(sizeof(struct leanfs_file_info));
|
|
info->ino = lfs_dir->inode;
|
|
info->inode = (struct leanfs_inode *)malloc(sizeof(struct leanfs_inode));
|
|
|
|
memcpy(info->inode, buffer, sizeof(struct leanfs_inode));
|
|
|
|
if (parts == 1) {
|
|
if (type == 0) {
|
|
if (lfs_dir->type == ftDirectory) {
|
|
free(buffer2);
|
|
return info;
|
|
} else {
|
|
free(buffer2);
|
|
free(info->inode);
|
|
free(info);
|
|
return (void *)0;
|
|
}
|
|
} else if (type == 1) {
|
|
if (lfs_dir->type == ftFile) {
|
|
free(buffer2);
|
|
return info;
|
|
} else {
|
|
free(buffer2);
|
|
free(info->inode);
|
|
free(info);
|
|
return (void *)0;
|
|
}
|
|
} else {
|
|
free(buffer2);
|
|
return info;
|
|
}
|
|
|
|
} else {
|
|
free(buffer2);
|
|
return leanfs_find_sub_entry(device, info, ptr, 1, parts, type);
|
|
}
|
|
}
|
|
lfs_dir = (struct leanfs_direntry *)((char *)lfs_dir + lfs_dir->reclen);
|
|
}
|
|
}
|
|
|
|
int leanfs_get_dents(struct vfs_device_t *device, struct leanfs_file_info *info, char *buffer, int len, unsigned long long offset);
|
|
|
|
int leanfs_create_directory(struct vfs_device_t *device, char *path);
|
|
|
|
int leanfs_write_data(struct vfs_device_t *device, struct leanfs_file_info *info, char *filename, char *buffer, int len, unsigned long long offset);
|
|
|
|
int leanfs_trunc_file(struct vfs_device_t *device, struct leanfs_file_info *info, char *filename);
|
|
|
|
int leanfs_create_file(struct vfs_device_t *device, char *path);
|
|
|
|
int leanfs_read_data(struct vfs_device_t *device, struct leanfs_file_info *info, char *buffer, int len, unsigned long long offset);
|
|
|
|
int leanfs_change_directory(struct vfs_device_t *device, char *path);
|