refactor: rewrite mkfs.stpd
This commit is contained in:
parent
3f68ab8263
commit
43da2b6b53
37
libfs/dir.c
37
libfs/dir.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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);
|
||||
|
@ -97,4 +124,25 @@ 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);
|
||||
}
|
|
@ -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 */
|
|
@ -63,6 +63,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)
|
||||
|
|
|
@ -9,4 +9,7 @@ struct fs_super {
|
|||
struct stpdfs_sb sb;
|
||||
};
|
||||
|
||||
|
||||
int fs_super_kill(struct fs_super *super);
|
||||
|
||||
#endif /* !FS_SUPER_H */
|
|
@ -1,10 +1,10 @@
|
|||
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
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -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(©, sb->freelist.free, sizeof(uint32_t) * 100);
|
||||
copy.nfree = sb->freelist.nfree;
|
||||
|
||||
stpdfs_write(fd, blocknum, ©, 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);
|
||||
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,80 @@ 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));
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
rootip->valid = 1;
|
||||
|
||||
/* write super block */
|
||||
super.time = time(NULL);
|
||||
super.state = STPDFS_CLEANLY_UNMOUNTED;
|
||||
stpdfs_write(fd, 1, &super, sizeof(struct stpdfs_sb));
|
||||
rootip->inode.modtime = time(NULL);
|
||||
rootip->inode.actime = time(NULL);
|
||||
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);
|
||||
}
|
||||
|
|
293
tools/mkfs/main.old.c
Normal file
293
tools/mkfs/main.old.c
Normal file
|
@ -0,0 +1,293 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <libstpdfs/stpdfs.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 */
|
||||
|
||||
static const char *prg_name;
|
||||
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[];
|
||||
|
||||
#ifdef HAVE_STRUCT_OPTION
|
||||
static struct option long_options[] = {
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"version", no_argument, 0, 'V'},
|
||||
{"boot", no_argument, 0, 'b'},
|
||||
{"inodes", required_argument, 0, 'i'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
#endif /* HAVE_STRUCT_OPTION */
|
||||
|
||||
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 [blocks]\n\n", prg_name);
|
||||
printf("Options:\n");
|
||||
printf(" -b, --boot make filesystem bootable\n");
|
||||
printf(" -i, --inode <num> number of inodes for the filesystem\n");
|
||||
printf(" -h, --help display this help\n");
|
||||
printf(" -V, --version display version\n\n");
|
||||
|
||||
printf("For more details see mkfs.stpd(8).\n");
|
||||
}
|
||||
exit(retval);
|
||||
}
|
||||
|
||||
static void
|
||||
version(void)
|
||||
{
|
||||
printf("%s (%s) %s\n", prg_name, PACKAGE_NAME, PACKAGE_VERSION);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
alloc_block(int fd, struct stpdfs_sb *sb)
|
||||
{
|
||||
uint32_t blocknum;
|
||||
struct stpdfs_free freelist;
|
||||
|
||||
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)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
|
||||
sb->state = STPDFS_DIRTY; /* mark state dirty */
|
||||
|
||||
if (sb->freelist.nfree == 100)
|
||||
{
|
||||
memcpy(©, sb->freelist.free, sizeof(uint32_t) * 100);
|
||||
copy.nfree = sb->freelist.nfree;
|
||||
|
||||
stpdfs_write(fd, blocknum, ©, 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)
|
||||
{
|
||||
perror(device);
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
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);
|
||||
if (blocks < 0)
|
||||
{
|
||||
blocks = dev_block;
|
||||
}
|
||||
|
||||
if (inodes <= 0)
|
||||
{
|
||||
if (512 * 1024 < blocks)
|
||||
{
|
||||
inodes = blocks / 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
inodes = blocks / 3;
|
||||
}
|
||||
}
|
||||
|
||||
super.magic = STPDFS_SB_MAGIC;
|
||||
super.revision = STPDFS_SB_REV;
|
||||
super.isize = inodes / STPDFS_INODES_PER_BLOCK;
|
||||
super.fsize = blocks;
|
||||
super.freelist.nfree = 0;
|
||||
|
||||
/* 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++)
|
||||
{
|
||||
if (write_block(fd, &inds, sizeof(struct stpdfs_inode) * STPDFS_INODES_PER_BLOCK));
|
||||
}
|
||||
|
||||
/* set free blocks */
|
||||
freeblock = blocks - (inodes + 2);
|
||||
for (nextfree = super.isize + 3; nextfree < freeblock; nextfree++)
|
||||
{
|
||||
if (free_block(fd, &super, nextfree) != 0)
|
||||
{
|
||||
fprintf(stderr, "error: %u\n", nextfree);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
/* write super block */
|
||||
super.time = time(NULL);
|
||||
super.state = STPDFS_CLEANLY_UNMOUNTED;
|
||||
stpdfs_write(fd, 1, &super, sizeof(struct stpdfs_sb));
|
||||
|
||||
if (bootable)
|
||||
{
|
||||
stpdfs_write(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);
|
||||
|
||||
close(fd);
|
||||
|
||||
return (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, "hVbi:", long_options, &idx)) != EOF)
|
||||
#else
|
||||
while ((c = getopt(argc, argv, "hVbi:")) != EOF)
|
||||
#endif /* HAVE_GETOPT_LONG && HAVE_STRUCT_OPTION */
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'h':
|
||||
usage(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'V':
|
||||
version();
|
||||
break;
|
||||
case 'b':
|
||||
bootable = 1;
|
||||
break;
|
||||
case 'i':
|
||||
inodes = atoi(optarg);
|
||||
break;
|
||||
default:
|
||||
usage(EXIT_FAILURE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind >= argc)
|
||||
{
|
||||
usage(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
device = argv[optind++];
|
||||
if (optind < argc)
|
||||
{
|
||||
blocks = atoi(argv[optind]);
|
||||
}
|
||||
|
||||
return (mkfs());
|
||||
}
|
Loading…
Reference in a new issue