StupidFS/libfs/inode.c
2024-08-27 10:39:09 +02:00

148 lines
2.6 KiB
C

#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include "inode.h"
#include "bio/bio.h"
#include "stupidfs.h"
#define IBLOCK(x) (x / STPDFS_INODES_PER_BLOCK + 2)
static struct fs_inode *head;
struct fs_inode *
fs_inode_alloc(struct fs_super *super)
{
uint32_t inum;
struct fs_buffer *buff;
struct stpdfs_inode *dinode;
for (inum = 1; inum < super->sb.isize; inum++)
{
buff = fs_bio_bread(super->fd, IBLOCK(inum));
dinode = (struct stpdfs_inode *)buff->data + inum % STPDFS_INODES_PER_BLOCK;
if ((dinode->flags & STPDFS_INO_FLAG_ALOC) == 0)
{
memset(dinode, 0, sizeof(struct stpdfs_inode));
dinode->flags = STPDFS_INO_FLAG_ALOC;
fs_bio_bwrite(buff);
fs_bio_brelse(buff);
return (fs_inode_get(super, inum));
}
fs_bio_brelse(buff);
}
return (NULL);
}
struct fs_inode *
fs_inode_get(struct fs_super *super, uint32_t inum)
{
struct fs_inode *ip;
for (ip = head; ip != NULL; ip = ip->next)
{
if (ip->inum == inum)
{
ip->refcount++;
return (ip);
}
}
ip = (struct fs_inode *)malloc(sizeof(struct fs_inode));
if (ip == NULL) return (NULL);
ip->super = super;
ip->inum = inum;
ip->refcount = 1;
ip->valid = 0;
return (ip);
}
struct fs_inode *
fs_inode_read(struct fs_inode *ip)
{
struct fs_buffer *buff;
struct stpdfs_inode *dinode;
if (ip == NULL) return (NULL);
buff = fs_bio_bread(ip->super->fd, IBLOCK(ip->inum));
if (buff == NULL) return (NULL);
dinode = (struct stpdfs_inode *)buff->data + ip->inum % STPDFS_INODES_PER_BLOCK;
memcpy(&ip->inode, dinode, sizeof(struct stpdfs_inode));
fs_bio_brelse(buff);
ip->valid = 1;
return (ip);
}
int
fs_inode_update(struct fs_inode *ip)
{
struct fs_buffer *buff;
struct stpdfs_inode *dinode;
buff = fs_bio_bread(ip->super->fd, IBLOCK(ip->inum));
if (buff == NULL) return (-1);
dinode = (struct stpdfs_inode *)buff->data + ip->inum % STPDFS_INODES_PER_BLOCK;
memcpy(dinode, &ip->inode, sizeof(struct stpdfs_inode));
fs_bio_bwrite(buff);
fs_bio_brelse(buff);
return (0);
}
void
fs_inode_release(struct fs_inode *ip)
{
struct fs_inode *tmp;
ip->refcount--;
if (ip->refcount > 0) return;
if (ip == head)
{
head = ip->next;
}
else
{
for (tmp = head; tmp != NULL; tmp = tmp->next)
{
if (tmp->next == tmp)
{
tmp->next = ip->next;
break;
}
}
}
free(ip);
}
int
fs_inode_stat(struct fs_inode *ip, struct stat *st)
{
if (ip == NULL || st == NULL)
{
return (-1);
}
if (ip->valid == 0)
{
fs_inode_read(ip);
}
st->st_atime = ip->inode.actime;
st->st_mode = ip->inode.mode;
st->st_gid = ip->inode.gid;
st->st_uid = ip->inode.uid;
return (0);
}