OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [tags/] [eco32-0.22/] [disk/] [tools/] [fs-EOS32/] [mkfs/] [mkfs.c] - Rev 21

Compare with Previous | Blame | View Log

/*
 * mkfs.c -- make an EOS32 file system
 */
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
 
 
/**************************************************************/
 
 
#define SSIZE		512	/* disk sector size in bytes */
#define BSIZE		4096	/* disk block size in bytes */
#define SPB		(BSIZE / SSIZE)	/* sectors per block */
#define AFS		(3 * BSIZE / 2)	/* average file size */
 
#define NICINOD		500	/* number of inodes in superblock */
#define NICFREE		500	/* number of free blocks in superblock */
#define NADDR		8	/* number of block addresses in inode */
#define NDADDR		6	/* number of direct block addresses */
#define SINGLE_INDIR	(NDADDR + 0)	/* index of single indirect block */
#define DOUBLE_INDIR	(NDADDR + 1)	/* index of double indirect block */
#define DIRSIZ		60	/* max length of a path name component */
 
#define NIPB		(BSIZE / sizeof(Dinode))
#define NDIRENT		(BSIZE / sizeof(Dirent))
#define NINDIR		(BSIZE / sizeof(EOS32_daddr_t))
 
#define SUPER_MAGIC	0x44FCB67D
 
#define IFMT		070000	/* type of file */
#define   IFREG		040000	/* regular file */
#define   IFDIR		030000	/* directory */
#define   IFCHR		020000	/* character special */
#define   IFBLK		010000	/* block special */
#define   IFFREE	000000	/* reserved (indicates free inode) */
#define ISUID		004000	/* set user id on execution */
#define ISGID		002000	/* set group id on execution */
#define ISVTX		001000	/* save swapped text even after use */
#define IUREAD		000400	/* user's read permission */
#define IUWRITE		000200	/* user's write permission */
#define IUEXEC		000100	/* user's execute permission */
#define IGREAD		000040	/* group's read permission */
#define IGWRITE		000020	/* group's write permission */
#define IGEXEC		000010	/* group's execute permission */
#define IOREAD		000004	/* other's read permission */
#define IOWRITE		000002	/* other's write permission */
#define IOEXEC		000001	/* other's execute permission */
 
/*
 * The following two macros convert an inode number to the disk
 * block containing the inode and an inode number within the block.
 */
#define itod(i)		(2 + (i) / NIPB)
#define itoo(i)		((i) % NIPB)
 
#define TYPE_COPY	0
#define TYPE_INODE	1
#define TYPE_FREE	2
#define TYPE_SUPER	3
#define TYPE_INDIRECT	4
#define TYPE_DIRECTORY	5
 
 
/**************************************************************/
 
 
/* EOS32 types */
 
typedef unsigned long EOS32_ino_t;
typedef unsigned long EOS32_daddr_t;
typedef unsigned long EOS32_off_t;
typedef long EOS32_time_t;
 
 
/* super block */
 
typedef struct {
  unsigned int s_magic;			/* must be SUPER_MAGIC */
  EOS32_daddr_t s_fsize;		/* size of file system in blocks */
  EOS32_daddr_t s_isize;		/* size of inode list in blocks */
  EOS32_daddr_t s_freeblks;		/* number of free blocks */
  EOS32_ino_t s_freeinos;		/* number of free inodes */
  unsigned int s_ninode;		/* number of inodes in s_inode */
  EOS32_ino_t s_inode[NICINOD];		/* free inode list */
  unsigned int s_nfree;			/* number of addresses in s_free */
  EOS32_daddr_t s_free[NICFREE];	/* free block list */
  EOS32_time_t s_time;			/* last super block update */
  char s_flock;				/* lock for free list manipulation */
  char s_ilock;				/* lock for i-list manipulation */
  char s_fmod;				/* super block modified flag */
  char s_ronly;				/* mounted read-only flag */
  char s_pad[BSIZE - 4036];		/* pad to block size */
} Filsys;
 
 
/* inode on disk */
 
