xv6-cs450/mkfs.c

287 lines
5.4 KiB
C
Raw Normal View History

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
2006-07-27 23:10:00 +02:00
#include <assert.h>
#include "types.h"
#include "fs.h"
#include "stat.h"
2007-08-24 16:56:17 +02:00
int nblocks = 995;
int ninodes = 200;
2006-08-09 03:09:36 +02:00
int size = 1024;
2006-07-27 23:10:00 +02:00
int fsfd;
struct superblock sb;
char zeroes[512];
uint freeblock;
2006-08-09 03:09:36 +02:00
uint usedblocks;
uint bitblocks;
2006-07-27 23:10:00 +02:00
uint freeinode = 1;
2006-08-09 03:09:36 +02:00
void balloc(int);
2006-09-06 19:27:19 +02:00
void wsect(uint, void*);
void winode(uint, struct dinode*);
void rinode(uint inum, struct dinode *ip);
void rsect(uint sec, void *buf);
2006-07-27 23:10:00 +02:00
uint ialloc(ushort type);
void iappend(uint inum, void *p, int n);
// convert to intel byte order
ushort
xshort(ushort x)
{
ushort y;
2006-09-06 19:27:19 +02:00
uchar *a = (uchar*) &y;
a[0] = x;
a[1] = x >> 8;
return y;
}
uint
xint(uint x)
{
uint y;
2006-09-06 19:27:19 +02:00
uchar *a = (uchar*) &y;
a[0] = x;
a[1] = x >> 8;
a[2] = x >> 16;
a[3] = x >> 24;
return y;
}
2006-09-07 15:07:39 +02:00
int
main(int argc, char *argv[])
{
2006-07-27 23:10:00 +02:00
int i, cc, fd;
2007-08-28 01:26:33 +02:00
uint rootino, inum, off;
2006-07-27 23:10:00 +02:00
struct dirent de;
char buf[512];
struct dinode din;
2006-07-27 23:10:00 +02:00
if(argc < 2){
fprintf(stderr, "Usage: mkfs fs.img files...\n");
exit(1);
}
2006-07-27 23:10:00 +02:00
assert((512 % sizeof(struct dinode)) == 0);
assert((512 % sizeof(struct dirent)) == 0);
2006-07-27 23:10:00 +02:00
fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
if(fsfd < 0){
perror(argv[1]);
exit(1);
}
2006-08-09 03:09:36 +02:00
sb.size = xint(size);
sb.nblocks = xint(nblocks); // so whole disk is size sectors
sb.ninodes = xint(ninodes);
2006-09-06 19:27:19 +02:00
bitblocks = size/(512*8) + 1;
2006-08-09 03:09:36 +02:00
usedblocks = ninodes / IPB + 3 + bitblocks;
freeblock = usedblocks;
printf("used %d (bit %d ninode %zu) free %u total %d\n", usedblocks,
bitblocks, ninodes/IPB + 1, freeblock, nblocks+usedblocks);
2006-08-09 03:09:36 +02:00
2006-09-06 19:27:19 +02:00
assert(nblocks + usedblocks == size);
2006-08-09 03:09:36 +02:00
for(i = 0; i < nblocks + usedblocks; i++)
wsect(i, zeroes);
wsect(1, &sb);
2006-07-27 23:10:00 +02:00
rootino = ialloc(T_DIR);
2008-10-08 20:57:13 +02:00
assert(rootino == ROOTINO);
2006-07-27 23:10:00 +02:00
bzero(&de, sizeof(de));
de.inum = xshort(rootino);
strcpy(de.name, ".");
iappend(rootino, &de, sizeof(de));
bzero(&de, sizeof(de));
de.inum = xshort(rootino);
strcpy(de.name, "..");
iappend(rootino, &de, sizeof(de));
for(i = 2; i < argc; i++){
assert(index(argv[i], '/') == 0);
2006-07-27 23:10:00 +02:00
if((fd = open(argv[i], 0)) < 0){
perror(argv[i]);
exit(1);
}
2006-09-07 15:07:39 +02:00
// Skip leading _ in name when writing to file system.
// The binaries are named _rm, _cat, etc. to keep the
// build operating system from trying to execute them
// in place of system binaries like rm and cat.
if(argv[i][0] == '_')
++argv[i];
2006-07-27 23:10:00 +02:00
inum = ialloc(T_FILE);
bzero(&de, sizeof(de));
de.inum = xshort(inum);
strncpy(de.name, argv[i], DIRSIZ);
iappend(rootino, &de, sizeof(de));
2006-09-06 19:27:19 +02:00
2006-07-27 23:10:00 +02:00
while((cc = read(fd, buf, sizeof(buf))) > 0)
iappend(inum, buf, cc);
close(fd);
}
// fix size of root inode dir
rinode(rootino, &din);
2006-09-06 19:27:19 +02:00
off = xint(din.size);
off = ((off/BSIZE) + 1) * BSIZE;
din.size = xint(off);
winode(rootino, &din);
2006-08-09 03:09:36 +02:00
balloc(usedblocks);
exit(0);
}
void
wsect(uint sec, void *buf)
{
2006-07-27 23:10:00 +02:00
if(lseek(fsfd, sec * 512L, 0) != sec * 512L){
perror("lseek");
exit(1);
}
2006-07-27 23:10:00 +02:00
if(write(fsfd, buf, 512) != 512){
perror("write");
exit(1);
}
}
uint
i2b(uint inum)
{
return (inum / IPB) + 2;
}
void
winode(uint inum, struct dinode *ip)
{
char buf[512];
uint bn;
struct dinode *dip;
bn = i2b(inum);
rsect(bn, buf);
2006-09-06 19:27:19 +02:00
dip = ((struct dinode*) buf) + (inum % IPB);
*dip = *ip;
wsect(bn, buf);
2006-07-27 23:10:00 +02:00
}
void
rinode(uint inum, struct dinode *ip)
{
char buf[512];
uint bn;
struct dinode *dip;
bn = i2b(inum);
rsect(bn, buf);
2006-09-06 19:27:19 +02:00
dip = ((struct dinode*) buf) + (inum % IPB);
2006-07-27 23:10:00 +02:00
*ip = *dip;
}
void
rsect(uint sec, void *buf)
{
2006-07-27 23:10:00 +02:00
if(lseek(fsfd, sec * 512L, 0) != sec * 512L){
perror("lseek");
exit(1);
}
2006-07-27 23:10:00 +02:00
if(read(fsfd, buf, 512) != 512){
perror("read");
exit(1);
}
}
2006-07-27 23:10:00 +02:00
uint
ialloc(ushort type)
{
uint inum = freeinode++;
struct dinode din;
bzero(&din, sizeof(din));
din.type = xshort(type);
din.nlink = xshort(1);
din.size = xint(0);
winode(inum, &din);
return inum;
}
2006-08-09 03:09:36 +02:00
void
balloc(int used)
{
uchar buf[512];
int i;
printf("balloc: first %d blocks have been allocated\n", used);
2006-09-06 19:27:19 +02:00
assert(used < 512);
2006-08-09 03:09:36 +02:00
bzero(buf, 512);
2006-09-06 19:27:19 +02:00
for(i = 0; i < used; i++) {
2006-08-09 03:09:36 +02:00
buf[i/8] = buf[i/8] | (0x1 << (i%8));
}
printf("balloc: write bitmap block at sector %zu\n", ninodes/IPB + 3);
2006-08-09 03:09:36 +02:00
wsect(ninodes / IPB + 3, buf);
}
2006-07-27 23:10:00 +02:00
#define min(a, b) ((a) < (b) ? (a) : (b))
void
iappend(uint inum, void *xp, int n)
{
2006-09-06 19:27:19 +02:00
char *p = (char*) xp;
2006-07-27 23:10:00 +02:00
uint fbn, off, n1;
struct dinode din;
char buf[512];
uint indirect[NINDIRECT];
uint x;
2006-07-27 23:10:00 +02:00
rinode(inum, &din);
off = xint(din.size);
while(n > 0){
fbn = off / 512;
assert(fbn < MAXFILE);
2006-09-06 19:27:19 +02:00
if(fbn < NDIRECT) {
if(xint(din.addrs[fbn]) == 0) {
din.addrs[fbn] = xint(freeblock++);
usedblocks++;
}
x = xint(din.addrs[fbn]);
} else {
if(xint(din.addrs[NDIRECT]) == 0) {
2006-09-08 15:44:56 +02:00
// printf("allocate indirect block\n");
din.addrs[NDIRECT] = xint(freeblock++);
usedblocks++;
}
2006-09-08 15:44:56 +02:00
// printf("read indirect block\n");
rsect(xint(din.addrs[NDIRECT]), (char*) indirect);
2006-09-06 19:27:19 +02:00
if(indirect[fbn - NDIRECT] == 0) {
indirect[fbn - NDIRECT] = xint(freeblock++);
usedblocks++;
wsect(xint(din.addrs[NDIRECT]), (char*) indirect);
}
x = xint(indirect[fbn-NDIRECT]);
2006-08-09 03:09:36 +02:00
}
2006-07-27 23:10:00 +02:00
n1 = min(n, (fbn + 1) * 512 - off);
rsect(x, buf);
2006-07-27 23:10:00 +02:00
bcopy(p, buf + off - (fbn * 512), n1);
wsect(x, buf);
2006-07-27 23:10:00 +02:00
n -= n1;
off += n1;
p += n1;
}
din.size = xint(off);
winode(inum, &din);
}