|
CS471/571 - Operating Systems
| Displaying exercises/e6/solution/tree.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 bpos, void *buf, int size);
int readino(int ino, struct dinode *di);
char *readfile(struct dinode di, int *size);
int tree(int ino, int level);
struct superblock sb;
int fsfd;
char *type[] = {"?", "DIR ", "FILE", "DEV "};
int main(int argc, char *argv[])
{
if (argc < 2) {
printf("Usage:disksb <image>\n");
return 1;
}
fsfd = open(argv[1], O_RDWR);
if(fsfd < 0){
perror(argv[1]);
exit(1);
}
if (lread(1 * BSIZE, &sb, sizeof(sb)) != sizeof(sb)) return 1;
tree(1, 0);
return 0;
}
int tree(int ino, int level)
{
int size;
struct dinode di;
if (readino(ino, &di) < 0) return -1;
char *dir = readfile(di, &size);
struct dirent *de = (struct dirent *)dir;
for(int dp=0; dp < size; dp+=sizeof(struct dirent), de++) {
if (de->inum == 0) continue;
if (strcmp(de->name, ".") == 0 || strcmp(de->name, "..") == 0) continue;
if (readino(de->inum, &di) < 0) return -1;
printf("%.*s%s %2d %5d %s\n", level, " ", type[di.type], de->inum, di.size, de->name);
if (di.type == 1) tree(de->inum, level+4);
}
}
char *readfile(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(di.addrs[NDIRECT], indirect, BSIZE);
for(blk = 0; sz > 0; blk++) {
if (blk < NDIRECT) db = di.addrs[blk];
else db = indirect[blk-NDIRECT];
lread(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 readino(int ino, struct dinode *di)
{
if (lread((sb.inodestart * BSIZE) + (ino*sizeof(*di)), di, sizeof(*di)) != sizeof(*di))
return -1;
return 0;
}
int lread(int bpos, void *buf, int size)
{
int n;
if (lseek(fsfd, bpos, SEEK_SET) != bpos) {
perror("lseek");
return -1;
}
if ( (n = read(fsfd, buf, size)) < 0) {
perror("read");
return -1;
}
// printf("read %d = %d\n", size, n);
return n;
}
|