typedef struct {
  unsigned int di_mode;			/* type and mode of file */
  unsigned int di_nlink;		/* number of links to file */
  unsigned int di_uid;			/* owner's user id */
  unsigned int di_gid;			/* owner's group id */
  EOS32_time_t di_ctime;		/* time created */
  EOS32_time_t di_mtime;		/* time last modified */
  EOS32_time_t di_atime;		/* time last accessed */
  EOS32_off_t di_size;			/* number of bytes in file */
  EOS32_daddr_t di_addr[NADDR];		/* block addresses */
} Dinode;
 
 
/* inode in memory */
 
typedef struct {
  EOS32_ino_t i_number;			/* inode number */
  unsigned int i_mode;			/* type and mode of file */
  unsigned int i_nlink;			/* number of links to file */
  unsigned int i_uid;			/* owner's user id */
  unsigned int i_gid;			/* owner's group id */
  EOS32_off_t i_size;			/* number of bytes in file */
  EOS32_daddr_t i_addr[NADDR];		/* block addresses */
} Inode;
 
 
/* directory entry */
 
typedef struct {
  EOS32_ino_t d_ino;			/* directory inode */
  char d_name[DIRSIZ];			/* directory name */
} Dirent;
 
 
/* free block */
 
typedef struct {
  unsigned int df_nfree;		/* number of valid block addresses */
  EOS32_daddr_t df_free[NICFREE];	/* addresses of free blocks */
  char df_pad[BSIZE - 2004];		/* pad to block size */
} Fblk;
 
 
/**************************************************************/
 
 
time_t now;		/* timestamp used throughout the file system */
FILE *fs;		/* the file which holds the disk image */
Filsys filsys;		/* the file system's super block */
EOS32_ino_t lastIno;	/* last inode allocated */
 
 
/**************************************************************/
 
 
void error(char *fmt, ...) {
  va_list ap;
 
  va_start(ap, fmt);
  printf("Error: ");
  vprintf(fmt, ap);
  printf("\n");
  va_end(ap);
  exit(1);
}
 
 
/**************************************************************/
 
 
unsigned int read4FromEco(unsigned char *p) {
  return (unsigned int) p[0] << 24 |
         (unsigned int) p[1] << 16 |
         (unsigned int) p[2] <<  8 |
         (unsigned int) p[3] <<  0;
}
 
 
void write4ToEco(unsigned char *p, unsigned int data) {
  p[0] = data >> 24;
  p[1] = data >> 16;
  p[2] = data >>  8;
  p[3] = data >>  0;
}
 
 
void conv4FromEcoToX86(unsigned char *p) {
  unsigned int data;
 
  data = read4FromEco(p);
  * (unsigned int *) p = data;
}
 
 
void conv4FromX86ToEco(unsigned char *p) {
  unsigned int data;
 
  data = * (unsigned int *) p;
  write4ToEco(p, data);
}
 
 
/**************************************************************/
 
 
void superFromEcoToX86(unsigned char *p) {
  int i;
 
  /* magic */
  conv4FromEcoToX86(p);
  p += 4;
  /* fsize */
  conv4FromEcoToX86(p);
  p += 4;
  /* isize */
  conv4FromEcoToX86(p);
  p += 4;
  /* freeblks */
  conv4FromEcoToX86(p);
  p += 4;
  /* freeinos */
  conv4FromEcoToX86(p);
  p += 4;
  /* ninode */
  conv4FromEcoToX86(p);
  p += 4;
  /* inode */
  for (i = 0; i < NICINOD; i++) {
    conv4FromEcoToX86(p);
    p += 4;
  }
  /* nfree */
  conv4FromEcoToX86(p);
  p += 4;
  /* free */
  for (i = 0; i < NICFREE; i++) {
    conv4FromEcoToX86(p);
    p += 4;
  }
  /* time */
  conv4FromEcoToX86(p);
  p += 4;
  /* flock */
  p += 1;
  /* ilock */
  p += 1;
  /* fmod */
  p += 1;
  /* ronly */
  p += 1;
}
 
 
void superFromX86ToEco(unsigned char *p) {
  int i;
 
  /* magic */
  conv4FromX86ToEco(p);
  p += 4;
  /* fsize */
  conv4FromX86ToEco(p);
  p += 4;
  /* isize */
  conv4FromX86ToEco(p);
  p += 4;
  /* freeblks */
  conv4FromX86ToEco(p);
  p += 4;
  /* freeinos */
  conv4FromX86ToEco(p);
  p += 4;
  /* ninode */
  conv4FromX86ToEco(p);
  p += 4;
  /* inode */
  for (i = 0; i < NICINOD; i++) {
    conv4FromX86ToEco(p);
    p += 4;
  }
  /* nfree */
  conv4FromX86ToEco(p);
  p += 4;
  /* free */
  for (i = 0; i < NICFREE; i++) {
    conv4FromX86ToEco(p);
    p += 4;
  }
  /* time */
  conv4FromX86ToEco(p);
  p += 4;
  /* flock */
  p += 1;
  /* ilock */
  p += 1;
  /* fmod */
  p += 1;
  /* ronly */
  p += 1;
}
 
 
void inodeFromEcoToX86(unsigned char *p) {
  int i, j;
 
  for (i = 0; i < NIPB; i++) {
    /* mode */
    conv4FromEcoToX86(p);
    p += 4;
    /* nlink */
    conv4FromEcoToX86(p);
    p += 4;
    /* uid */
    conv4FromEcoToX86(p);
    p += 4;
    /* gid */
    conv4FromEcoToX86(p);
    p += 4;
    /* ctime */
    conv4FromEcoToX86(p);
    p += 4;
    /* mtime */
    conv4FromEcoToX86(p);
    p += 4;
    /* atime */
    conv4FromEcoToX86(p);
    p += 4;
    /* size */
    conv4FromEcoToX86(p);
    p += 4;
    /* addr */
    for (j = 0; j < NADDR; j++) {
      conv4FromEcoToX86(p);
      p += 4;
    }
  }
}
 
 
void inodeFromX86ToEco(unsigned char *p) {
  int i, j;
 
  for (i = 0; i < NIPB; i++) {
    /* mode */
    conv4FromX86ToEco(p);
    p += 4;
    /* nlink */
    conv4FromX86ToEco(p);
    p += 4;
    /* uid */
    conv4FromX86ToEco(p);
    p += 4;
    /* gid */
    conv4FromX86ToEco(p);
    p += 4;
    /* ctime */
    conv4FromX86ToEco(p);
    p += 4;
    /* mtime */
    conv4FromX86ToEco(p);
    p += 4;
    /* atime */
    conv4FromX86ToEco(p);
    p += 4;
    /* size */
    conv4FromX86ToEco(p);
    p += 4;
    /* addr */
    for (j = 0; j < NADDR; j++) {
      conv4FromX86ToEco(p);
      p += 4;
    }
  }
}
 
 
void freeFromEcoToX86(unsigned char *p) {
  int i;
 
  /* nfree */
  conv4FromEcoToX86(p);
  p += 4;
  /* free */
  for (i = 0; i < NICFREE; i++) {
    conv4FromEcoToX86(p);
    p += 4;
  }
}
 
 
void freeFromX86ToEco(unsigned char *p) {
  int i;
 
  /* nfree */
  conv4FromX86ToEco(p);
  p += 4;
  /* free */
  for (i = 0; i < NICFREE; i++) {
    conv4FromX86ToEco(p);
    p += 4;
  }
}
 
 
void indirectFromEcoToX86(unsigned char *p) {
  int i;
 
  for (i = 0; i < NINDIR; i++) {
    conv4FromEcoToX86(p);
    p += 4;
  }
}
 
 
void indirectFromX86ToEco(unsigned char *p) {
  int i;
 
  for (i = 0; i < NINDIR; i++) {
    conv4FromX86ToEco(p);
    p += 4;
  }
}
 
 
void directoryFromEcoToX86(unsigned char *p) {
  int i;
 
  for (i = 0; i < NDIRENT; i++) {
    conv4FromEcoToX86(p);
    p += 4;
    p += DIRSIZ;
  }
}
 
 
void directoryFromX86ToEco(unsigned char *p) {
  int i;
 
  for (i = 0; i < NDIRENT; i++) {
    conv4FromX86ToEco(p);
    p += 4;
    p += DIRSIZ;
  }
}
 
 
/**************************************************************/
 
 
unsigned long fsStart;		/* file system start sector */
 
 
void rdfs(EOS32_daddr_t bno, unsigned char *bf, int blkType) {
  int n;
 
  fseek(fs, fsStart * SSIZE + bno * BSIZE, SEEK_SET);
  n = fread(bf, 1, BSIZE, fs);
  if (n != BSIZE) {
    printf("read error: %ld\n", bno);
    exit(1);
  }
  switch (blkType) {
    case TYPE_COPY:
      /* nothing to do here */
      break;
    case TYPE_INODE:
      inodeFromEcoToX86(bf);
      break;
    case TYPE_FREE:
      freeFromEcoToX86(bf);
      break;
    case TYPE_SUPER:
      superFromEcoToX86(bf);
      break;
    case TYPE_INDIRECT:
      indirectFromEcoToX86(bf);
      break;
    case TYPE_DIRECTORY:
      directoryFromEcoToX86(bf);
      break;
    default:
      error("illegal block type %d in rdfs()", blkType);
      break;
  }
}
 
 
void wtfs(EOS32_daddr_t bno, unsigned char *bf, int blkType) {
  int n;
 
  switch (blkType) {
    case TYPE_COPY:
      /* nothing to do here */
      break;
    case TYPE_INODE:
      inodeFromX86ToEco(bf);
      break;
    case TYPE_FREE:
      freeFromX86ToEco(bf);
      break;
    case TYPE_SUPER:
      superFromX86ToEco(bf);
      break;
    case TYPE_INDIRECT:
      indirectFromX86ToEco(bf);
      break;
    case TYPE_DIRECTORY:
      directoryFromX86ToEco(bf);
      break;
    default:
      error("illegal block type %d in wtfs()", blkType);
      break;
  }
  fseek(fs, fsStart * SSIZE + bno * BSIZE, SEEK_SET);
  n = fwrite(bf, 1, BSIZE, fs);
  if(n != BSIZE) {
    printf("write error: %ld\n", bno);
    exit(1);
  }
  switch (blkType) {
    case TYPE_COPY:
      /* nothing to do here */
      break;
    case TYPE_INODE:
      inodeFromEcoToX86(bf);
      break;
    case TYPE_FREE:
      freeFromEcoToX86(bf);
      break;
    case TYPE_SUPER:
      superFromEcoToX86(bf);
      break;
    case TYPE_INDIRECT:
      indirectFromEcoToX86(bf);
      break;
    case TYPE_DIRECTORY:
      directoryFromEcoToX86(bf);
      break;
    default:
      error("illegal block type %d in wtfs()", blkType);
      break;
  }
}
 
 
/**************************************************************/
 
 
char *charp;
FILE *fin;
char string[100];
 
 
char getChar(void) {
  int c;
 
  if (charp != NULL) {
    /* take character from string */
    c = *charp;
    if (c != 0) {
      charp++;
    }
  } else {
    /* take character from prototype file */
    c = getc(fin);
    if (c == EOF) {
      c = 0;
    }
  }
  return c;
}
 
 
void getStr(void) {
  char c;
  int i;
 
  while (1) {
    c = getChar();
    if (c == ' ' || c == '\t' || c == '\n') {
      continue;
    }
    if (c == '\0') {
      error("unexpected EOF in prototype file");
    }
    if (c == '#') {
      do {
        c = getChar();
        if (c == '\0') {
          error("unexpected EOF in prototype file");
        }
      } while (c != '\n');
      continue;
    }
    break;
  }
  i = 0;
  do {
    string[i++] = c;
    c = getChar();
  } while (c != ' ' &&
           c != '\t' &&
           c != '\n' &&
           c != '\0');
  string[i] = '\0';
}
 
 
void badMode(char c) {
  error("%c/%s: bad mode", c, string);
}
 
 
int getMode(char c, char *s, int m0, int m1, int m2, int m3) {
  if (s[0] == 0) badMode(c);
  if (c == s[0]) return m0;
  if (s[1] == 0) badMode(c);
  if (c == s[1]) return m1;
  if (s[2] == 0) badMode(c);
  if (c == s[2]) return m2;
  if (s[3] == 0) badMode(c);
  if (c == s[3]) return m3;
  badMode(c);
  /* never reached */
  return 0;
}
 
 
long getNum(void) {
  int i, c;
  long n;
 
  getStr();
  n = 0;
  i = 0;
  for (i = 0; (c = string[i]) != '\0'; i++) {
    if (c < '0' || c > '9') {
      error("%s: bad number", string);
    }
    n = n * 10 + (c - '0');
  }
  return n;
}
 
 
/**************************************************************/
 
