📄 readfs.c
字号:
/* readfs - read a MINIX file system Author: Paul Polderman *//* Command: readfs - read and extract a MINIX filesystem. * * Syntax: readfs [-li] block-special [directory] * * Flags: -l: Extract files and dirs and produce a mkfs-listing on stdout * -i: Information only: give the listing, but do not extract files. * -d: Don't extract regular files, just the skeleton please. * * Examples: readfs /dev/fd1 # extract all files from /dev/fd1. * readfs -i /dev/hd2 # see what's on /dev/hd2. * readfs -l /dev/at0 rootfs # extract and list the filesystem * # of /dev/at0 and put the tree * # in the directory `rootfs'. * * Readfs reads a MINIX filesystem and extracts recursively all directories * and files, and (optionally) produces a mkfs-listing of them on stdout. * The root directory contents are placed in the current directory, unless * a directory is given as argument, in which case the contents are put there. * Readfs tries to restore the attributes (mode/uid/gid/time) of the files * extracted to those of the original files. * Special files are created as ordinary files, but the mkfs-listing * enables mkfs to restore them to original. */#include <sys/types.h>#include <sys/dir.h>#include <sys/stat.h>#include <sys/wait.h>#include <fcntl.h>#include <limits.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <utime.h>#include <minix/config.h>#include <minix/const.h>#include <minix/type.h>#include "../../fs/const.h"#include "../../fs/type.h"#include "../../fs/buf.h"#include "../../fs/super.h"#undef printf /* Definition used only in the kernel */#include <stdio.h>/* Compile with -I/user0/ast/minix * (i.e. the directory containing the MINIX system sources) * * Author: Paul Polderman (polder@cs.vu.nl) April 1987 */char verbose = 0; /* give a mkfs-listing of the filesystem */ /* And extracts its contents. */char noaction = 0; /* just give a mkfs-listing, do not extract * files. */char nofiles = 0; /* only extract the skeleton FS structure */struct super_block sb;char pathname[1024];int inodes_per_block;_PROTOTYPE(int main, (int argc, char **argv));_PROTOTYPE(void get_flags, (char *flags));_PROTOTYPE(void readfs, (char *special_file, char *directory));_PROTOTYPE(int get_inode, (int fd, Ino_t inum, d1_inode * ip));_PROTOTYPE(void dump_dir, (int special, d1_inode * ip, char *directory));_PROTOTYPE(int dump_file, (int special, d1_inode * ip, char *filename));_PROTOTYPE(int get_fileblock, (int special, d1_inode * ip, block_t b, struct buf * bp));_PROTOTYPE(int get_block, (int fd, block_t block, struct buf * bp, int type));_PROTOTYPE(int get_rawblock, (int special, block_t blockno, char *bufp));_PROTOTYPE(void restore, (char *name, d1_inode * ip));_PROTOTYPE(void show_info, (char *name, d1_inode * ip, char *path));_PROTOTYPE(void do_indent, (int i));_PROTOTYPE(int Mkdir, (char *directory));int main(argc, argv)int argc;char **argv;{ switch (argc) { case 2: pathname[0] = '\0'; readfs(argv[1], pathname); break; case 3: if (argv[1][0] == '-') { get_flags(&argv[1][1]); pathname[0] = '\0'; readfs(argv[2], pathname); } else { strcpy(pathname, argv[2]); readfs(argv[1], pathname); } break; case 4: if (argv[1][0] == '-') { get_flags(&argv[1][1]); strcpy(pathname, argv[3]); readfs(argv[2], pathname); break; } /* else fall through .. */ default: fprintf(stderr, "Usage: %s [-li] <special> [dirname]\n", argv[0]); exit(1); } return(0);}void get_flags(flags)register char *flags;{ while (*flags) { switch (*flags) { case 'L': case 'l': verbose = 1; break; case 'I': case 'i': noaction = 1; verbose = 1; break; case 'D': case 'd': nofiles = 1; break; default: fprintf(stderr, "Bad flag: %c\n", *flags); break; } flags++; }}#define zone_shift (sb.s_log_zone_size) /* zone to block ratio */void readfs(special_file, directory)char *special_file, *directory;/* Readfs: opens the given special file (with MINIX filesystem), * and extracts its contents into the given directory. */{ d1_inode root_inode; int special, magic; off_t super_b; umask(0); /* Open the special file */ if ((special = open(special_file, O_RDONLY)) < 0) { fprintf(stderr, "cannot open %s\n", special_file); return; } /* Read the superblock */ super_b = (off_t) SUPER_BLOCK *(off_t) BLOCK_SIZE; if (lseek(special, super_b, SEEK_SET) != super_b) { fprintf(stderr, "cannot seek to superblock\n"); return; } if (read(special, (char *) &sb, sizeof(struct super_block)) != sizeof(struct super_block)) { fprintf(stderr, "cannot read superblock\n"); return; } /* The number of inodes in a block differs in V1 and V2. */ magic = sb.s_magic; if (magic == SUPER_MAGIC || magic == SUPER_REV) { inodes_per_block = V1_INODES_PER_BLOCK; } else { inodes_per_block = V2_INODES_PER_BLOCK; } /* Is it really a MINIX filesystem ? */ if (magic != SUPER_MAGIC && magic != SUPER_V2) { fprintf(stderr, "%s is not a valid MINIX filesystem\n", special_file); return; } /* Fetch the inode of the root directory */ if (get_inode(special, (ino_t) ROOT_INODE, &root_inode) < 0) { fprintf(stderr, "cannot get inode of root directory\n"); return; } /* Print number of blocks and inodes */ if (verbose) printf("boot\n%ld %d\n", (block_t) sb.s_nzones << zone_shift, sb.s_ninodes); /* Extract (recursively) the root directory */ dump_dir(special, &root_inode, directory);}/* Different type of blocks: (used in routine get_block for caching) */#define B_INODE 0 /* Cache #0 is the inode cache */#define B_INDIRECT 1 /* Cache #1 is the (dbl) indirect block cache */#define B_DATA 2 /* No cache for data blocks (only read once) */int get_inode(fd, inum, ip)int fd;ino_t inum;d1_inode *ip;/* Get inode `inum' from the MINIX filesystem. (Uses the inode-cache) */{ struct buf bp; block_t block; block_t ino_block; unsigned short ino_offset; /* Calculate start of i-list */ block = SUPER_BLOCK + 1 + sb.s_imap_blocks + sb.s_zmap_blocks; /* Calculate block with inode inum */ ino_block = ((inum - 1) / inodes_per_block); ino_offset = ((inum - 1) % inodes_per_block); block += ino_block; /* Fetch the block */ if (get_block(fd, block, &bp, B_INODE) == 0) { memcpy((void *) ip, (void *) &bp.b_v1_ino[ino_offset], sizeof(d1_inode)); return(0); } /* Oeps, foutje .. */ fprintf(stderr, "cannot find inode %d\n", inum); return(-1);}static int indent = 0; /* current indent (used for mkfs-listing) */void dump_dir(special, ip, directory)int special;d1_inode *ip;char *directory;/* Make the given directory (if non-NULL), * and recursively extract its contents. */{ register struct direct *dp; register int n_entries; register char *name; block_t b = 0; d1_inode dip; struct buf bp; if (verbose) { show_info(directory, ip, ""); indent++; } if (!noaction && *directory) { /* Try to make the directory if not already there */ if (Mkdir(directory) != 0 || chdir(directory) < 0) { fprintf(stderr, "Mkdir %s failed\n", directory); return; } } for (name = directory; *name; name++) /* Find end of pathname */ ; *name++ = '/'; /* Add trailing slash */ n_entries = (int) (ip->d1_size / (off_t) sizeof(struct direct)); while (n_entries > 0) { /* Read next block of the directory */ if (get_fileblock(special, ip, b, &bp) < 0) return; dp = &bp.b_dir[0]; if (b++ == (block_t) 0) { dp += 2; /* Skip "." and ".." */ n_entries -= 2; } /* Extract the files/directories listed in the block */ while (n_entries-- > 0 && dp < &bp.b_dir[NR_DIR_ENTRIES]) { if (dp->d_ino != (ino_t) 0) { if (get_inode(special, dp->d_ino, &dip) < 0) { /* Bad luck */ dp++; continue; } /* Add new pathname-component to `pathname'. */ strncpy(name, dp->d_name, (size_t) NAME_MAX); name[NAME_MAX] = '\0'; /* Call the right routine */ if ((dip.d1_mode & I_TYPE) == I_DIRECTORY) dump_dir(special, &dip, name); else dump_file(special, &dip, name); } dp++; /* Next entry, please. */ } } *--name = '\0'; /* Restore `pathname' to what it was. */ if (!noaction && *directory) { chdir(".."); /* Go back up. */ restore(directory, ip); /* Restore mode/owner/accesstime */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -