Logo  

CS471/571 - Operating Systems

Displaying exercises/e6/files/disksb.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include "fs.h"
#include <arpa/inet.h>

int lread(int fd, int bpos, void *buf, int size);
char *readfile(int fsfd, struct dinode di, int *size);

/**
 * This program dumps the superblock information for a Xv6 filesystem
 * and attempts to read and output inode 3 (probably the README) from
 * the filesystem image specified on the command line.
 */
int main(int argc, char *argv[])
{
  if (argc < 2) {
    printf("Usage:disksb <image>\n");
    return 1;
  }

  int fsfd = open(argv[1], O_RDWR);
  if(fsfd < 0){
    perror(argv[1]);
    exit(1);
  }

  struct superblock sb;

  if (lread(fsfd, 1 * BSIZE, &sb, sizeof(sb)) != sizeof(sb)) return 1;

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

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

  int dpos = sb.inodestart * BSIZE;
  struct dinode di;
  char *type[] = {"?", "DIR ", "FILE", "DEV "};

  for(int ino = 0; ino < sb.ninodes; ino++) {
    if (lread(fsfd, dpos, &di, sizeof(di)) != sizeof(di)) return 1;
    dpos += sizeof(di);

    if (di.nlink == 0) continue;

    printf("%d: %s links: %d size: %d\n", ino, type[di.type], di.nlink, di.size);
  }

  // Fetch inode #3 into di:
  if (lread(fsfd, (sb.inodestart * BSIZE) + (3*sizeof(di)), &di, sizeof(di)) != sizeof(di)) return 1;

  int size;
  char *data = readfile(fsfd, di, &size);

  for(int i=0; i < size; i++) putchar(data[i]);

  return 0;
}

char *readfile(int fsfd, struct dinode di, int *size)
{
  char buf[BSIZE];
  uint indirect[NINDIRECT];
  int sz = di.size, rd = 0;
  int blks = sz/BSIZE, blk = 0, db;

  char *data = NULL;
  
  if (blks >= NDIRECT) lread(fsfd, di.addrs[NDIRECT], indirect, BSIZE);

  for(blk = 0; sz > 0; blk++) {
    if (blk < NDIRECT) db = di.addrs[blk];
    else db = indirect[blk-NDIRECT];

    lread(fsfd, db * BSIZE, buf, BSIZE);
    int mx = sz < BSIZE? sz: BSIZE;

    data = realloc(data, rd+mx);
    memcpy(data+rd, buf, mx);

    rd += mx;
    sz -= mx;
  }

  printf("Read %d bytes\n", rd);
  *size = rd;
  return data;
}

int lread(int fd, int bpos, void *buf, int size)
{
  int n;
  if (lseek(fd, bpos, SEEK_SET) != bpos) {
    perror("lseek");
    return -1;
  }
  if ( (n = read(fd, buf, size)) < 0) {
    perror("read");
    return -1;
  }
  return n;
}