|
CS471/571 - Operating Systems
| Displaying exercises/e6/solution/fcat.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"
char bdata[BSIZE];
int findino(char **paths, int index, int ino);
char *readfile(int ino, int *size);
int readino(int ino, struct dinode *di);
int lread(int bpos, void *buf, int size);
struct superblock sb;
int fsfd;
int main(int argc, char *argv[])
{
int size, i = 0;
if (argc < 3) {
printf("Usage:fcat <image> <file>\n");
return 1;
}
if ((fsfd = open(argv[1], O_RDWR)) < 0) {
perror(argv[1]);
exit(1);
}
char *path = argv[2], *paths[10], *s;
if (lread(1 * BSIZE, &sb, sizeof(sb)) != sizeof(sb)) return 1;
if (strchr(path, '/') != NULL) {
for(s=strtok(path, "/"); s; s=strtok(NULL, "/"))
paths[i++] = s;
} else paths[i++] = path;
paths[i] = NULL;
int ino = findino(paths, 0, 1);
if (ino <= 0) {
printf("File not found\n");
return 1;
}
// fprintf(stderr,"Reading inode %d\n", ino);
char *data = readfile(ino, &size);
for(int i=0; i < size; i++)
putchar(data[i]);
return 0;
}
// struct dirent {
// ushort inum;
// char name[DIRSIZ];
// };
int findino(char **paths, int index, int ino)
{
int size;
struct dirent *de = (struct dirent *)readfile(ino, &size);
for(int dp=0; dp < size; de++, dp += sizeof(struct dirent)) {
if (de->inum == 0) continue;
if (strcmp(de->name, paths[index]) == 0) {
if (paths[index+1] != NULL) return findino(paths, index+1, de->inum);
return de->inum;
}
}
return -1;
}
int readino(int ino, struct dinode *di)
{
int inoloc = (sb.inodestart*BSIZE)+(ino*sizeof(struct dinode));
if (lseek(fsfd, inoloc, SEEK_SET) != inoloc) {
perror("lseek");
return -1;
}
return read(fsfd, di, sizeof(struct dinode));
}
char *readfile(int ino, int *size)
{
struct dinode di;
char buf[BSIZE];
uint indirect[NINDIRECT];
readino(ino, &di);
if (di.nlink == 0) return NULL;
int sz = di.size, rd = 0;
int blks = sz/BSIZE, blk = 0, db;
char *data = malloc(di.size);
if (blks >= NDIRECT) lread(di.addrs[NDIRECT] * BSIZE, indirect, BSIZE);
for(blk = 0; sz > 0; blk++) {
if (blk < NDIRECT) db = di.addrs[blk];
else db = indirect[blk-NDIRECT];
int mx = sz < BSIZE? sz: BSIZE;
lread(db * BSIZE, data+rd, mx);
rd += mx;
sz -= mx;
}
*size = rd;
return data;
}
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;
}
return n;
}
|