Logo  

CS471/571 - Operating Systems

Displaying ./code/Xv6/fscatls/cat.c

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

#define min(a, b)	((a) < (b)? (a) : (b))

typedef unsigned short ushort;
typedef unsigned int uint;

#include "fs.h"

char *filetype[] = {"?", "dir", "regular", "device" };
typedef enum { UNKNOWN = 0, DIR =1, REGULAR = 2, DEVICE = 3 } ftype;

int fsfd;
struct superblock sb;

int readinode(int inum, struct dinode *di)
{
  lseek(fsfd, (sb.inodestart*BSIZE) + inum*sizeof(struct dinode), SEEK_SET);
  return read(fsfd, di, sizeof(struct dinode));
}

int readblock(int blkno, unsigned char *buf)
{
  lseek(fsfd, blkno*BSIZE, SEEK_SET);
  return read(fsfd, buf, BSIZE);
}

int main(int argc, char *argv[])
{
  if (argc < 3) {
    printf("Usage: cat <fs.img> <inode#>\n");
    return 1;
  }

  fsfd = open(argv[1], O_RDONLY);
  if (fsfd < 0) {
    perror("fs open");
    return 1;
  }

  lseek(fsfd, BSIZE, SEEK_SET);
  read(fsfd, &sb, sizeof(struct superblock));

  printf("sb.size       = %d\n", sb.size);
  printf("sb.nblocks    = %d\n", sb.nblocks);
  printf("sb.inodes     = %d\n", sb.ninodes);
  printf("sb.nlog       = %d\n", sb.nlog);
  printf("sb.logstart   = %d\n", sb.logstart);
  printf("sb.inodestart = %d\n", sb.inodestart);
  printf("sb.bmapstart  = %d\n", sb.bmapstart);

  printf("Inode size    = %d\n", sizeof(struct dinode));

  struct dinode ino;
  readinode(atoi(argv[2]), &ino);

  printf("File type = %d (%s)\n", ino.type, filetype[ino.type]);
  printf("Major #   = %d\n", ino.major);
  printf("Minor #   = %d\n", ino.minor);
  printf("nlink     = %d\n", ino.nlink);
  printf("size      = %d\n", ino.size);

  uint indirect[NINDIRECT];
  unsigned char block[BSIZE];
  int r = 0, left = ino.size, addrindex = 0;
  if (ino.size > BSIZE*NDIRECT) {
    readblock(ino.addrs[NDIRECT], (unsigned char *)indirect);
  }

  while (left > 0) {
    if (addrindex >= NDIRECT) {
      r = readblock(indirect[addrindex-NDIRECT], block);
    } else {
//      printf("block addr : %d [%d]\n", ino.addrs[addrindex], addrindex);
      r = readblock(ino.addrs[addrindex], block);
    }
    write(STDERR_FILENO, block, min(BSIZE, left));

    addrindex++;
    left -= r;
  }

  return 0;
}