Compare commits

...

2 commits

16 changed files with 371 additions and 159 deletions

View file

@ -62,7 +62,7 @@
struct stpdfs_free {
uint32_t free[100]; /**< List of free block (0-99), index 0 point to next freelist */
uint8_t nfree; /**< index */
} __attribute__((packed));
};
enum stpdfs_state {
STPDFS_CLEANLY_UNMOUNTED = 0,

View file

@ -42,7 +42,6 @@ redo:
int
fs_bfree(struct fs_super *super, uint32_t blocknum)
{
struct stpdfs_free copy;
struct fs_buffer *buff;
if (blocknum == 0 || blocknum >= super->sb.fsize)

View file

@ -59,7 +59,7 @@ fs_bio_bread(int fd, uint32_t blocknum)
void
fs_bio_bwrite(struct fs_buffer *buff)
{
fs_bio_raw_read(buff->fd, buff->blocknum, buff->data, STPDFS_BLOCK_SIZE);
fs_bio_raw_write(buff->fd, buff->blocknum, buff->data, STPDFS_BLOCK_SIZE);
}
void
@ -88,15 +88,3 @@ fs_bio_brelse(struct fs_buffer *buff)
free(buff);
}
void
stpdfs_bpin(struct fs_buffer *buff)
{
buff->refcount++;
}
void
stpdfs_bunpin(struct fs_buffer *buff)
{
buff->refcount--;
}

View file

@ -1,6 +1,7 @@
#include <stdint.h>
#include <unistd.h>
#include <stupidfs.h>
#include <stdio.h>
size_t
fs_bio_raw_write(int fd, uint32_t blocknum, void *data, size_t size)

View file

@ -32,3 +32,40 @@ fs_dir_lookup(struct fs_inode *dp, const char *name, size_t *offset)
return (NULL);
}
int
fs_dir_link(struct fs_inode *dp, const char *name, uint32_t inum)
{
int offset;
struct fs_inode *ip;
struct stpdfs_dirent dirent;
ip = fs_dir_lookup(dp, name, 0);
if (ip != NULL)
{
fs_inode_release(ip);
return (-EEXIST);
}
for (offset = 0; offset < dp->inode.size; offset += STPDFS_DIRENT_SIZE)
{
fs_read(dp, (uint8_t *)&dirent, offset, STPDFS_DIRENT_SIZE);
if (dirent.inode == 0)
{
break;
}
}
memset(dirent.filename, 0, STPDFS_NAME_MAX);
strncpy(dirent.filename, name, STPDFS_NAME_MAX);
dirent.inode = inum;
if (fs_write(dp, (uint8_t *)&dirent, offset, STPDFS_DIRENT_SIZE) != STPDFS_DIRENT_SIZE)
{
return (-1);
}
fs_inode_update(dp);
return (0);
}

View file

@ -2,6 +2,7 @@
# define FS_DIR_H 1
# include <stupidfs.h>
# include "inode.h"
struct fs_dir {
char name[STPDFS_NAME_MAX];
@ -10,6 +11,6 @@ struct fs_dir {
};
int fs_dir_link(struct fs_inode *dp, const char *name, uint32_t inum);
#endif /* !FS_DIR_H */

View file

@ -4,10 +4,12 @@
# include <stdint.h>
# include "super.h"
# include "inode.h"
# include "dir.h"
uint32_t fs_balloc(struct fs_super *super);
int fs_bfree(struct fs_super *super, uint32_t blocknum);
int fs_read(struct fs_inode *ip, uint8_t *dest, size_t offset, size_t size);
int fs_write(struct fs_inode *ip, const uint8_t *src, size_t offset, size_t size);
#endif /* !FS_H */

View file

@ -1,3 +1,4 @@
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include "inode.h"
@ -8,6 +9,32 @@
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)
{
@ -26,7 +53,7 @@ fs_inode_get(struct fs_super *super, uint32_t inum)
if (ip == NULL) return (NULL);
ip->super = super;
ip->inum = 0;
ip->inum = inum;
ip->refcount = 1;
ip->valid = 0;
@ -44,7 +71,7 @@ fs_inode_read(struct fs_inode *ip)
buff = fs_bio_bread(ip->super->fd, IBLOCK(ip->inum));
if (buff == NULL) return (NULL);
dinode = (struct stpdfs_inode *)buff->data;
dinode = (struct stpdfs_inode *)buff->data + ip->inum % STPDFS_INODES_PER_BLOCK;;
memcpy(&ip->inode, dinode, sizeof(struct stpdfs_inode));
fs_bio_brelse(buff);
@ -98,3 +125,24 @@ fs_inode_release(struct fs_inode *ip)
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);
}