/* data block handling */
 
 
EOS32_daddr_t allocBlock(void) {
  EOS32_daddr_t bno;
  Fblk fbuf;
  int i;
 
  if (filsys.s_nfree <= 0) {
    error("this should never happen (filsys.s_nfree <= 0)");
  }
  bno = filsys.s_free[--filsys.s_nfree];
  if (bno == 0) {
    error("out of free disk blocks");
  }
  if (filsys.s_nfree == 0) {
    rdfs(bno, (unsigned char *) &fbuf, TYPE_FREE);
    filsys.s_nfree = fbuf.df_nfree;
    for (i = 0; i < NICFREE; i++) {
      filsys.s_free[i] = fbuf.df_free[i];
    }
  }
  filsys.s_freeblks--;
  return bno;
}
 
 
void freeBlock(EOS32_daddr_t bno) {
  Fblk fbuf;
  int i;
 
  if (filsys.s_nfree > NICFREE) {
    error("this should never happen (filsys.s_nfree > NICFREE)");
  }
  if (filsys.s_nfree == NICFREE) {
    memset(&fbuf, 0, sizeof(Fblk));
    fbuf.df_nfree = NICFREE;
    for (i = 0; i < NICFREE; i++) {
      fbuf.df_free[i] = filsys.s_free[i];
    }
    wtfs(bno, (unsigned char *) &fbuf, TYPE_FREE);
    filsys.s_nfree = 0;
  }
  filsys.s_free[filsys.s_nfree++] = bno;
  if (bno != 0) {
    /* note: block number 0 does not count as free block */
    filsys.s_freeblks++;
  }
}
 
 
void initFreeList(void) {
  EOS32_daddr_t bno;
 
  freeBlock(0);
  for (bno = filsys.s_fsize - 1; bno >= 2 + filsys.s_isize; bno--) {
    freeBlock(bno);
  }
}
 
 
/**************************************************************/
 
