1474 lines
40 KiB
C
1474 lines
40 KiB
C
#include "vfs.h"
|
|
#include "minix.h"
|
|
#include "memory.h"
|
|
#include "string.h"
|
|
#include "ramdisk.h"
|
|
#include "hd.h"
|
|
#include "console.h"
|
|
|
|
unsigned int minix_alloc_bit(struct vfs_device_t *device, int map, unsigned int bit);
|
|
struct minix_inode *minix_get_inode(struct vfs_device_t *device, int ino);
|
|
struct minix_file_info *minix_check_if_exists(struct vfs_device_t *device, char *path, int type);
|
|
struct minix_inode *minix_alloc_inode(struct vfs_device_t *device, unsigned short mode, unsigned int *ino);
|
|
|
|
unsigned int minix_alloc_zone(struct vfs_device_t *device, unsigned int z) {
|
|
return minix_alloc_bit(device, 1, z);
|
|
}
|
|
|
|
unsigned int minix_free_zone(struct vfs_device_t *device, unsigned int z) {
|
|
return minix_free_bit(device, 1, z);
|
|
}
|
|
|
|
unsigned int minix_rd_indir(char *buffer, int index) {
|
|
unsigned int *ptr = (unsigned int *)buffer;
|
|
return ptr[index];
|
|
}
|
|
|
|
void minix_wr_indir(char *buffer, int index, int value) {
|
|
unsigned int *ptr = (unsigned int *)buffer;
|
|
ptr[index] = value;
|
|
}
|
|
|
|
int minix_empty_indir(char *bp, struct minix_super_block *sb) {
|
|
unsigned int i;
|
|
for (i=0;i<(sb->s_blocksize / 4); i++) {
|
|
if (minix_rd_indir(bp, i) != 0) {
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int minix_add_directory_entry(struct vfs_device_t *device, struct minix_inode *dir, int dir_ino, char *name, int ino) {
|
|
struct minix_data *mdata = (struct minix_data *)device->fs_data;
|
|
int i, j, k;
|
|
char *buffer;
|
|
struct minix_dir_entry *direntry;
|
|
|
|
unsigned int blockstoread = dir->i_size / mdata->sb.s_blocksize;
|
|
unsigned int blockno;
|
|
|
|
if (dir->i_size % mdata->sb.s_blocksize) {
|
|
blockstoread++;
|
|
}
|
|
|
|
unsigned int old_entrys = dir->i_size / sizeof(struct minix_dir_entry);
|
|
unsigned int new_entrys = ((blockstoread * mdata->sb.s_blocksize) / sizeof(struct minix_dir_entry)) - old_entrys;
|
|
|
|
buffer = (char *)malloc(mdata->sb.s_blocksize);
|
|
if (!buffer) {
|
|
return 0;
|
|
}
|
|
|
|
for (k=0;k<blockstoread;k++) {
|
|
blockno = minix_read_map(device, dir, (unsigned long long)(k * mdata->sb.s_blocksize));
|
|
if (blockno == 0) {
|
|
kprintf("Unable to read map??!\n");
|
|
return 0;
|
|
}
|
|
if (device->device == 1) {
|
|
ramdisk_read_block(blockno, buffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), blockno, buffer, mdata->sb.s_blocksize);
|
|
}
|
|
|
|
|
|
for (i=0;i<mdata->sb.s_blocksize / sizeof(struct minix_dir_entry) && i + k * (mdata->sb.s_blocksize / sizeof(struct minix_dir_entry)) < old_entrys;i++) {
|
|
direntry = (struct minix_dir_entry *)&buffer[i * sizeof(struct minix_dir_entry)];
|
|
|
|
if (direntry->inode == 0) {
|
|
direntry->inode = ino;
|
|
for (j=0;j<60 && j < strlen(name);j++) {
|
|
direntry->name[j] = name[j];
|
|
}
|
|
if (device->device == 1) {
|
|
ramdisk_write_block(blockno, buffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_block((device->device & 0xff), blockno, buffer, mdata->sb.s_blocksize);
|
|
}
|
|
// kprintf("Found old entry old entrys %d, this entry %d\n", old_entrys, i);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (i + k * (mdata->sb.s_blocksize / sizeof(struct minix_dir_entry)) == old_entrys) {
|
|
if (new_entrys > 0) {
|
|
direntry = (struct minix_dir_entry *)&buffer[i * sizeof(struct minix_dir_entry)];
|
|
direntry->inode = ino;
|
|
for (j=0;j<60 && j < strlen(name);j++) {
|
|
direntry->name[j] = name[j];
|
|
}
|
|
|
|
if (device->device == 1) {
|
|
ramdisk_write_block(blockno, buffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_block((device->device & 0xff), blockno, buffer, mdata->sb.s_blocksize);
|
|
}
|
|
|
|
dir->i_size += sizeof(struct minix_dir_entry);
|
|
minix_write_inode(device, dir_ino, dir);
|
|
// kprintf("Found new entry on old block\n");
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// no free spaces, allocate some more space
|
|
unsigned int new_zone = minix_alloc_zone(device, blockno);
|
|
unsigned int old_size = dir->i_size;
|
|
|
|
dir->i_size += sizeof(struct minix_dir_entry);
|
|
|
|
minix_write_map(device, dir, dir_ino, old_size, new_zone, 0);
|
|
|
|
blockno = minix_read_map(device, dir, old_size);
|
|
|
|
memset(buffer, 0, sizeof(mdata->sb.s_blocksize));
|
|
|
|
direntry = (struct minix_dir_entry *)buffer;
|
|
direntry->inode = ino;
|
|
for (j=0;j<60 && j < strlen(name);j++) {
|
|
direntry->name[j] = name[j];
|
|
}
|
|
|
|
if (device->device == 1) {
|
|
ramdisk_write_block(blockno, buffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_block((device->device & 0xff), blockno, buffer, mdata->sb.s_blocksize);
|
|
}
|
|
|
|
// kprintf("Allocated new block for entry\n");
|
|
return 1;
|
|
}
|
|
|
|
static struct minix_inode *minix_new_node(struct vfs_device_t *device, struct minix_inode *dirp, unsigned int dir_ino, char *name, unsigned short mode, unsigned int z0) {
|
|
struct minix_inode *new_inode;
|
|
unsigned int ino;
|
|
|
|
if (dirp->i_nlinks == 0) {
|
|
return (void *)0;
|
|
}
|
|
|
|
if (mode & S_IFDIR && dirp->i_nlinks >= 32767) {
|
|
return (void *)0;
|
|
}
|
|
|
|
new_inode = minix_alloc_inode(device, mode, &ino);
|
|
new_inode->i_nlinks++;
|
|
new_inode->i_zone[0] = z0;
|
|
|
|
minix_write_inode(device, ino, new_inode);
|
|
|
|
// add directory entry
|
|
if (!minix_add_directory_entry(device, dirp, dir_ino, name, ino)) {
|
|
// free inode
|
|
minix_free_inode(device, ino);
|
|
return (void *)0;
|
|
}
|
|
return new_inode;
|
|
}
|
|
|
|
int minix_create_file(struct vfs_device_t *device, char *path) {
|
|
if (minix_check_if_exists(device, path, -1)) {
|
|
return -1;
|
|
}
|
|
char *path_copy = (char *)malloc(strlen(path) + 1);
|
|
char *basename;
|
|
int i;
|
|
|
|
strcpy(path_copy, path);
|
|
|
|
for (i=strlen(path_copy)-1;i >= 0; i--) {
|
|
if (path_copy[i] == '/') {
|
|
path_copy[i] = '\0';
|
|
basename = &path_copy[i+1];
|
|
break;
|
|
}
|
|
}
|
|
|
|
// kprintf("DIR: %s. FILE: %s.\n", path_copy, basename);
|
|
|
|
struct minix_file_info *minfo;
|
|
struct minix_inode *dirp;
|
|
struct minix_inode *new_node;
|
|
if (strlen(path_copy) > 0) {
|
|
// kprintf("Not root\n");
|
|
minfo = minix_check_if_exists(device, path_copy, 0);
|
|
dirp = minix_get_inode(device, minfo->inode);
|
|
new_node = minix_new_node(device, dirp, minfo->inode, basename, S_IFREG, minix_alloc_zone(device, 0));
|
|
} else {
|
|
dirp = minix_get_inode(device, 1);
|
|
new_node = minix_new_node(device, dirp, 1, basename, S_IFREG, minix_alloc_zone(device, 0));
|
|
}
|
|
|
|
if (!new_node) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int minix_write_map(struct vfs_device_t *device, struct minix_inode *inode, int ino, unsigned long long position, unsigned int new_zone, int op) {
|
|
struct minix_data *mdata = (struct minix_data *)device->fs_data;
|
|
unsigned int scale = mdata->sb.s_log_zone_size;
|
|
unsigned int zone = (position / mdata->sb.s_blocksize) >> scale;
|
|
unsigned int excess;
|
|
unsigned int nr_indirects = mdata->sb.s_blocksize / 4;
|
|
unsigned int z, z1, z2 = 0;
|
|
unsigned int old_zone;
|
|
int ex;
|
|
int single;
|
|
int new_ind;
|
|
int new_dbl;
|
|
int ind_ex;
|
|
unsigned int b, b_indr;
|
|
char *buffer_indr = (void *)0;
|
|
char *buffer = (void *)0;
|
|
|
|
if (zone < 7) {
|
|
if (inode->i_zone[zone] != 0 && (op == 1)) {
|
|
} else {
|
|
inode->i_zone[zone] = new_zone;
|
|
}
|
|
minix_write_inode(device, ino, inode);
|
|
return 1;
|
|
}
|
|
|
|
excess = zone - 7;
|
|
|
|
new_dbl = 0;
|
|
new_ind = 0;
|
|
|
|
if (excess < nr_indirects) {
|
|
z1 = inode->i_zone[7];
|
|
single = 1;
|
|
} else {
|
|
if ((z2 = z = inode->i_zone[8]) == 0 && op == 0) {
|
|
if ((z = minix_alloc_zone(device, inode->i_zone[0])) == 0){
|
|
return 0;
|
|
}
|
|
inode->i_zone[8] = z;
|
|
new_dbl = 1;
|
|
}
|
|
excess -= nr_indirects;
|
|
ind_ex = (int)(excess / nr_indirects);
|
|
if (ind_ex >= nr_indirects) return 0;
|
|
|
|
if (z == 0 && op == 1) {
|
|
z1 = 0;
|
|
} else {
|
|
b_indr = z << scale;
|
|
buffer_indr = (char *)malloc(mdata->sb.s_blocksize);
|
|
if (!buffer_indr) {
|
|
return 0;
|
|
}
|
|
|
|
if (!new_dbl) {
|
|
if (device->device == 1) {
|
|
ramdisk_read_block(b_indr, buffer_indr, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), b_indr, buffer_indr, mdata->sb.s_blocksize);
|
|
}
|
|
} else {
|
|
memset(buffer_indr, 0, mdata->sb.s_blocksize);
|
|
}
|
|
z1 = minix_rd_indir(buffer_indr, ind_ex);
|
|
}
|
|
single = 0;
|
|
}
|
|
|
|
if (z1 == 0 && op == 0) {
|
|
z1 = minix_alloc_zone(device, inode->i_zone[0]);
|
|
if (single) {
|
|
inode->i_zone[7] = z1;
|
|
} else {
|
|
minix_wr_indir(buffer, ind_ex, z1);
|
|
}
|
|
new_ind = 1;
|
|
if (buffer_indr) {
|
|
if (device->device == 1) {
|
|
ramdisk_write_block(b_indr, buffer_indr, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_block((device->device & 0xff), b_indr, buffer_indr, mdata->sb.s_blocksize);
|
|
}
|
|
free(buffer_indr);
|
|
buffer_indr = (void *)0;
|
|
}
|
|
|
|
if (z1 == 0) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (z1 != 0) {
|
|
ex = (int)excess;
|
|
b = z1 << scale;
|
|
buffer = (char *)malloc(mdata->sb.s_blocksize);
|
|
if (!buffer) {
|
|
return 0;
|
|
}
|
|
if (!new_ind) {
|
|
if (device->device == 1) {
|
|
ramdisk_read_block(b, buffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), b, buffer, mdata->sb.s_blocksize);
|
|
}
|
|
} else {
|
|
memset(buffer, 0, mdata->sb.s_blocksize);
|
|
}
|
|
|
|
if (op == 1) {
|
|
if ((old_zone == minix_rd_indir(buffer, ex)) != 0) {
|
|
minix_free_zone(device, old_zone);
|
|
minix_wr_indir(buffer, ex, 0);
|
|
}
|
|
if (minix_empty_indir(buffer, &mdata->sb)) {
|
|
minix_free_zone(device, z1);
|
|
z1 = 0;
|
|
|
|
if (single) {
|
|
inode->i_zone[7] = z1;
|
|
} else {
|
|
if (device->device == 1) {
|
|
ramdisk_write_block(b_indr, buffer_indr, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_block((device->device & 0xff), b_indr, buffer_indr, mdata->sb.s_blocksize);
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
minix_wr_indir(buffer, ex, new_zone);
|
|
}
|
|
if (z1 != 0) {
|
|
if (device->device == 1) {
|
|
ramdisk_write_block(b, buffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_block((device->device & 0xff), b, buffer, mdata->sb.s_blocksize);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (z1 == 0 && !single && z2 != 0 && minix_empty_indir(buffer, &mdata->sb)) {
|
|
minix_free_zone(device, z2);
|
|
inode->i_zone[8] = 0;
|
|
}
|
|
|
|
free(buffer);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int minix_read_map(struct vfs_device_t *device, struct minix_inode *inode, unsigned long long position) {
|
|
struct minix_data *mdata = (struct minix_data *)device->fs_data;
|
|
int scale = mdata->sb.s_log_zone_size;
|
|
int zind;
|
|
int index;
|
|
|
|
unsigned int block_pos = position / mdata->sb.s_blocksize;
|
|
unsigned int zone = block_pos >> scale;
|
|
unsigned int z;
|
|
unsigned int b;
|
|
unsigned int excess;
|
|
int boff = (int)(block_pos - (zone << scale));
|
|
unsigned int dzones = 7;
|
|
unsigned int nr_indirects = mdata->sb.s_blocksize / 4;
|
|
char *buffer;
|
|
|
|
if (zone < dzones) {
|
|
zind = (int) zone;
|
|
z = inode->i_zone[zind];
|
|
if (z == NO_ZONE) {
|
|
// kprintf("0.");
|
|
return NO_BLOCK;
|
|
}
|
|
b = (unsigned int)((z << scale) + boff);
|
|
return b;
|
|
}
|
|
|
|
excess = zone - dzones;
|
|
|
|
if (excess < nr_indirects) {
|
|
z = inode->i_zone[dzones];
|
|
} else {
|
|
if ((z = inode->i_zone[dzones+1]) == NO_ZONE) {
|
|
// kprintf("A.");
|
|
return NO_BLOCK;
|
|
}
|
|
excess -= nr_indirects;
|
|
b = (unsigned int) z << scale;
|
|
index = (int)(excess/nr_indirects);
|
|
|
|
if ((unsigned int) index > nr_indirects) {
|
|
// kprintf("1.");
|
|
return NO_BLOCK;
|
|
}
|
|
|
|
buffer = (char *)malloc(mdata->sb.s_blocksize);
|
|
if (!buffer) {
|
|
// kprintf("2.");
|
|
return NO_BLOCK;
|
|
}
|
|
|
|
if (device->device == 1) {
|
|
ramdisk_read_block(b, buffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), b, buffer, mdata->sb.s_blocksize);
|
|
}
|
|
|
|
z = minix_rd_indir(buffer, index);
|
|
|
|
free(buffer);
|
|
excess = excess % nr_indirects;
|
|
}
|
|
|
|
if (z == NO_ZONE) {
|
|
// kprintf("3.");
|
|
return NO_BLOCK;
|
|
}
|
|
|
|
b = z << scale;
|
|
buffer = (char *)malloc(mdata->sb.s_blocksize);
|
|
if (!buffer) {
|
|
// kprintf("4.");
|
|
return NO_BLOCK;
|
|
}
|
|
|
|
if (device->device == 1) {
|
|
ramdisk_read_block(b, buffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), b, buffer, mdata->sb.s_blocksize);
|
|
}
|
|
|
|
z = minix_rd_indir(buffer, (int)excess);
|
|
free(buffer);
|
|
|
|
if (z == NO_ZONE) {
|
|
// kprintf("5.");
|
|
return NO_BLOCK;
|
|
}
|
|
b = (z << scale) + boff;
|
|
return b;
|
|
}
|
|
|
|
void minix_free_bit(struct vfs_device_t *device, int map, unsigned int bit) {
|
|
struct minix_data *mdata = (struct vfs_device_t *)device->fs_data;
|
|
unsigned long mask, offset, index;
|
|
|
|
index = bit / 8;
|
|
offset = bit % 8;
|
|
|
|
mask = ~(1<<offset);
|
|
|
|
if (map == 0) {
|
|
mdata->s_imap[index] &= mask;
|
|
if (device->device == 1) {
|
|
ramdisk_write_blocks(2, mdata->sb.s_imap_blocks, mdata->s_imap, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_blocks((device->device & 0xff), 2, mdata->sb.s_imap_blocks, mdata->s_imap, mdata->sb.s_blocksize);
|
|
}
|
|
} else {
|
|
mdata->s_zmap[index] &= mask;
|
|
if (device->device == 1) {
|
|
ramdisk_write_blocks(2 + mdata->sb.s_imap_blocks, mdata->sb.s_zmap_blocks, mdata->s_zmap, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_blocks((device->device & 0xff), 2 + mdata->sb.s_imap_blocks, mdata->sb.s_zmap_blocks, mdata->s_zmap, mdata->sb.s_blocksize);
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned int minix_alloc_bit(struct vfs_device_t *device, int map, unsigned int bit) {
|
|
struct minix_data *mdata = (struct minix_data *)device->fs_data;
|
|
unsigned int mask, offset, index, i;
|
|
int j;
|
|
int oldbit;
|
|
|
|
if (map == 0) {
|
|
oldbit = mdata->sb.s_ninodes;
|
|
} else {
|
|
oldbit = mdata->sb.s_zones;
|
|
}
|
|
|
|
for (j=0;j<2;j++) {
|
|
if (map == 0) {
|
|
// inode map
|
|
for (i=bit;i<oldbit;i++) {
|
|
mask = 1;
|
|
index = i / 8;
|
|
offset = i % 8;
|
|
|
|
if (!(mdata->s_imap[index] & (mask << offset))) {
|
|
mdata->s_imap[index] |= (mask << offset);
|
|
|
|
// write out inode table
|
|
if (device->device == 1) {
|
|
ramdisk_write_blocks(2, mdata->sb.s_imap_blocks, mdata->s_imap, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_blocks((device->device & 0xff), 2, mdata->sb.s_imap_blocks, mdata->s_imap, mdata->sb.s_blocksize);
|
|
}
|
|
return i;
|
|
}
|
|
}
|
|
} else {
|
|
// zone map
|
|
for (i=bit;i<oldbit;i++) {
|
|
mask = 1;
|
|
index = i / 8;
|
|
offset = i % 8;
|
|
|
|
if (!(mdata->s_zmap[index] & (mask << offset))) {
|
|
mdata->s_zmap[index] |= (mask << offset);
|
|
|
|
// write out zone table
|
|
if (device->device == 1) {
|
|
ramdisk_write_blocks(2 + mdata->sb.s_imap_blocks, mdata->sb.s_zmap_blocks, mdata->s_zmap, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_blocks((device->device & 0xff), 2 + mdata->sb.s_imap_blocks, mdata->sb.s_zmap_blocks, mdata->s_zmap, mdata->sb.s_blocksize);
|
|
}
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
if (bit == 0) {
|
|
break;
|
|
}
|
|
|
|
oldbit = bit + 1;
|
|
bit = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int minix_write_inode(struct vfs_device_t *device, unsigned int ino, struct minix_inode *inode) {
|
|
struct minix_data *mdata = (struct minix_data *)device->fs_data;
|
|
ino--;
|
|
unsigned int block = mdata->inode_table_start_block + ino / (mdata->sb.s_blocksize / sizeof(struct minix_inode));
|
|
char *buffer = (char *)malloc(mdata->sb.s_blocksize);
|
|
|
|
if (!buffer) {
|
|
return 0;
|
|
}
|
|
|
|
if (device->device == 1) {
|
|
ramdisk_read_block(block, buffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), block, buffer, mdata->sb.s_blocksize);
|
|
}
|
|
|
|
memcpy(&buffer[(ino % (mdata->sb.s_blocksize / sizeof(struct minix_inode))) * sizeof(struct minix_inode)], inode, sizeof(struct minix_inode));
|
|
|
|
if (device->device == 1) {
|
|
ramdisk_write_block(block, buffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_block((device->device & 0xff), block, buffer, mdata->sb.s_blocksize);
|
|
}
|
|
|
|
free(buffer);
|
|
|
|
return 1;
|
|
}
|
|
|
|
char *minix_get_block_map(struct vfs_device_t *device, struct minix_inode *inode, unsigned long long position) {
|
|
struct minix_data *mdata = (struct minix_data *)device->fs_data;
|
|
char *buffer;
|
|
|
|
unsigned int b = minix_read_map(device, inode, position);
|
|
if (b == 0) {
|
|
return (void *)0;
|
|
}
|
|
|
|
buffer = (char *)malloc(mdata->sb.s_blocksize);
|
|
|
|
if (!buffer) {
|
|
return (void *)0;
|
|
}
|
|
|
|
if (device->device == 1) {
|
|
ramdisk_read_block(b, buffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), b, buffer, mdata->sb.s_blocksize);
|
|
}
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
void minix_put_block_map(struct vfs_device_t *device, struct minix_inode *inode, unsigned long long position, char *buffer) {
|
|
struct minix_data *mdata = (struct minix_data *)device->fs_data;
|
|
unsigned int b = minix_read_map(device, inode, position);
|
|
if (b == 0) {
|
|
return (void *)0;
|
|
}
|
|
if (device->device == 1) {
|
|
ramdisk_write_block(b, buffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_block((device->device & 0xff), b, buffer, mdata->sb.s_blocksize);
|
|
}
|
|
free(buffer);
|
|
}
|
|
|
|
void minix_zerozone_range(struct vfs_device_t *device, struct minix_inode *inode, unsigned int pos, unsigned int len) {
|
|
struct minix_data *mdata = (struct minix_data *)device->fs_data;
|
|
char *buffer;
|
|
unsigned int offset;
|
|
unsigned int bytes;
|
|
if (!len) return;
|
|
|
|
while (len > 0) {
|
|
buffer = minix_get_block_map(device, inode, (pos / mdata->sb.s_blocksize) * pos);
|
|
offset = pos % mdata->sb.s_blocksize;
|
|
bytes = mdata->sb.s_blocksize - offset;
|
|
|
|
if (bytes > len) {
|
|
bytes = len;
|
|
}
|
|
|
|
memset(buffer + offset, 0, bytes);
|
|
|
|
minix_put_block_map(device, inode, (pos / mdata->sb.s_blocksize) * pos, buffer);
|
|
|
|
pos += bytes;
|
|
len -= bytes;
|
|
}
|
|
}
|
|
|
|
unsigned int minix_nextblock(unsigned int pos, int zone_size) {
|
|
unsigned int p;
|
|
|
|
p = (pos / zone_size) * zone_size;
|
|
if ((pos % zone_size)) p += zone_size;
|
|
|
|
return p;
|
|
}
|
|
|
|
void minix_zerozone_half(struct vfs_device_t *device, struct minix_inode *inode, unsigned int pos, int half, int zone_size) {
|
|
unsigned int offset, len;
|
|
|
|
offset = pos % zone_size;
|
|
|
|
if (half == 1) {
|
|
len = zone_size - offset;
|
|
} else {
|
|
len = offset;
|
|
}
|
|
|
|
minix_zerozone_range(device, inode, pos, len);
|
|
}
|
|
|
|
int minix_clear_zones(struct vfs_device_t *device, int ino, unsigned int start, unsigned int end) {
|
|
struct minix_data *mdata = (struct minix_data *)device->fs_data;
|
|
struct minix_inode *inode = minix_get_inode(device, ino);
|
|
unsigned int e;
|
|
unsigned int p;
|
|
int zone_size;
|
|
int zero_first, zero_last;
|
|
if (end > inode->i_size) {
|
|
end = inode->i_size;
|
|
}
|
|
|
|
if (end <= start) {
|
|
return 0;
|
|
}
|
|
|
|
zone_size = mdata->sb.s_blocksize << mdata->sb.s_log_zone_size;
|
|
|
|
zero_last = start % zone_size;
|
|
zero_first = end % zone_size && end < inode->i_size;
|
|
|
|
if (start / zone_size == (end - 1) / zone_size && (zero_last || zero_first)) {
|
|
minix_zerozone_range(device, inode, start, end - start);
|
|
} else {
|
|
if (zero_last)
|
|
minix_zerozone_half(device, inode, start, 1, zone_size);
|
|
if (zero_first)
|
|
minix_zerozone_half(device, inode, end, 0, zone_size);
|
|
|
|
e = end / zone_size;
|
|
|
|
if (end == inode->i_size && (end % zone_size)) e++;
|
|
for (p = minix_nextblock(start, zone_size) / zone_size; p < e; p++) {
|
|
minix_write_map(device, inode, ino, p * zone_size, 0, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void minix_trunc_file(struct vfs_device_t *device, struct minix_file_info *finfo, char *path) {
|
|
minix_clear_zones(device, finfo->inode, 0, finfo->file_size);
|
|
}
|
|
|
|
void minix_free_inode(struct vfs_device_t *device, unsigned int ino) {
|
|
minix_free_bit(device, 0, ino);
|
|
}
|
|
|
|
struct minix_inode *minix_alloc_inode(struct vfs_device_t *device, unsigned short mode, unsigned int *ino) {
|
|
unsigned int b;
|
|
struct minix_inode *new_inode;
|
|
|
|
b = minix_alloc_bit(device, 0, 0);
|
|
|
|
if (b == 0) {
|
|
return (void *)0;
|
|
}
|
|
|
|
new_inode = (struct minix_inode *)malloc(sizeof(struct minix_inode));
|
|
|
|
if (!new_inode) {
|
|
minix_free_bit(device, 0, b);
|
|
}
|
|
memset(new_inode, 0, sizeof(struct minix_inode));
|
|
new_inode->i_mode = mode;
|
|
|
|
minix_write_inode(device, b, new_inode);
|
|
*ino = b;
|
|
// kprintf("INODE %d\n", b);
|
|
return new_inode;
|
|
}
|
|
|
|
struct minix_inode *minix_get_inode(struct vfs_device_t *device, int ino) {
|
|
struct minix_data *mdata = (struct minix_data *)device->fs_data;
|
|
int inodes_per_block = mdata->sb.s_blocksize / sizeof(struct minix_inode);
|
|
unsigned int block;
|
|
|
|
char *buffer = (char *)malloc(mdata->sb.s_blocksize);
|
|
|
|
if (!buffer) {
|
|
return (void *)0;
|
|
}
|
|
|
|
|
|
struct minix_inode *inode = (struct minix_inode *)malloc(sizeof(struct minix_inode));
|
|
|
|
if (!inode) {
|
|
free(buffer);
|
|
return (void *)0;
|
|
}
|
|
|
|
if (ino == 0 || ino > mdata->sb.s_ninodes) {
|
|
free(buffer);
|
|
free(inode);
|
|
return (void *)0;
|
|
}
|
|
|
|
ino--;
|
|
|
|
block = mdata->inode_table_start_block + ino / inodes_per_block;
|
|
|
|
if (device->device == 1) {
|
|
ramdisk_read_block(block, buffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), block, buffer, mdata->sb.s_blocksize);
|
|
}
|
|
|
|
memcpy(inode, &buffer[(ino % inodes_per_block) * sizeof(struct minix_inode)], sizeof(struct minix_inode));
|
|
free(buffer);
|
|
|
|
return inode;
|
|
}
|
|
|
|
unsigned int minix_read_entire_file(struct vfs_device_t *device, struct minix_inode *inode, char **buffer) {
|
|
struct minix_data *mdata = (struct minix_data *)device->fs_data;
|
|
int i;
|
|
int blockstoread;
|
|
char *buffer2;
|
|
int blockno;
|
|
unsigned int size;
|
|
char *buffer_loc;
|
|
|
|
size = inode->i_size;
|
|
|
|
|
|
unsigned int bytesleft = size;
|
|
|
|
|
|
|
|
blockstoread = size / mdata->sb.s_blocksize;
|
|
|
|
|
|
if (size % mdata->sb.s_blocksize) {
|
|
blockstoread++;
|
|
}
|
|
|
|
*buffer = (char *)malloc(size);
|
|
if (!*buffer) {
|
|
return -1;
|
|
}
|
|
buffer_loc = *buffer;
|
|
buffer2 = (char *)malloc(mdata->sb.s_blocksize);
|
|
if (!buffer2) {
|
|
free(*buffer);
|
|
return -1;
|
|
}
|
|
|
|
for (i=0;i<blockstoread;i++) {
|
|
blockno = minix_read_map(device, inode, (unsigned long long)(i * mdata->sb.s_blocksize));
|
|
|
|
//kprintf("Blockno: %d To Read: %d\n", blockno, blockstoread);
|
|
|
|
if (device->device == 1) {
|
|
ramdisk_read_block(blockno, buffer2, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), blockno, buffer2, mdata->sb.s_blocksize);
|
|
}
|
|
|
|
if (bytesleft > mdata->sb.s_blocksize) {
|
|
memcpy(&buffer_loc[i * mdata->sb.s_blocksize], buffer2, mdata->sb.s_blocksize);
|
|
bytesleft -= mdata->sb.s_blocksize;
|
|
} else {
|
|
memcpy(&buffer_loc[i * mdata->sb.s_blocksize], buffer2, bytesleft);
|
|
}
|
|
}
|
|
free(buffer2);
|
|
return size;
|
|
}
|
|
|
|
struct minix_file_info *minix_find_sub_entry(struct vfs_device_t *device, unsigned int ino, char **ptr, int part, int parts, int type) {
|
|
int i;
|
|
char *buffer;
|
|
struct minix_inode *inode;
|
|
struct minix_inode *pinode;
|
|
struct minix_dir_entry *dir;
|
|
struct minix_file_info *fileinf;
|
|
int size;
|
|
int childinode;
|
|
inode = minix_get_inode(device, ino);
|
|
|
|
if (!inode) {
|
|
return (void *)0;
|
|
}
|
|
|
|
if (S_IFDIR & inode->i_mode) {
|
|
// find direntry for part 0;
|
|
size = minix_read_entire_file(device, inode, &buffer);
|
|
if (size > 0) {
|
|
for (i=0;i<size/sizeof(struct minix_dir_entry);i++) {
|
|
dir = &((struct minix_dir_entry *)buffer)[i];
|
|
|
|
if (parts == part + 1) {
|
|
if (strcmp(dir->name, ptr[part]) == 0) {
|
|
pinode = minix_get_inode(device, dir->inode);
|
|
if (pinode != (void *)0) {
|
|
if (pinode->i_nlinks > 0) {
|
|
if (type == 0 && (pinode->i_mode & S_IFDIR)) {
|
|
fileinf = (struct minix_file_info *)malloc(sizeof(struct minix_file_info));
|
|
if (!fileinf) {
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
return (void *)0;
|
|
}
|
|
|
|
fileinf->inode = dir->inode;
|
|
fileinf->file_size = pinode->i_size;
|
|
fileinf->type = 0;
|
|
fileinf->atime = pinode->i_atime;
|
|
fileinf->ctime = pinode->i_ctime;
|
|
fileinf->mtime = pinode->i_mtime;
|
|
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
return fileinf;
|
|
} else if (type == 1 && (pinode->i_mode & S_IFREG)) {
|
|
fileinf = (struct minix_file_info *)malloc(sizeof(struct minix_file_info));
|
|
if (!fileinf) {
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
return (void *)0;
|
|
}
|
|
|
|
fileinf->inode = dir->inode;
|
|
fileinf->file_size = pinode->i_size;
|
|
fileinf->type = 1;
|
|
fileinf->atime = pinode->i_atime;
|
|
fileinf->ctime = pinode->i_ctime;
|
|
fileinf->mtime = pinode->i_mtime;
|
|
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
return fileinf;
|
|
} else if (type == -1) {
|
|
fileinf = (struct minix_file_info *)malloc(sizeof(struct minix_file_info));
|
|
if (!fileinf) {
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
return (void *)0;
|
|
}
|
|
|
|
fileinf->inode = dir->inode;
|
|
fileinf->file_size = pinode->i_size;
|
|
if (pinode->i_mode & S_IFDIR) {
|
|
fileinf->type = 0;
|
|
} else {
|
|
fileinf->type = 1;
|
|
}
|
|
fileinf->atime = pinode->i_atime;
|
|
fileinf->ctime = pinode->i_ctime;
|
|
fileinf->mtime = pinode->i_mtime;
|
|
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
return fileinf;
|
|
} else {
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
return (void *)0;
|
|
}
|
|
} else {
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
return (void *)0;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (strcmp(dir->name, ptr[part]) == 0) {
|
|
pinode = minix_get_inode(device, dir->inode);
|
|
if (pinode->i_nlinks > 0 && pinode->i_mode & S_IFDIR) {
|
|
childinode = dir->inode;
|
|
free(pinode);
|
|
free(inode);
|
|
free(buffer);
|
|
return minix_find_sub_entry(device, childinode, ptr, part + 1, parts, type);
|
|
} else {
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
return (void *)0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
free(inode);
|
|
return (void *)0;
|
|
}
|
|
} else {
|
|
// root directory is not a directory ??
|
|
free(inode);
|
|
return (void *)0;
|
|
}
|
|
return (void *)0;
|
|
}
|
|
|
|
struct minix_file_info *minix_check_if_exists(struct vfs_device_t *device, char *path, int type) {
|
|
int i;
|
|
int parts = 0;
|
|
char *path_copy = (char *)malloc(strlen(path) + 1);
|
|
char *buffer;
|
|
struct minix_inode *inode;
|
|
struct minix_inode *pinode;
|
|
struct minix_dir_entry *dir;
|
|
struct minix_file_info *fileinf;
|
|
int size;
|
|
int childinode;
|
|
|
|
if (strcmp(path, "/") == 0) {
|
|
struct minix_file_info *info = (struct minix_file_info *)malloc(sizeof(struct minix_file_info));
|
|
if (!info) {
|
|
return (void *)0;
|
|
}
|
|
|
|
inode = minix_get_inode(device, 1);
|
|
|
|
info->inode = 1;
|
|
info->file_size = inode->i_size;
|
|
info->type = 0;
|
|
info->atime = inode->i_atime;
|
|
info->ctime = inode->i_ctime;
|
|
info->mtime = inode->i_mtime;
|
|
free(inode);
|
|
return info;
|
|
}
|
|
|
|
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 **)malloc(sizeof(char *) * parts );
|
|
|
|
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';
|
|
}
|
|
}
|
|
|
|
inode = minix_get_inode(device, 1);
|
|
if (!inode) {
|
|
return (void *)0;
|
|
}
|
|
|
|
if (S_IFDIR & inode->i_mode) {
|
|
// find direntry for part 0;
|
|
size = minix_read_entire_file(device, inode, &buffer);
|
|
if (size > 0) {
|
|
for (i=0;i<size/sizeof(struct minix_dir_entry);i++) {
|
|
dir = &((struct minix_dir_entry *)buffer)[i];
|
|
|
|
if (parts == 1) {
|
|
if (strcmp(dir->name, ptr[0]) == 0) {
|
|
pinode = minix_get_inode(device, dir->inode);
|
|
if (pinode != (void *)0) {
|
|
if (pinode->i_nlinks > 0) {
|
|
if (type == 0 && (pinode->i_mode & S_IFDIR)) {
|
|
fileinf = (struct minix_file_info *)malloc(sizeof(struct minix_file_info));
|
|
if (!fileinf) {
|
|
free(ptr);
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
return (void *)0;
|
|
}
|
|
|
|
fileinf->inode = dir->inode;
|
|
fileinf->file_size = pinode->i_size;
|
|
fileinf->type = 0;
|
|
fileinf->atime = pinode->i_atime;
|
|
fileinf->ctime = pinode->i_ctime;
|
|
fileinf->mtime = pinode->i_mtime;
|
|
free(ptr);
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
return fileinf;
|
|
} else if (type == 1 && (pinode->i_mode & S_IFREG)) {
|
|
fileinf = (struct minix_file_info *)malloc(sizeof(struct minix_file_info));
|
|
if (!fileinf) {
|
|
free(ptr);
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
return (void *)0;
|
|
}
|
|
|
|
fileinf->inode = dir->inode;
|
|
fileinf->file_size = pinode->i_size;
|
|
fileinf->type = 1;
|
|
fileinf->atime = pinode->i_atime;
|
|
fileinf->ctime = pinode->i_ctime;
|
|
fileinf->mtime = pinode->i_mtime;
|
|
free(ptr);
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
return fileinf;
|
|
} else if (type == -1) {
|
|
fileinf = (struct minix_file_info *)malloc(sizeof(struct minix_file_info));
|
|
if (!fileinf) {
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
free(ptr);
|
|
return (void *)0;
|
|
}
|
|
|
|
fileinf->inode = dir->inode;
|
|
fileinf->file_size = pinode->i_size;
|
|
if (pinode->i_mode & S_IFDIR) {
|
|
fileinf->type = 0;
|
|
} else {
|
|
fileinf->type = 1;
|
|
}
|
|
fileinf->atime = pinode->i_atime;
|
|
fileinf->ctime = pinode->i_ctime;
|
|
fileinf->mtime = pinode->i_mtime;
|
|
free(ptr);
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
return fileinf;
|
|
} else {
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
free(ptr);
|
|
return (void *)0;
|
|
}
|
|
} else {
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
free(ptr);
|
|
return (void *)0;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (strcmp(dir->name, ptr[0]) == 0) {
|
|
pinode = minix_get_inode(device, dir->inode);
|
|
if (pinode->i_nlinks > 0 && pinode->i_mode & S_IFDIR) {
|
|
childinode = dir->inode;
|
|
free(pinode);
|
|
free(inode);
|
|
free(buffer);
|
|
fileinf = minix_find_sub_entry(device, childinode, ptr, 1, parts, type);
|
|
free(ptr);
|
|
return fileinf;
|
|
} else {
|
|
free(inode);
|
|
free(pinode);
|
|
free(buffer);
|
|
return (void *)0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
free(inode);
|
|
return (void *)0;
|
|
}
|
|
} else {
|
|
// root directory is not a directory ??
|
|
free(inode);
|
|
return (void *)0;
|
|
}
|
|
|
|
return (void *)0;
|
|
}
|
|
|
|
int minix_change_directory(struct vfs_device_t *device, char *path) {
|
|
if (path[0] == '/' && path[1] == '\0') {
|
|
return 1;
|
|
} else {
|
|
if (minix_check_if_exists(device, path, 0)) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
int minix_read_data(struct vfs_device_t *device, struct minix_file_info *info, char *buffer, int len, unsigned long long offset) {
|
|
struct minix_data *mdata = (struct minix_data *)device->fs_data;
|
|
unsigned int blockcount;
|
|
unsigned int block_start;
|
|
unsigned int block_offset;
|
|
unsigned int j;
|
|
unsigned int blocks_read;
|
|
struct minix_inode *inode = minix_get_inode(device, info->inode);
|
|
unsigned int buffer_at;
|
|
char *tempbuffer;
|
|
|
|
if (!inode) {
|
|
return 0;
|
|
}
|
|
|
|
if (info->type == 0) {
|
|
free(inode);
|
|
return 0;
|
|
}
|
|
|
|
tempbuffer = (char *)malloc(mdata->sb.s_blocksize);
|
|
if (!tempbuffer) {
|
|
free(inode);
|
|
return 0;
|
|
}
|
|
|
|
if (len + offset > info->file_size) {
|
|
len = info->file_size - offset;
|
|
}
|
|
|
|
if (len > 0) {
|
|
block_start = offset / mdata->sb.s_blocksize;
|
|
block_offset = offset % mdata->sb.s_blocksize;
|
|
blockcount = len + block_offset / mdata->sb.s_blocksize;
|
|
|
|
if (len + block_offset % mdata->sb.s_blocksize > 0) {
|
|
blockcount += 1;
|
|
}
|
|
|
|
if (device->device == 1) {
|
|
for (j=0;j<blockcount;j++) {
|
|
ramdisk_read_block(minix_read_map(device, inode, (unsigned long long)(j * mdata->sb.s_blocksize)), tempbuffer, mdata->sb.s_blocksize);
|
|
if (j==0) {
|
|
if (len + block_offset > mdata->sb.s_blocksize) {
|
|
memcpy(buffer, &tempbuffer[block_offset], mdata->sb.s_blocksize - block_offset);
|
|
buffer_at = mdata->sb.s_blocksize - block_offset;
|
|
} else {
|
|
memcpy(buffer, &tempbuffer[block_offset], len);
|
|
free(tempbuffer);
|
|
free(inode);
|
|
return len;
|
|
}
|
|
} else {
|
|
if (len - buffer_at >= mdata->sb.s_blocksize) {
|
|
memcpy(&buffer[buffer_at], tempbuffer, mdata->sb.s_blocksize);
|
|
buffer_at += mdata->sb.s_blocksize;
|
|
} else {
|
|
memcpy(&buffer[buffer_at], tempbuffer, len - buffer_at);
|
|
free(tempbuffer);
|
|
free(inode);
|
|
return len;
|
|
}
|
|
}
|
|
}
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
for (j=0;j<blockcount;j++) {
|
|
hd_read_block((device->device & 0xff), minix_read_map(device, inode, (unsigned long long)(j * mdata->sb.s_blocksize)), tempbuffer, mdata->sb.s_blocksize);
|
|
if (j==0) {
|
|
if (len + block_offset > mdata->sb.s_blocksize) {
|
|
memcpy(buffer, &tempbuffer[block_offset], mdata->sb.s_blocksize - block_offset);
|
|
buffer_at = mdata->sb.s_blocksize - block_offset;
|
|
} else {
|
|
memcpy(buffer, &tempbuffer[block_offset], len);
|
|
free(tempbuffer);
|
|
free(inode);
|
|
return len;
|
|
}
|
|
} else {
|
|
if (len - buffer_at >= mdata->sb.s_blocksize) {
|
|
memcpy(&buffer[buffer_at], tempbuffer, mdata->sb.s_blocksize);
|
|
buffer_at += mdata->sb.s_blocksize;
|
|
} else {
|
|
memcpy(&buffer[buffer_at], tempbuffer, len - buffer_at);
|
|
free(tempbuffer);
|
|
free(inode);
|
|
return len;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
free(tempbuffer);
|
|
free(inode);
|
|
return 0;
|
|
}
|
|
|
|
int minix_get_dents(struct vfs_device_t *device, struct minix_file_info *info, char *buffer, int len, unsigned long long offset, int *newoffset) {
|
|
struct minix_inode *inode = minix_get_inode(device, info->inode);
|
|
char *buffer2;
|
|
int dirlen = minix_read_entire_file(device, inode, &buffer2);
|
|
char *dir_buffer;
|
|
unsigned int bytesread;
|
|
int buff_offset = 0;
|
|
int i;
|
|
if (offset >= dirlen) {
|
|
free(buffer2);
|
|
return 0;
|
|
}
|
|
|
|
dir_buffer = (char *)malloc(dirlen - offset + 1);
|
|
memcpy(dir_buffer, &buffer2[offset], dirlen - offset);
|
|
free(buffer2);
|
|
*newoffset = 0;
|
|
bytesread = dirlen - offset;
|
|
for (i=0;i<bytesread / sizeof(struct minix_dir_entry);i++) {
|
|
struct minix_dir_entry *dir = (struct minix_dir_entry *)(&dir_buffer[i * sizeof(struct minix_dir_entry)]);
|
|
struct quinn_dirent_t *dent = (struct quinn_dirent_t *)(&buffer[buff_offset]);
|
|
|
|
if (buff_offset + sizeof(struct quinn_dirent_t) + (strlen(dir->name)) > len) {
|
|
free(dir_buffer);
|
|
return buff_offset;
|
|
}
|
|
|
|
dent->name_len = strlen(dir->name);
|
|
dent->rec_len = sizeof(struct quinn_dirent_t) + strlen(dir->name);
|
|
dent->next_offset = buff_offset + dent->rec_len;
|
|
strcpy(dent->name, dir->name);
|
|
buff_offset = dent->next_offset;
|
|
*newoffset += sizeof(struct minix_dir_entry);
|
|
}
|
|
|
|
free(dir_buffer);
|
|
return buff_offset;
|
|
}
|
|
|
|
int minix_write_data(struct vfs_device_t *device, struct minix_file_info *info, char *filename, char *buffer, int len, unsigned long long offset) {
|
|
struct minix_data *mdata = (struct minix_data *)device->fs_data;
|
|
unsigned int zone_size = mdata->sb.s_blocksize << mdata->sb.s_log_zone_size;
|
|
struct minix_inode *inode = minix_get_inode(device, info->inode);
|
|
|
|
unsigned int blockcount;
|
|
unsigned int block_start;
|
|
unsigned int block_offset;
|
|
unsigned int i;
|
|
|
|
char *obuffer;
|
|
unsigned int block;
|
|
unsigned int last_block;
|
|
unsigned int buffer_at = 0;
|
|
obuffer = (char *)malloc(mdata->sb.s_blocksize);
|
|
if (!buffer) {
|
|
return 0;
|
|
}
|
|
|
|
if (info->type == 0) {
|
|
// it's a directory
|
|
free(inode);
|
|
free(obuffer);
|
|
return 0;
|
|
}
|
|
|
|
if (len > 0) {
|
|
block_start = offset / mdata->sb.s_blocksize;
|
|
block_offset = offset % mdata->sb.s_blocksize;
|
|
blockcount = len + block_offset / mdata->sb.s_blocksize;
|
|
|
|
for (i=0;i<blockcount;i++) {
|
|
block = minix_read_map(device, inode, i * mdata->sb.s_blocksize);
|
|
if (block == 0) {
|
|
if (!minix_write_map(device, inode, info->inode, i * mdata->sb.s_blocksize, minix_alloc_zone(device, last_block), 0)) {
|
|
if (inode->i_size < offset + buffer_at) {
|
|
inode->i_size = offset + buffer_at;
|
|
minix_write_inode(device, info->inode, inode);
|
|
}
|
|
free(obuffer);
|
|
free(inode);
|
|
return buffer_at;
|
|
}
|
|
block = minix_read_map(device, inode, i * mdata->sb.s_blocksize);
|
|
if (block == 0) {
|
|
if (inode->i_size < offset + buffer_at) {
|
|
inode->i_size = offset + buffer_at;
|
|
minix_write_inode(device, info->inode, inode);
|
|
}
|
|
free(obuffer);
|
|
free(inode);
|
|
|
|
return buffer_at;
|
|
}
|
|
} else {
|
|
last_block = block;
|
|
if (device->device == 1) {
|
|
ramdisk_read_block(block, obuffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), block, obuffer, mdata->sb.s_blocksize);
|
|
}
|
|
}
|
|
|
|
if (i==0) {
|
|
if (len + block_offset > mdata->sb.s_blocksize) {
|
|
memcpy(&obuffer[block_offset], buffer, mdata->sb.s_blocksize - block_offset);
|
|
buffer_at = mdata->sb.s_blocksize - block_offset;
|
|
if (device->device == 1) {
|
|
ramdisk_write_block(block, obuffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_block((device->device & 0xff), block, obuffer, mdata->sb.s_blocksize);
|
|
}
|
|
} else {
|
|
memcpy(&obuffer[block_offset], buffer, len);
|
|
if (device->device == 1) {
|
|
ramdisk_write_block(block, obuffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_block((device->device & 0xff), block, obuffer, mdata->sb.s_blocksize);
|
|
}
|
|
|
|
if (inode->i_size < offset + len) {
|
|
inode->i_size = offset + len;
|
|
minix_write_inode(device, info->inode, inode);
|
|
}
|
|
free(obuffer);
|
|
free(inode);
|
|
return len;
|
|
}
|
|
} else {
|
|
if (len - buffer_at >= mdata->sb.s_blocksize) {
|
|
memcpy(obuffer, &buffer[buffer_at], mdata->sb.s_blocksize);
|
|
buffer_at += mdata->sb.s_blocksize;
|
|
if (device->device == 1) {
|
|
ramdisk_write_block(block, obuffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_block((device->device & 0xff), block, obuffer, mdata->sb.s_blocksize);
|
|
}
|
|
} else {
|
|
memcpy(obuffer, &buffer[buffer_at], len - buffer_at);
|
|
if (device->device == 1) {
|
|
ramdisk_write_block(block, obuffer, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_write_block((device->device & 0xff), block, obuffer, mdata->sb.s_blocksize);
|
|
}
|
|
if (inode->i_size < offset + len) {
|
|
inode->i_size = offset + len;
|
|
minix_write_inode(device, info->inode, inode);
|
|
}
|
|
free(obuffer);
|
|
free(inode);
|
|
return len;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return buffer_at;
|
|
}
|
|
|
|
int minix_load_superblock(struct vfs_device_t *device) {
|
|
unsigned char *buffer;
|
|
struct minix_data *mdata;
|
|
|
|
buffer = (char *)malloc(1024);
|
|
if (!buffer) {
|
|
return 0;
|
|
}
|
|
|
|
mdata = (struct minix_data *)malloc(sizeof(struct minix_data));
|
|
|
|
if (!mdata) {
|
|
free(buffer);
|
|
return 0;
|
|
}
|
|
|
|
if (device->device == 1) {
|
|
ramdisk_read_block(1, buffer, 1024);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_block((device->device & 0xff), 1, buffer, 1024);
|
|
}
|
|
|
|
memcpy((char *)&mdata->sb, buffer, sizeof(struct minix_super_block));
|
|
|
|
if (mdata->sb.s_magic != 0x4d5a) {
|
|
// kprintf("MINIX FS: Unrecognized Filesystem %x\n", mdata->sb.s_magic);
|
|
free(buffer);
|
|
free(mdata);
|
|
return 0;
|
|
}
|
|
|
|
mdata->s_imap = (char *)malloc(mdata->sb.s_imap_blocks * mdata->sb.s_blocksize);
|
|
if (!mdata->s_imap) {
|
|
free(buffer);
|
|
free(mdata);
|
|
return 0;
|
|
}
|
|
mdata->s_zmap = (char *)malloc(mdata->sb.s_zmap_blocks * mdata->sb.s_blocksize);
|
|
if (!mdata->s_zmap) {
|
|
free(mdata->s_imap);
|
|
free(buffer);
|
|
free(mdata);
|
|
return 0;
|
|
}
|
|
|
|
if (device->device == 1) {
|
|
ramdisk_read_blocks(2, mdata->sb.s_imap_blocks, mdata->s_imap, mdata->sb.s_blocksize);
|
|
ramdisk_read_blocks(2 + mdata->sb.s_imap_blocks, mdata->sb.s_zmap_blocks, mdata->s_zmap, mdata->sb.s_blocksize);
|
|
} else if ((device->device & 0xff00) == 0x100) {
|
|
hd_read_blocks((device->device & 0xff), 2, mdata->sb.s_imap_blocks, mdata->s_imap, mdata->sb.s_blocksize);
|
|
hd_read_blocks((device->device & 0xff), 2 + mdata->sb.s_imap_blocks, mdata->sb.s_zmap_blocks, mdata->s_zmap, mdata->sb.s_blocksize);
|
|
}
|
|
|
|
mdata->inode_table_start_block = 2 + mdata->sb.s_imap_blocks + mdata->sb.s_zmap_blocks;
|
|
mdata->first_data_block = mdata->inode_table_start_block + ((mdata->sb.s_ninodes * sizeof(struct minix_inode)) / mdata->sb.s_blocksize);
|
|
kprintf("MINIX FS: Recognized Filesystem\n");
|
|
|
|
device->fs_data = mdata;
|
|
|
|
return 1;
|
|
}
|