StupidFS/libstpdfs/super.c
2024-07-27 10:57:23 +00:00

149 lines
No EOL
2.6 KiB
C

#include "stupidfs.h"
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <libstpdfs/stpdfs.h>
int
stpdfs_super_validate(struct stpdfs_sb *sb)
{
if (sb->magic != STPDFS_SB_MAGIC)
{
return (-1);
}
if (sb->revision != STPDFS_SB_REV)
{
return (-1);
}
if (sb->fsize == 0 || sb->isize == 0)
{
return (-1);
}
if (sb->isize > sb->fsize)
{
return (-1);
}
return (0);
}
int
stpdfs_super_open(struct stpdfs_super_info *sbi, const char *fname)
{
struct stpdfs_buffer *buff;
sbi->fd = open(fname, O_RDWR);
if (sbi->fd < 0)
{
perror(fname);
return (-1);
}
buff = stpdfs_bread(sbi->fd, 1);
if (!buff) goto err;
if (stpdfs_super_validate((struct stpdfs_sb *)buff->data) != 0) goto err;
memcpy(&sbi->sb, buff->data, sizeof(struct stpdfs_sb));
return (0);
err:
close(sbi->fd);
return (-1);
}
int
stpdfs_super_kill(struct stpdfs_super_info *sbi)
{
struct stpdfs_buffer *buff;
buff = stpdfs_bread(sbi->fd, 1);
if (buff == NULL) goto end;
memcpy(buff->data, &sbi->sb, sizeof(struct stpdfs_sb));
stpdfs_bwrite(buff);
stpdfs_brelse(buff);
end:
close(sbi->fd);
return (0);
}
uint32_t
stpdfs_super_balloc(struct stpdfs_super_info *sbi)
{
uint32_t blocknum;
struct stpdfs_free freelist;
struct stpdfs_buffer *buff;
sbi->sb.state = STPDFS_DIRTY;
redo:
sbi->sb.freelist.nfree--;
blocknum = sbi->sb.freelist.free[sbi->sb.freelist.nfree];
if (sbi->sb.freelist.nfree == 0 && blocknum != 0)
{
buff = stpdfs_bread(sbi->fd, blocknum);
memcpy(&sbi->sb.freelist, buff->data, sizeof(struct stpdfs_free));
goto redo;
}
buff = stpdfs_bread(sbi->fd, 1);
memcpy(buff->data, &sbi->sb, sizeof(struct stpdfs_sb));
stpdfs_bwrite(buff);
buff = stpdfs_bread(sbi->fd, blocknum);
memset(buff->data, 0, STPDFS_BLOCK_SIZE);
stpdfs_bwrite(buff);
stpdfs_brelse(buff);
sbi->sb.time = time(NULL);
return (blocknum);
}
int
stpdfs_super_bfreee(struct stpdfs_super_info *sbi, uint32_t blocknum)
{
struct stpdfs_free copy;
struct stpdfs_buffer *buff;
if (blocknum == 0 || blocknum >= sbi->sb.fsize)
{
return (-1);
}
sbi->sb.state = STPDFS_DIRTY;
if (sbi->sb.freelist.nfree == 100)
{
buff = stpdfs_bread(sbi->fd, blocknum);
memcpy(buff->data, &sbi->sb.freelist, sizeof(struct stpdfs_free));
stpdfs_bwrite(buff);
stpdfs_brelse(buff);
sbi->sb.freelist.nfree = 1;
sbi->sb.freelist.free[0] = blocknum;
}
else
{
sbi->sb.freelist.free[sbi->sb.freelist.nfree++] = blocknum;
}
sbi->sb.time = time(NULL);
buff = stpdfs_bread(sbi->fd, 1);
memcpy(buff->data, &sbi->sb, sizeof(struct stpdfs_sb));
stpdfs_bwrite(buff);
return (0);
}