refactor
This commit is contained in:
parent
2bd8cca428
commit
fc2b116dc2
341
dump_inode.c
341
dump_inode.c
|
@ -44,10 +44,24 @@ union dinode {
|
|||
#define DIP(dp, field) \
|
||||
((sblock->fs_magic == FS_UFS1_MAGIC) ? (dp)->dp1.field : (dp)->dp2.field)
|
||||
|
||||
typedef void (*process_fn)(union dinode *dp, void *datablock, size_t blksize,
|
||||
off_t blkoff);
|
||||
|
||||
void usage(void);
|
||||
void dump_inode(ino_t inum, union dinode *dp);
|
||||
void dump_directory(union dinode *dp);
|
||||
void dump_file(union dinode *dp);
|
||||
void dump_data(union dinode *dp, process_fn process_data,
|
||||
process_fn process_gap);
|
||||
void dump_indirect(union dinode *dp, void *indirblock, int level,
|
||||
off_t *filesize, process_fn process_data,
|
||||
process_fn process_gap);
|
||||
|
||||
void process_directory(union dinode *dp, void *datablock, size_t blksize,
|
||||
off_t blkoff);
|
||||
void process_dirblk(int deleted, void *dirblk, size_t size);
|
||||
void process_file(union dinode *dp, void *datablock, size_t blksize,
|
||||
off_t blkoff);
|
||||
void process_file_gap(union dinode *dp, void *datablock, size_t gapsize,
|
||||
off_t blkoff);
|
||||
|
||||
void *xmalloc(size_t size);
|
||||
void xpread(int fd, void *buf, size_t nbytes, off_t offset);
|
||||
|
@ -158,7 +172,9 @@ int main(int argc, char **argv) {
|
|||
(struct ufs2_dinode *)inoblock)[ino_to_fsbo(sblock, inum)];
|
||||
}
|
||||
if (mode & MODE_DIRECTORY) {
|
||||
dump_directory(dp);
|
||||
if ((DIP(dp, di_mode) & IFMT) == IFDIR) {
|
||||
dump_data(dp, process_directory, NULL);
|
||||
}
|
||||
} else {
|
||||
dump_inode(inum, dp);
|
||||
}
|
||||
|
@ -175,12 +191,14 @@ int main(int argc, char **argv) {
|
|||
(struct ufs2_dinode *)inoblock)[ino_to_fsbo(sblock, inode)];
|
||||
}
|
||||
if (mode & MODE_FILE) {
|
||||
dump_file(dp);
|
||||
dump_data(dp, process_file, process_file_gap);
|
||||
fprintf(stderr, "\r%" PRIu64 "/%" PRIu64 "\n", DIP(dp, di_size),
|
||||
DIP(dp, di_size));
|
||||
} else if (mode & MODE_DIRECTORY) {
|
||||
if ((DIP(dp, di_mode) & IFMT) != IFDIR) {
|
||||
errx(1, "Not a directory");
|
||||
}
|
||||
dump_directory(dp);
|
||||
dump_data(dp, process_directory, NULL);
|
||||
} else {
|
||||
dump_inode(inode, dp);
|
||||
}
|
||||
|
@ -233,10 +251,99 @@ void dump_inode(ino_t inum, union dinode *dp) {
|
|||
DIP(dp, di_mtime), DIP(dp, di_ctime));
|
||||
}
|
||||
|
||||
void dump_dirblk(int deleted, void *dirblk, size_t size) {
|
||||
void dump_data(union dinode *dp, process_fn process_data,
|
||||
process_fn process_gap) {
|
||||
char *datablock = xmalloc(sblock->fs_bsize);
|
||||
off_t filesize = DIP(dp, di_size);
|
||||
for (int i = 0; filesize > 0 && i < NDADDR;
|
||||
filesize -= sblock->fs_bsize, i++) {
|
||||
if (!DIP(dp, di_db[i])) {
|
||||
if (process_gap) {
|
||||
memset(datablock, 0, sblock->fs_bsize);
|
||||
process_gap(dp, datablock, sblock->fs_bsize,
|
||||
DIP(dp, di_size) - filesize);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
size_t blksize = sblksize(sblock, DIP(dp, di_size), i);
|
||||
daddr_t blkno = fsbtodb(sblock, DIP(dp, di_db[i]));
|
||||
xpread(diskfd, datablock, blksize, blkno * DEV_BSIZE);
|
||||
if (filesize < blksize) {
|
||||
blksize = filesize;
|
||||
}
|
||||
process_data(dp, datablock, blksize, DIP(dp, di_size) - filesize);
|
||||
}
|
||||
for (int i = 0; filesize > 0 && i < NIADDR; i++) {
|
||||
if (!DIP(dp, di_ib[i])) {
|
||||
size_t gapsize = NINDIR(sblock) * sblock->fs_bsize;
|
||||
for (int j = 0; j < i; j++) {
|
||||
gapsize *= NINDIR(sblock);
|
||||
}
|
||||
if (process_gap) {
|
||||
memset(datablock, 0, sblock->fs_bsize);
|
||||
process_gap(dp, datablock, gapsize, DIP(dp, di_size) - filesize);
|
||||
}
|
||||
filesize -= gapsize;
|
||||
continue;
|
||||
}
|
||||
daddr_t blkno = fsbtodb(sblock, DIP(dp, di_ib[i]));
|
||||
xpread(diskfd, datablock, sblock->fs_bsize, blkno * DEV_BSIZE);
|
||||
dump_indirect(dp, datablock, i, &filesize, process_data, process_gap);
|
||||
}
|
||||
free(datablock);
|
||||
}
|
||||
|
||||
void dump_indirect(union dinode *dp, void *indirblock, int level,
|
||||
off_t *filesize, process_fn process_data,
|
||||
process_fn process_gap) {
|
||||
void *datablock = xmalloc(sblock->fs_bsize);
|
||||
for (int i = 0; *filesize > 0 && i < NINDIR(sblock); i++) {
|
||||
daddr_t fsblkno;
|
||||
if (sblock->fs_magic == FS_UFS1_MAGIC) {
|
||||
fsblkno = ((uint32_t *)indirblock)[i];
|
||||
} else {
|
||||
fsblkno = ((uint64_t *)indirblock)[i];
|
||||
}
|
||||
if (!fsblkno) {
|
||||
size_t gapsize = sblock->fs_bsize;
|
||||
for (int j = 0; j < level; j++) {
|
||||
gapsize *= NINDIR(sblock);
|
||||
}
|
||||
if (process_gap) {
|
||||
memset(datablock, 0, sblock->fs_bsize);
|
||||
process_gap(dp, datablock, gapsize, DIP(dp, di_size) - *filesize);
|
||||
}
|
||||
*filesize -= gapsize;
|
||||
continue;
|
||||
}
|
||||
size_t blksize = sblock->fs_bsize;
|
||||
daddr_t blkno = fsbtodb(sblock, fsblkno);
|
||||
xpread(diskfd, datablock, blksize, blkno * DEV_BSIZE);
|
||||
if (level) {
|
||||
dump_indirect(dp, datablock, level - 1, filesize, process_data,
|
||||
process_gap);
|
||||
} else {
|
||||
if (*filesize < blksize) {
|
||||
blksize = *filesize;
|
||||
}
|
||||
process_data(dp, datablock, blksize, DIP(dp, di_size) - *filesize);
|
||||
*filesize -= sblock->fs_bsize;
|
||||
}
|
||||
}
|
||||
free(datablock);
|
||||
}
|
||||
|
||||
void process_directory(union dinode *dp, void *datablock, size_t blksize,
|
||||
off_t blkoff) {
|
||||
for (size_t j = 0; j < blksize; j += DIRBLKSIZ) {
|
||||
process_dirblk(0, datablock + j, MIN(blksize - j, DIRBLKSIZ));
|
||||
}
|
||||
}
|
||||
|
||||
void process_dirblk(int deleted, void *dirblk, size_t size) {
|
||||
char *end = (char *)dirblk + size;
|
||||
for (struct direct *d = dirblk;
|
||||
(char *)&d->d_name < end && d->d_name + d->d_namlen - 1 < end;
|
||||
(char *)&d->d_namlen < end && d->d_name + d->d_namlen - 1 < end;
|
||||
d = (struct direct *)((char *)d + d->d_reclen)) {
|
||||
char type;
|
||||
switch (d->d_type) {
|
||||
|
@ -278,210 +385,40 @@ void dump_dirblk(int deleted, void *dirblk, size_t size) {
|
|||
return;
|
||||
}
|
||||
if (d->d_reclen > DIRSIZ(NEWDIRFMT, d)) {
|
||||
dump_dirblk(1, (char *)d + DIRSIZ(NEWDIRFMT, d),
|
||||
d->d_reclen - DIRSIZ(NEWDIRFMT, d));
|
||||
process_dirblk(1, (char *)d + DIRSIZ(NEWDIRFMT, d),
|
||||
d->d_reclen - DIRSIZ(NEWDIRFMT, d));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dump_directory_indirect(union dinode *dp, void *indirblock, int level, off_t *filesize) {
|
||||
void *datablock = xmalloc(sblock->fs_bsize);
|
||||
if (!level) {
|
||||
for (int i = 0; *filesize > 0 && i < NINDIR(sblock);
|
||||
*filesize -= sblock->fs_bsize, i++) {
|
||||
daddr_t fsblkno;
|
||||
if (sblock->fs_magic == FS_UFS1_MAGIC) {
|
||||
fsblkno = ((uint32_t *)indirblock)[i];
|
||||
} else {
|
||||
fsblkno = ((uint64_t *)indirblock)[i];
|
||||
}
|
||||
if (!fsblkno) {
|
||||
continue;
|
||||
}
|
||||
size_t blksize = sblock->fs_bsize;
|
||||
daddr_t blkno = fsbtodb(sblock, fsblkno);
|
||||
xpread(diskfd, datablock, blksize, blkno * DEV_BSIZE);
|
||||
if (*filesize < blksize) {
|
||||
blksize = *filesize;
|
||||
}
|
||||
for (size_t j = 0; j < blksize; j += DIRBLKSIZ) {
|
||||
dump_dirblk(0, datablock + j, MIN(blksize - j, DIRBLKSIZ));
|
||||
}
|
||||
void process_file(union dinode *dp, void *datablock, size_t blksize,
|
||||
off_t blkoff) {
|
||||
if (filefd == STDOUT_FILENO) {
|
||||
xwrite(filefd, datablock, blksize);
|
||||
} else {
|
||||
xpwrite(filefd, datablock, blksize, blkoff);
|
||||
}
|
||||
if (blkoff / (1024 * 1024) != (blkoff + blksize) / (1024 * 1024)) {
|
||||
fprintf(stderr, "\r%" PRIu64 "/%" PRIu64, blkoff + blksize,
|
||||
DIP(dp, di_size));
|
||||
}
|
||||
}
|
||||
|
||||
void process_file_gap(union dinode *dp, void *datablock, size_t gapsize,
|
||||
off_t blkoff) {
|
||||
if (filefd == STDOUT_FILENO) {
|
||||
for (int j = 0; j < gapsize / sblock->fs_bsize; j++) {
|
||||
xwrite(filefd, datablock, sblock->fs_bsize);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; *filesize > 0 && i < NINDIR(sblock); i++) {
|
||||
daddr_t fsblkno;
|
||||
if (sblock->fs_magic == FS_UFS1_MAGIC) {
|
||||
fsblkno = ((uint32_t *)indirblock)[i];
|
||||
} else {
|
||||
fsblkno = ((uint64_t *)indirblock)[i];
|
||||
}
|
||||
if (!fsblkno) {
|
||||
size_t gapsize = NINDIR(sblock) * sblock->fs_bsize;
|
||||
for (int j = 0; j < i; j++) {
|
||||
gapsize *= NINDIR(sblock);
|
||||
}
|
||||
*filesize -= gapsize;
|
||||
continue;
|
||||
}
|
||||
daddr_t blkno = fsbtodb(sblock, fsblkno);
|
||||
xpread(diskfd, datablock, sblock->fs_bsize, blkno * DEV_BSIZE);
|
||||
dump_directory_indirect(dp, datablock, level - 1, filesize);
|
||||
if (ftruncate(filefd, blkoff + gapsize) == -1) {
|
||||
err(1, "ftruncate() failed");
|
||||
}
|
||||
}
|
||||
free(datablock);
|
||||
}
|
||||
|
||||
void dump_directory(union dinode *dp) {
|
||||
if ((DIP(dp, di_mode) & IFMT) != IFDIR) {
|
||||
return;
|
||||
if (blkoff / (1024 * 1024) != (blkoff + gapsize) / (1024 * 1024)) {
|
||||
fprintf(stderr, "\r%" PRIu64 "/%" PRIu64, blkoff + gapsize,
|
||||
DIP(dp, di_size));
|
||||
}
|
||||
char *datablock = xmalloc(sblock->fs_bsize);
|
||||
off_t filesize = DIP(dp, di_size);
|
||||
for (int i = 0; filesize > 0 && i < NDADDR;
|
||||
filesize -= sblock->fs_bsize, i++) {
|
||||
if (!DIP(dp, di_db[i])) {
|
||||
continue;
|
||||
}
|
||||
size_t blksize = sblksize(sblock, DIP(dp, di_size), i);
|
||||
daddr_t blkno = fsbtodb(sblock, DIP(dp, di_db[i]));
|
||||
xpread(diskfd, datablock, blksize, blkno * DEV_BSIZE);
|
||||
if (filesize < blksize) {
|
||||
blksize = filesize;
|
||||
}
|
||||
for (size_t j = 0; j < blksize; j += DIRBLKSIZ) {
|
||||
dump_dirblk(0, datablock + j, MIN(blksize - j, DIRBLKSIZ));
|
||||
}
|
||||
}
|
||||
for (int i = 0; filesize > 0 && i < NIADDR; i++) {
|
||||
if (!DIP(dp, di_ib[i])) {
|
||||
size_t gapsize = NINDIR(sblock) * sblock->fs_bsize;
|
||||
for (int j = 0; j < i; j++) {
|
||||
gapsize *= NINDIR(sblock);
|
||||
}
|
||||
filesize -= gapsize;
|
||||
continue;
|
||||
}
|
||||
daddr_t blkno = fsbtodb(sblock, DIP(dp, di_ib[i]));
|
||||
xpread(diskfd, datablock, sblock->fs_bsize, blkno * DEV_BSIZE);
|
||||
dump_directory_indirect(dp, datablock, i, &filesize);
|
||||
}
|
||||
free(datablock);
|
||||
}
|
||||
|
||||
void dump_file_indirect(union dinode *dp, void *indirblock, int level,
|
||||
off_t *filesize) {
|
||||
void *datablock = xmalloc(sblock->fs_bsize);
|
||||
if (!level) {
|
||||
for (int i = 0; *filesize > 0 && i < NINDIR(sblock);
|
||||
*filesize -= sblock->fs_bsize, i++) {
|
||||
daddr_t fsblkno;
|
||||
if (sblock->fs_magic == FS_UFS1_MAGIC) {
|
||||
fsblkno = ((uint32_t *)indirblock)[i];
|
||||
} else {
|
||||
fsblkno = ((uint64_t *)indirblock)[i];
|
||||
}
|
||||
if (!fsblkno) {
|
||||
if (filefd == STDOUT_FILENO) {
|
||||
memset(datablock, 0, sblock->fs_bsize);
|
||||
xwrite(filefd, datablock, sblock->fs_bsize);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
size_t blksize = sblock->fs_bsize;
|
||||
daddr_t blkno = fsbtodb(sblock, fsblkno);
|
||||
xpread(diskfd, datablock, blksize, blkno * DEV_BSIZE);
|
||||
if (*filesize < blksize) {
|
||||
blksize = *filesize;
|
||||
}
|
||||
if (filefd == STDOUT_FILENO) {
|
||||
xwrite(filefd, datablock, blksize);
|
||||
} else {
|
||||
xpwrite(filefd, datablock, blksize, DIP(dp, di_size) - *filesize);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; *filesize > 0 && i < NINDIR(sblock); i++) {
|
||||
daddr_t fsblkno;
|
||||
if (sblock->fs_magic == FS_UFS1_MAGIC) {
|
||||
fsblkno = ((uint32_t *)indirblock)[i];
|
||||
} else {
|
||||
fsblkno = ((uint64_t *)indirblock)[i];
|
||||
}
|
||||
if (!fsblkno) {
|
||||
size_t gapsize = NINDIR(sblock) * sblock->fs_bsize;
|
||||
for (int j = 0; j < i; j++) {
|
||||
gapsize *= NINDIR(sblock);
|
||||
}
|
||||
*filesize -= gapsize;
|
||||
if (filefd == STDOUT_FILENO) {
|
||||
memset(datablock, 0, sblock->fs_bsize);
|
||||
for (int j = 0; j < gapsize / sblock->fs_bsize; j++) {
|
||||
xwrite(filefd, datablock, sblock->fs_bsize);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
daddr_t blkno = fsbtodb(sblock, fsblkno);
|
||||
xpread(diskfd, datablock, sblock->fs_bsize, blkno * DEV_BSIZE);
|
||||
dump_file_indirect(dp, datablock, level - 1, filesize);
|
||||
}
|
||||
}
|
||||
free(datablock);
|
||||
fprintf(stderr, "\r%" PRIu64 "/%" PRIu64, DIP(dp, di_size) - *filesize,
|
||||
DIP(dp, di_size));
|
||||
}
|
||||
|
||||
void dump_file(union dinode *dp) {
|
||||
off_t filesize = DIP(dp, di_size);
|
||||
if (filefd != STDOUT_FILENO && ftruncate(filefd, filesize) == -1) {
|
||||
err(1, "ftruncate() failed");
|
||||
}
|
||||
void *datablock = xmalloc(sblock->fs_bsize);
|
||||
int i;
|
||||
for (i = 0; filesize > 0 && i < NDADDR; filesize -= sblock->fs_bsize, i++) {
|
||||
if (!DIP(dp, di_db[i])) {
|
||||
if (filefd == STDOUT_FILENO) {
|
||||
memset(datablock, 0, sblock->fs_bsize);
|
||||
xwrite(filefd, datablock, sblksize(sblock, DIP(dp, di_size), i));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
size_t blksize = sblksize(sblock, DIP(dp, di_size), i);
|
||||
daddr_t blkno = fsbtodb(sblock, DIP(dp, di_db[i]));
|
||||
xpread(diskfd, datablock, blksize, blkno * DEV_BSIZE);
|
||||
if (filesize < blksize) {
|
||||
blksize = filesize;
|
||||
}
|
||||
if (filefd == STDOUT_FILENO) {
|
||||
xwrite(filefd, datablock, blksize);
|
||||
} else {
|
||||
xpwrite(filefd, datablock, blksize, DIP(dp, di_size) - filesize);
|
||||
}
|
||||
}
|
||||
for (i = 0; filesize > 0 && i < NIADDR; i++) {
|
||||
if (!DIP(dp, di_ib[i])) {
|
||||
size_t gapsize = NINDIR(sblock) * sblock->fs_bsize;
|
||||
for (int j = 0; j < i; j++) {
|
||||
gapsize *= NINDIR(sblock);
|
||||
}
|
||||
filesize -= gapsize;
|
||||
if (filefd == STDOUT_FILENO) {
|
||||
memset(datablock, 0, sblock->fs_bsize);
|
||||
for (int j = 0; j < gapsize / sblock->fs_bsize; j++) {
|
||||
xwrite(filefd, datablock, sblock->fs_bsize);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
daddr_t blkno = fsbtodb(sblock, DIP(dp, di_ib[i]));
|
||||
xpread(diskfd, datablock, sblock->fs_bsize, blkno * DEV_BSIZE);
|
||||
dump_file_indirect(dp, datablock, i, &filesize);
|
||||
}
|
||||
if (i) {
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
free(datablock);
|
||||
}
|
||||
|
||||
void *xmalloc(size_t size) {
|
||||
|
|
Loading…
Reference in a new issue