/* inode handling */
 
 
void iput(Inode *ip) {
  EOS32_daddr_t inodeBlock;
  Dinode *dp;
  unsigned char buf[BSIZE];
  int i;
 
  inodeBlock = itod(ip->i_number);
  if (inodeBlock >= 2 + filsys.s_isize) {
    error("too few inodes");
  }
  rdfs(inodeBlock, buf, TYPE_INODE);
  dp = (Dinode *) buf;
  dp += itoo(ip->i_number);
  dp->di_mode = ip->i_mode;
  dp->di_nlink = ip->i_nlink;
  dp->di_uid = ip->i_uid;
  dp->di_gid = ip->i_gid;
  dp->di_ctime = now;
  dp->di_mtime = now;
  dp->di_atime = now;
  dp->di_size = ip->i_size;
  for (i = 0; i < NADDR; i++) {
    dp->di_addr[i] = ip->i_addr[i];
  }
  wtfs(inodeBlock, buf, TYPE_INODE);
  filsys.s_freeinos--;
}
 
 
void initInodes(void) {
  int i;
  EOS32_daddr_t n;
  unsigned char buf[BSIZE];
  Inode in;
 
  /* init all inodes to free */
  for (i = 0; i < BSIZE; i++) {
    buf[i] = '\0';
  }
  for (n = 0; n < filsys.s_isize; n++) {
    wtfs(2 + n, buf, TYPE_INODE);
    filsys.s_freeinos += NIPB;
  }
  /* init inode 0 */
  lastIno = 0;
  in.i_number = lastIno;
  in.i_mode = IFREG;
  in.i_nlink = 0;
  in.i_uid = 0;
  in.i_gid = 0;
  in.i_size = 0;
  for (i = 0; i < NADDR; i++) {
    in.i_addr[i] = 0;
  }
  iput(&in);
}
 
 
void fillFreeInodeList(EOS32_ino_t numInodes) {
  int index;
  EOS32_ino_t ino;
  int i;
 
  /* fill the free inode list starting at the upper end */
  index = NICINOD;
  for (ino = lastIno + 1; ino < numInodes && index > 0; ino++) {
    filsys.s_inode[--index] = ino;
  }
  filsys.s_ninode = NICINOD - index;
  /* if the list is not completely filled, shift entries down */
  if (index > 0) {
    for (i = 0; i < filsys.s_ninode; i++) {
      filsys.s_inode[i] = filsys.s_inode[index++];
    }
  }
}
 
 
/**************************************************************/
 
 
void appendData(Inode *ip, int blkType, unsigned char *src, int size) {
  EOS32_off_t offset;
  int index1, index2;
  EOS32_daddr_t bno;
  unsigned char buf[BSIZE];
  EOS32_daddr_t ibno;
  EOS32_daddr_t iblk[NINDIR];
  EOS32_daddr_t dibno;
  EOS32_daddr_t diblk[NINDIR];
 
  offset = ip->i_size;
  if (offset < NDADDR * BSIZE) {
    /* direct block */
    index1 = offset / BSIZE;
    offset %= BSIZE;
    if (ip->i_addr[index1] == 0) {
      bno = allocBlock();
      ip->i_addr[index1] = bno;
      memset(buf, 0, BSIZE);
    } else {
      bno = ip->i_addr[index1];
      rdfs(bno, buf, blkType);
    }
  } else
  if (offset < (NINDIR + NDADDR) * BSIZE) {
    /* single indirect block */
    offset -= NDADDR * BSIZE;
    index1 = offset / BSIZE;
    offset %= BSIZE;
    if (ip->i_addr[SINGLE_INDIR] == 0) {
      ibno = allocBlock();
      ip->i_addr[SINGLE_INDIR] = ibno;
      memset(iblk, 0, BSIZE);
    } else {
      ibno = ip->i_addr[SINGLE_INDIR];
      rdfs(ibno, (unsigned char *) iblk, TYPE_INDIRECT);
    }
    if (iblk[index1] == 0) {
      bno = allocBlock();
      iblk[index1] = bno;
      wtfs(ibno, (unsigned char *) iblk, TYPE_INDIRECT);
      memset(buf, 0, BSIZE);
    } else {
      bno = iblk[index1];
      rdfs(bno, buf, blkType);
    }
  } else {
    /* double indirect block */
    offset -= (NINDIR + NDADDR) * BSIZE;
    index1 = offset / BSIZE;
    offset %= BSIZE;
    index2 = index1 / NINDIR;
    index1 %= NINDIR;
    if (ip->i_addr[DOUBLE_INDIR] == 0) {
      dibno = allocBlock();
      ip->i_addr[DOUBLE_INDIR] = dibno;
      memset(diblk, 0, BSIZE);
    } else {
      dibno = ip->i_addr[DOUBLE_INDIR];
      rdfs(dibno, (unsigned char *) diblk, TYPE_INDIRECT);
    }
    if (diblk[index2] == 0) {
      ibno = allocBlock();
      diblk[index2] = ibno;
      wtfs(dibno, (unsigned char *) diblk, TYPE_INDIRECT);
      memset(iblk, 0, BSIZE);
    } else {
      ibno = diblk[index2];
      rdfs(ibno, (unsigned char *) iblk, TYPE_INDIRECT);
    }
    if (iblk[index1] == 0) {
      bno = allocBlock();
      iblk[index1] = bno;
      wtfs(ibno, (unsigned char *) iblk, TYPE_INDIRECT);
      memset(buf, 0, BSIZE);
    } else {
      bno = iblk[index1];
      rdfs(bno, buf, blkType);
    }
  }
  memcpy(buf + offset, src, size);
  wtfs(bno, buf, blkType);
  ip->i_size += size;
}
 
 
void makeDirEntry(Inode *dir, EOS32_ino_t ino, char *name) {
  Dirent entry;
 
  memset(&entry, 0, sizeof(Dirent));
  entry.d_ino = ino;
  strcpy(entry.d_name, name);
  appendData(dir, TYPE_DIRECTORY, (unsigned char *) &entry, sizeof(Dirent));
}
 
 
void createFile(Inode *parent) {
  Inode in;
  int i;
  char c;
  FILE *f;
  unsigned char buf[BSIZE];
 
  /* get mode, uid and gid */
  getStr();
  in.i_mode = getMode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR);
  in.i_mode |= getMode(string[1], "-u", 0, ISUID, 0, 0);
  in.i_mode |= getMode(string[2], "-g", 0, ISGID, 0, 0);
  for (i = 3; i < 6; i++) {
    c = string[i];
    if (c < '0' || c > '7') {
      error("%c/%s: bad octal mode digit", c, string);
    }
    in.i_mode |= (c - '0') << (15 - 3 * i);
  }
  in.i_uid = getNum();
  in.i_gid = getNum();
  /* general initialization prior to switching on format */
  lastIno++;
  in.i_number = lastIno;
  in.i_nlink = 1;
  in.i_size = 0;
  for (i = 0; i < NADDR; i++) {
    in.i_addr[i] = 0;
  }
  if (parent == NULL) {
    parent = &in;
    in.i_nlink--;
  }
  /* now switch on format */
  switch (in.i_mode & IFMT) {
    case IFREG:
      /* regular file:
         contents is a file name */
      getStr();
      f = fopen(string, "rb");
      if (f == NULL) {
        error("%s: cannot open", string);
      }
      while ((i = fread(buf, 1, BSIZE, f)) > 0) {
        appendData(&in, TYPE_COPY, buf, i);
      }
      fclose(f);
      break;
    case IFBLK:
    case IFCHR:
      /* special file:
         contents is major/minor device */
      in.i_addr[0] = (getNum() & 0xFFFF) << 16;
      in.i_addr[0] |= (getNum() & 0xFFFF);
      break;
    case IFDIR:
      /* directory:
         put in extra links, call recursively until name is "$" */
      parent->i_nlink++;
      in.i_nlink++;
      makeDirEntry(&in, in.i_number, ".");
      makeDirEntry(&in, parent->i_number, "..");
      while (1) {
        getStr();
        if (string[0] == '$' && string[1] == '\0') {
          break;
        }
        makeDirEntry(&in, lastIno + 1, string);
        createFile(&in);
      }
      break;
    default:
      error("bad format/mode %o\n", in.i_mode);
      break;
  }
  /* finally write the inode */
  iput(&in);
}
 
 
/**************************************************************/
 
 
void showSizes(void) {
  printf("BSIZE   = %d\n", BSIZE);
  printf("NICINOD = %d\n", NICINOD);
  printf("NICFREE = %d\n", NICFREE);
  printf("NADDR   = %d\n", NADDR);
  printf("NDADDR  = %d\n", NDADDR);
  printf("DIRSIZ  = %d\n", DIRSIZ);
  printf("NIPB    = %d\n", NIPB);
  printf("NDIRENT = %d\n", NDIRENT);
  printf("NINDIR  = %d\n", NINDIR);
  printf("sizeof(Filsys) = %d\n", sizeof(Filsys));
  printf("sizeof(Dinode) = %d\n", sizeof(Dinode));
  printf("sizeof(Dirent) = %d\n", sizeof(Dirent));
  printf("sizeof(Fblk)   = %d\n", sizeof(Fblk));
}
 
 
int main(int argc, char *argv[]) {
  char *fsnam;
  char *proto;
  char protoBuf[20];
  unsigned long fsSize;
  int part;
  char *endptr;
  unsigned char partTable[SSIZE];
  unsigned char *ptptr;
  unsigned long partType;
  EOS32_daddr_t maxBlocks;
  EOS32_daddr_t numBlocks;
  EOS32_ino_t numInodes;
  int i;
  char c;
  FILE *bootblk;
  long bootblkSize;
  unsigned char buf[BSIZE];
 
  if (argc == 2 && strcmp(argv[1], "--sizes") == 0) {
    showSizes();
    exit(0);
  }
  if (argc != 3 && argc != 4) {
    printf("Usage: %s <disk> <partition or '*'> [<prototype or size>]\n",
           argv[0]);
    printf("   or: %s --sizes\n", argv[0]);
    exit(1);
  }
  time(&now);
  fsnam = argv[1];
  fs = fopen(fsnam, "r+b");
  if (fs == NULL) {
    error("cannot open disk image '%s'", fsnam);
  }
  if (strcmp(argv[2], "*") == 0) {
    /* whole disk contains one single file system */
    fsStart = 0;
    fseek(fs, 0, SEEK_END);
    fsSize = ftell(fs) / SSIZE;
  } else {
    /* argv[2] is partition number of file system */
    part = strtoul(argv[2], &endptr, 10);
    if (*endptr != '\0' || part < 0 || part > 15) {
      error("illegal partition number '%s'", argv[2]);
    }
    fseek(fs, 1 * SSIZE, SEEK_SET);
    if (fread(partTable, 1, SSIZE, fs) != SSIZE) {
      error("cannot read partition table of disk '%s'", fsnam);
    }
    ptptr = partTable + part * 32;
    partType = read4FromEco(ptptr + 0);
    if ((partType & 0x7FFFFFFF) != 0x00000058) {
      error("partition %d of disk '%s' does not contain an EOS32 file system",
            part, fsnam);
    }
    fsStart = read4FromEco(ptptr + 4);
    fsSize = read4FromEco(ptptr + 8);
  }
  printf("File system space is %lu (0x%lX) sectors of %d bytes each.\n",
         fsSize, fsSize, SSIZE);
  if (fsSize % SPB != 0) {
    printf("File system space is not a multiple of block size.\n");
  }
  maxBlocks = fsSize / SPB;
  printf("This equals %lu (0x%lX) blocks of %d bytes each.\n",
         maxBlocks, maxBlocks, BSIZE);
  if (argc == 4) {
    proto = argv[3];
  } else {
    proto = protoBuf;
    sprintf(protoBuf, "%lu", maxBlocks);
  }
  /* initialize super block and possibly write boot block */
  filsys.s_magic = SUPER_MAGIC;
  fin = fopen(proto, "rt");
  if (fin == NULL) {
    /* cannot open prototype file, perhaps size was specified */
    charp = "d--777 0 0 $ ";
    numBlocks = 0;
    for (i = 0; (c = proto[i]) != '\0'; i++) {
      if (c < '0' || c > '9') {
        /* neither valid prototype file nor valid size */
        error("cannot open prototype '%s'", proto);
      }
      numBlocks = numBlocks * 10 + (c - '0');
    }
    numInodes = (numBlocks * BSIZE) / AFS;
  } else {
    /* prototype file opened */
    charp = NULL;
    getStr();
    if (strcmp(string, "-noboot-") == 0) {
      /* boot block not wanted */
    } else {
      /* string holds the name of the boot block file */
      bootblk = fopen(string, "rb");
      if (bootblk == NULL) {
        error("cannot open boot block file '%s'", string);
      }
      fseek(bootblk, 0, SEEK_END);
      bootblkSize = ftell(bootblk);
      fseek(bootblk, 0, SEEK_SET);
      if (bootblkSize > BSIZE) {
        error("boot block file '%s' is bigger than a block", string);
      }
      for (i = 0; i < BSIZE; i++) {
        buf[i] = '\0';
      }
      if (fread(buf, 1, bootblkSize, bootblk) != bootblkSize) {
        error("cannot read boot block file '%s'", string);
      }
      wtfs(0, buf, TYPE_COPY);
      fclose(bootblk);
    }
    numBlocks = getNum();
    numInodes = getNum();
  }
  if (numBlocks > maxBlocks) {
    error("file system exceeds available space");
  }
  if (numBlocks < maxBlocks) {
    printf("File system does not fully utilize available space.\n");
  }
  filsys.s_fsize = numBlocks;
  filsys.s_isize = (numInodes + NIPB - 1) / NIPB;
  numInodes = filsys.s_isize * NIPB;
  if (2 + filsys.s_isize >= filsys.s_fsize) {
    error("bad block ratio (total/inode = %lu/%lu)",
          filsys.s_fsize, filsys.s_isize);
  }
  printf("File system size = %ld blocks\n", filsys.s_fsize);
  printf("Number of inodes = %ld inodes\n", numInodes);
  filsys.s_freeblks = 0;
  filsys.s_freeinos = 0;
  filsys.s_ninode = 0;
  for (i = 0; i < NICINOD; i++) {
    filsys.s_inode[i] = 0;
  }
  filsys.s_nfree = 0;
  for (i = 0; i < NICFREE; i++) {
    filsys.s_free[i] = 0;
  }
  filsys.s_time = now;
  filsys.s_flock = 0;
  filsys.s_ilock = 0;
  filsys.s_fmod = 0;
  filsys.s_ronly = 0;
  /* init inodes */
  initInodes();
  /* init free list */
  initFreeList();
  /* create files */
  createFile(NULL);
  /* fill free inode list in super block */
  /* note: this isn't strictly necessary, but cuts down file
     creation time within the newly created partition or disk */
  fillFreeInodeList(numInodes);
  /* finally write super block and return */
  wtfs(1, (unsigned char *) &filsys, TYPE_SUPER);
  return 0;
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.