View file

@ -18,6 +18,7 @@ struct fs_inode {
struct fs_inode *fs_inode_get(struct fs_super *super, uint32_t inum);
int fs_inode_update(struct fs_inode *ip);
void fs_inode_release(struct fs_inode *ip);
struct fs_inode *fs_inode_read(struct fs_inode *ip);
#endif /* !FS_INODE_H */

View file

@ -11,21 +11,25 @@ fs_super_valide(struct stpdfs_sb *sb)
{
if (sb->magic != STPDFS_SB_MAGIC)
{
printf("bad magic\n");
return (-1);
}
if (sb->revision != STPDFS_SB_REV)
{
printf("bad rev\n");
return (-1);
}
if (sb->fsize == 0 || sb->isize == 0)
{
printf("size null\n");
return (-1);
}
if (sb->isize > sb->fsize)
{
printf("invalid size\n");
return (-1);
}
@ -37,7 +41,7 @@ fs_super_open(struct fs_super *super, const char *fname)
{
struct fs_buffer *buff;
super->fd = open(fname, O_RDWR);
super->fd = open(fname, O_RDWR | O_BINARY);
if (super->fd < 0)
{
perror(fname);
@ -48,6 +52,9 @@ fs_super_open(struct fs_super *super, const char *fname)
if (!buff) goto err;
memcpy(&super->sb, buff->data, sizeof(struct stpdfs_sb));
fs_bio_brelse(buff);
if (fs_super_valide(&super->sb) != 0) goto err;
return (0);
@ -63,6 +70,8 @@ fs_super_kill(struct fs_super *super)
struct fs_buffer *buff;
int ret;
super->sb.state = STPDFS_CLEANLY_UNMOUNTED;
ret = 0;
buff = fs_bio_bread(super->fd, STPDFS_SB_BLOCK);
if (buff == NULL)

View file

@ -9,4 +9,8 @@ struct fs_super {
struct stpdfs_sb sb;
};
int fs_super_kill(struct fs_super *super);
int fs_super_open(struct fs_super *super, const char *fname);
#endif /* !FS_SUPER_H */

View file

@ -39,7 +39,7 @@ stpdfs_super_open(struct stpdfs_super_info *sbi, const char *fname)
{
struct stpdfs_buffer *buff;
sbi->fd = open(fname, O_RDWR);
sbi->fd = open(fname, O_RDWR | O_BINARY);
if (sbi->fd < 0)
{
perror(fname);

View file

@ -1,13 +1,15 @@
AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/lib -I$(top_srcdir)
LDADD = ../libstpdfs/libstpdfs.a
LDADD = ../libstpdfs/libstpdfs.a ../libfs/libfs.a
bin_PROGRAMS = mkfs.stpd tools.stpd
bin_PROGRAMS = mkfs.stpd tools.stpd inspect.stpd
mkfs_stpd_SOURCES = mkfs/main.c
mkfs_stpd_LDADD = ../libstpdfs/libstpdfs.a mkfs/bootsector.o
mkfs_stpd_LDADD = ../libfs/libfs.a mkfs/bootsector.o
tools_stpd_SOURCES = tools/main.c tools/ls.c tools/copy.c
inspect_stpd_SOURCES = inspect/main.c
mkfs/boot.o: mkfs/boot.asm
$(NASM) -fbin -o $@ $<

164
tools/inspect/main.c Normal file
View file

@ -0,0 +1,164 @@
#include "libfs/inode.h"
#include "libfs/super.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#ifdef HAVE_LIBGEN_H
# include <libgen.h>
#endif /* HAVE_LIBGEN_H */
#ifdef HAVE_GETOPT_H
# include <getopt.h>
#endif /* HAVE_GETOPT_H */
#include <libfs/fs.h>
static const char *prg_name;
static const char *device;
static int inode = -1;
static int block = -1;
static int super = 0;
#ifdef HAVE_STRUCT_OPTION
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"inode", required_argument, 0, 'i'},
{"block", required_argument, 0, 'b'},
{"super", no_argument, 0, 's'},
{0, 0, 0, 0}
};
#endif /* HAVE_STRUCT_OPTION */
static int
inspect(void)
{
struct fs_super sb;
struct fs_inode *ip;
time_t time;
int idx;
if (fs_super_open(&sb, device) != 0)
{
fprintf(stderr, "Bad super\n");
return (EXIT_FAILURE);
}
if (super)
{
printf("Super:\n");
printf(" magic: %x\n", sb.sb.magic);
printf(" isize: %u\n", sb.sb.isize);
printf(" fsize: %u\n", sb.sb.fsize);
printf(" freelist:\n");
for (idx = 0; idx < sb.sb.freelist.nfree; idx++)
{
printf("\tblock[%02u]: %x\n", idx, sb.sb.freelist.free[idx]);
}
printf(" revision: %u\n", sb.sb.revision);
printf(" state: %hu\n", sb.sb.state);
time = sb.sb.time;
printf(" time: %s", ctime(&time));
}
if (inode > 0)
{
ip = fs_inode_get(&sb, inode);
if (ip->valid == 0)
{
fs_inode_read(ip);
}
printf("Inode %d:\n", inode);
printf(" mode: %ho\n", ip->inode.mode);
printf(" nlink: %hu\n", ip->inode.nlink);
printf(" size: %u\n", ip->inode.size);
time = ip->inode.actime;
printf(" actime: %s", ctime(&time));
time = ip->inode.modtime;
printf(" modtime: %s", ctime(&time));
}
fs_super_kill(&sb);
return (EXIT_SUCCESS);
}
static void
usage(int retval)
{
if (retval == EXIT_FAILURE)
{
fprintf(stderr, "Try '%s -h' for more information.\n", prg_name);
}
else
{
printf("Usage %s: [options] /dev/name\n\n", prg_name);
}
exit(retval);
}
static void
version(void)
{
printf("%s (%s) %s\n", prg_name, PACKAGE_NAME, PACKAGE_VERSION);
exit(EXIT_SUCCESS);
}
int
main(int argc, char **argv)
{
int idx;
int c;
#ifdef HAVE_LIBGEN_H
prg_name = basename(argv[0]);
#else
prg_name = argv[0];
#endif /* HAVE_LIBGEN_H */
#if defined(HAVE_GETOPT_LONG) && defined(HAVE_STRUCT_OPTION)
while ((c = getopt_long(argc, argv, "hVi:b:s", long_options, &idx)) != EOF)
#else
while ((c = getopt(argc, argv, "hVi:b:s")) != EOF)
#endif /* HAVE_GETOPT_LONG && HAVE_STRUCT_OPTION */
{
switch (c)
{
case 'h':
usage(EXIT_SUCCESS);
break;
case 'V':
version();
break;
case 'i':
inode = atoi(optarg);
break;
case 'b':
block = atoi(optarg);
break;
case 's':
super = 1;
break;
default:
usage(EXIT_FAILURE);
}
}
if (optind >= argc)
{
usage(EXIT_FAILURE);
}
device = argv[optind];
return (inspect());
}

View file

@ -1,3 +1,7 @@
#include "libfs/bio/bio.h"
#include "libfs/inode.h"
#include "libfs/super.h"
#include "stupidfs.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -7,7 +11,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <libstpdfs/stpdfs.h>
#include <libfs/fs.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
@ -23,7 +27,6 @@ static int inodes = -1;
static const char *device;
static int blocks = -1;
static int bootable = 0;
static struct stpdfs_sb super;
extern const char _binary_mkfs_boot_o_start[];
extern const char _binary_mkfs_boot_o_end[];
@ -66,103 +69,26 @@ version(void)
exit(EXIT_SUCCESS);
}
uint32_t
alloc_block(int fd, struct stpdfs_sb *sb)
static int
create_create_super(struct fs_super *super)
{
uint32_t blocknum;
struct stpdfs_free freelist;
struct stat st;
int dev_block;
sb->state = STPDFS_DIRTY; /* mark state dirty */
redo:
sb->freelist.nfree--;
blocknum = sb->freelist.free[sb->freelist.nfree];
if (sb->freelist.nfree == 0 && blocknum != 0)
{
stpdfs_read(fd, blocknum, &freelist, sizeof(struct stpdfs_free));
memcpy(sb->freelist.free, &freelist, sizeof(uint32_t) * 100);
sb->freelist.nfree = freelist.nfree;
goto redo;
}
sb->time = time(NULL);
return (blocknum);
}
int
free_block(int fd, struct stpdfs_sb *sb, uint32_t blocknum)
{
struct stpdfs_free copy;
if (blocknum == 0 || blocknum >= sb->fsize)
if (stat(device, &st) < 0)
{
perror(device);
return (-1);
}
sb->state = STPDFS_DIRTY; /* mark state dirty */
if (sb->freelist.nfree == 100)
{
memcpy(&copy, sb->freelist.free, sizeof(uint32_t) * 100);
copy.nfree = sb->freelist.nfree;
stpdfs_write(fd, blocknum, &copy, sizeof(struct stpdfs_free));
sb->freelist.nfree = 1;
sb->freelist.free[0] = blocknum;
}
else
{
sb->freelist.free[sb->freelist.nfree++] = blocknum;
}
sb->time = time(NULL);
return (0);
}
static int
write_block(int fd, void *data, size_t size)
{
uint8_t buffer[STPDFS_BLOCK_SIZE];
memset(buffer, 0, STPDFS_BLOCK_SIZE);
if (data)
{
memcpy(buffer, data, size);
}
return (write(fd, buffer, STPDFS_BLOCK_SIZE) == STPDFS_BLOCK_SIZE);
}
static int
mkfs()
{
struct stat statbuf;
struct stpdfs_dirent rootdirent[2];
int fd;
int dev_block;
int idx;
struct stpdfs_inode inds[STPDFS_INODES_PER_BLOCK];
struct stpdfs_free freebuff;
int freeblock;
int nextfree;
if (stat(device, &statbuf) < 0)
super->fd = open(device, O_RDWR | O_BINARY);
if (super->fd < 0)
{
perror(device);
return (EXIT_FAILURE);
return (-1);
}
fd = open(device, O_RDWR);
if (fd < 0)
{
perror(device);
return (EXIT_FAILURE);
}
dev_block = statbuf.st_size / STPDFS_BLOCK_SIZE;
printf("device blocks: %d\n", dev_block);
dev_block = st.st_size / STPDFS_BLOCK_SIZE;
if (blocks < 0)
{
blocks = dev_block;
@ -180,62 +106,84 @@ mkfs()
}
}
super.magic = STPDFS_SB_MAGIC;
super.revision = STPDFS_SB_REV;
super.isize = inodes / STPDFS_INODES_PER_BLOCK;
super.fsize = blocks;
super.freelist.nfree = 0;
super->sb.magic = STPDFS_SB_MAGIC;
super->sb.revision = STPDFS_SB_REV;
super->sb.isize = inodes / STPDFS_INODES_PER_BLOCK;
super->sb.fsize = blocks;
super->sb.freelist.nfree = 0;
return (0);
}
static int
mkfs()
{
uint32_t idx;
struct fs_super super;
struct stpdfs_inode dinodes[STPDFS_INODES_PER_BLOCK];
struct fs_inode *rootip;
if (create_create_super(&super) != 0)
{
return (EXIT_FAILURE);
}
/* write inodes */
lseek(fd, 2 * STPDFS_BLOCK_SIZE, SEEK_SET);
memset(&inds, 0, sizeof(struct stpdfs_inode) * STPDFS_INODES_PER_BLOCK);
for (idx = 0; idx < super.isize; idx++)
memset(dinodes, 0, sizeof(struct stpdfs_inode) * STPDFS_INODES_PER_BLOCK);
for (idx = 2; idx < (super.sb.isize + 2); idx++)
{
if (write_block(fd, &inds, sizeof(struct stpdfs_inode) * STPDFS_INODES_PER_BLOCK));
if (fs_bio_raw_write(super.fd, idx, dinodes, sizeof(struct stpdfs_inode) * STPDFS_INODES_PER_BLOCK) != sizeof(struct stpdfs_inode) * STPDFS_INODES_PER_BLOCK)
{
fprintf(stderr, "wtf?:");
}
}
/* set free blocks */
freeblock = blocks - (inodes + 2);
for (nextfree = super.isize + 3; nextfree < freeblock; nextfree++)
for (idx = super.sb.isize + 3; idx < blocks; idx++)
{
if (free_block(fd, &super, nextfree) != 0)
if (fs_bfree(&super, idx) != 0)
{
fprintf(stderr, "error: %u\n", nextfree);
fprintf(stderr, "error: %u\n", idx);
}
}
/* create root dir */
stpdfs_read(fd, 2, &inds, sizeof(struct stpdfs_inode) * STPDFS_INODES_PER_BLOCK);
inds[STPDFS_ROOTINO].modtime = time(NULL);
inds[STPDFS_ROOTINO].actime = time(NULL);
inds[STPDFS_ROOTINO].size = sizeof(struct stpdfs_dirent) * 2;
inds[STPDFS_ROOTINO].flags = STPDFS_INO_FLAG_ALOC;
inds[STPDFS_ROOTINO].mode = STPDFS_S_IFDIR | STPDFS_S_IRUSR | STPDFS_S_IWUSR | STPDFS_S_IXUSR | STPDFS_S_IRGRP | STPDFS_S_IXGRP | STPDFS_S_IXOTH;
inds[STPDFS_ROOTINO].zones[0] = alloc_block(fd, &super);
inds[STPDFS_ROOTINO].size = sizeof(struct stpdfs_dirent) * 2;
stpdfs_read(fd, inds[STPDFS_ROOTINO].zones[0], rootdirent, sizeof(struct stpdfs_dirent) * 2);
strcpy(rootdirent[0].filename, ".");
rootdirent[1].inode = 1;
strcpy(rootdirent[1].filename, "..");
rootdirent[1].inode = 1;
inds[STPDFS_ROOTINO].nlink += 2;
stpdfs_write(fd, inds[STPDFS_ROOTINO].zones[0], rootdirent, sizeof(struct stpdfs_dirent) * 2);
stpdfs_write(fd, 2, &inds, sizeof(struct stpdfs_inode) * STPDFS_INODES_PER_BLOCK);
rootip = fs_inode_get(&super, STPDFS_ROOTINO);
if (rootip == NULL)
{
return (EXIT_FAILURE);
}
/* write super block */
super.time = time(NULL);
super.state = STPDFS_CLEANLY_UNMOUNTED;
stpdfs_write(fd, 1, &super, sizeof(struct stpdfs_sb));
rootip->valid = 1;
rootip->inode.modtime = time(NULL);
rootip->inode.actime = time(NULL);
memset(rootip->inode.zones, 0, sizeof(uint32_t) * 10);
rootip->inode.size = 0;
rootip->inode.flags = STPDFS_INO_FLAG_ALOC;
rootip->inode.mode = STPDFS_S_IFDIR | STPDFS_S_IRUSR | STPDFS_S_IWUSR | STPDFS_S_IXUSR | STPDFS_S_IRGRP | STPDFS_S_IXGRP | STPDFS_S_IXOTH;
fs_inode_update(rootip);
if (fs_dir_link(rootip, ".", rootip->inum) != 0)
{
printf("WTF?");
}
fs_dir_link(rootip, "..", rootip->inum);
rootip->inode.nlink = 2;
fs_inode_update(rootip);
fs_inode_release(rootip);
if (bootable)
{
stpdfs_write(fd, 0, (void *)_binary_mkfs_boot_o_start, STPDFS_BLOCK_SIZE);
fs_bio_raw_write(super.fd, 0, (void *)_binary_mkfs_boot_o_start, STPDFS_BLOCK_SIZE);
}
/* we finished \o/ */
printf("StupidFS: %u blocks (%u Inodes)\n", super.fsize, super.isize);
fs_super_kill(&super);
close(fd);
/* we finished \o/ */
printf("StupidFS: %u blocks (%u Inodes)\n", super.sb.fsize, super.sb.isize);
return (EXIT_SUCCESS);
}

View file

@ -1,4 +1,7 @@
#include "libfs/fs.h"
#include "libfs/inode.h"
#include "libfs/super.h"
#include "stupidfs.h"
#include <stdio.h>
#include <stdlib.h>
@ -44,25 +47,30 @@ usage(int retval)
static int
do_ls(void)
{
struct stpdfs_super_info sbi;
struct stpdfs_inode_info *ip;
struct fs_super super;
struct fs_inode *ip;
struct stpdfs_dirent dirent;
size_t idx;
if (stpdfs_super_open(&sbi, image))
if (fs_super_open(&super, image))
{
return (EXIT_FAILURE);
}
ip = stpdfs_inode_get(&sbi, STPDFS_ROOTINO);
ip = fs_inode_get(&super, STPDFS_ROOTINO);
if (ip->valid == 0)
{
fs_inode_read(ip);
}
for (idx = 0; idx < ip->inode.size; idx += STPDFS_DIRENT_SIZE)
{
stpdfs_inode_read(ip, (uint8_t *)&dirent, idx, STPDFS_DIRENT_SIZE);
fs_read(ip, (uint8_t *)&dirent, idx, STPDFS_DIRENT_SIZE);
printf("%s\n", dirent.filename);
}
stpdfs_super_kill(&sbi);
fs_super_kill(&super);
return (EXIT_SUCCESS);
}