?? cramfsck.c
字號:
die(FSCK_UNCORRECTED, 0, "decompression error %p(%d): %s", zError(err), src, len); } return stream.total_out;}static void do_uncompress(char *path, int fd, unsigned long offset, unsigned long size){ unsigned long curr = offset + 4 * ((size + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE); do { unsigned long out = PAGE_CACHE_SIZE; unsigned long next = *(u32 *) romfs_read(offset); if (next > end_data) { end_data = next; } offset += 4; if (curr == next) { if (opt_verbose > 1) { printf(" hole at %ld (%d)\n", curr, PAGE_CACHE_SIZE); } if (size < PAGE_CACHE_SIZE) out = size; memset(outbuffer, 0x00, out); } else { if (opt_verbose > 1) { printf(" uncompressing block at %ld to %ld (%ld)\n", curr, next, next - curr); } out = uncompress_block(romfs_read(curr), next - curr); } if (size >= PAGE_CACHE_SIZE) { if (out != PAGE_CACHE_SIZE) { die(FSCK_UNCORRECTED, 0, "non-block (%ld) bytes", out); } } else { if (out != size) { die(FSCK_UNCORRECTED, 0, "non-size (%ld vs %ld) bytes", out, size); } } size -= out; if (opt_extract) { if (write(fd, outbuffer, out) < 0) { die(FSCK_ERROR, 1, "write failed: %s", path); } } curr = next; } while (size);}static void change_file_status(char *path, struct cramfs_inode *i){ struct utimbuf epoch = { 0, 0 }; if (euid == 0) { if (lchown(path, i->uid, i->gid) < 0) { die(FSCK_ERROR, 1, "lchown failed: %s", path); } if (S_ISLNK(i->mode)) return; if ((S_ISUID | S_ISGID) & i->mode) { if (chmod(path, i->mode) < 0) { die(FSCK_ERROR, 1, "chown failed: %s", path); } } } if (S_ISLNK(i->mode)) return; if (utime(path, &epoch) < 0) { die(FSCK_ERROR, 1, "utime failed: %s", path); }}static void do_directory(char *path, struct cramfs_inode *i){ int pathlen = strlen(path); int count = i->size; unsigned long offset = i->offset << 2; char *newpath = malloc(pathlen + 256); if (!newpath) { die(FSCK_ERROR, 1, "malloc failed"); } if (offset == 0 && count != 0) { die(FSCK_UNCORRECTED, 0, "directory inode has zero offset and non-zero size: %s", path); } if (offset != 0 && offset < start_dir) { start_dir = offset; } /* TODO: Do we need to check end_dir for empty case? */ memcpy(newpath, path, pathlen); newpath[pathlen] = '/'; pathlen++; if (opt_verbose) { print_node('d', i, path); } if (opt_extract) { if (mkdir(path, i->mode) < 0) { die(FSCK_ERROR, 1, "mkdir failed: %s", path); } change_file_status(path, i); } while (count > 0) { struct cramfs_inode *child = iget(offset); int size; int newlen = child->namelen << 2; size = sizeof(struct cramfs_inode) + newlen; count -= size; offset += sizeof(struct cramfs_inode); memcpy(newpath + pathlen, romfs_read(offset), newlen); newpath[pathlen + newlen] = 0; if (newlen == 0) { die(FSCK_UNCORRECTED, 0, "filename length is zero"); } if ((pathlen + newlen) - strlen(newpath) > 3) { die(FSCK_UNCORRECTED, 0, "bad filename length"); } expand_fs(newpath, child); offset += newlen; if (offset <= start_dir) { die(FSCK_UNCORRECTED, 0, "bad inode offset"); } if (offset > end_dir) { end_dir = offset; } iput(child); /* free(child) */ } free(newpath);}static void do_file(char *path, struct cramfs_inode *i){ unsigned long offset = i->offset << 2; int fd = 0; if (offset == 0 && i->size != 0) { die(FSCK_UNCORRECTED, 0, "file inode has zero offset and non-zero size"); } if (i->size == 0 && offset != 0) { die(FSCK_UNCORRECTED, 0, "file inode has zero size and non-zero offset"); } if (offset != 0 && offset < start_data) { start_data = offset; } if (opt_verbose) { print_node('f', i, path); } if (opt_extract) { fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, i->mode); if (fd < 0) { die(FSCK_ERROR, 1, "open failed: %s", path); } } if (i->size) { do_uncompress(path, fd, offset, i->size); } if (opt_extract) { close(fd); change_file_status(path, i); }}static void do_symlink(char *path, struct cramfs_inode *i){ unsigned long offset = i->offset << 2; unsigned long curr = offset + 4; unsigned long next = *(u32 *) romfs_read(offset); unsigned long size; if (offset == 0) { die(FSCK_UNCORRECTED, 0, "symbolic link has zero offset"); } if (i->size == 0) { die(FSCK_UNCORRECTED, 0, "symbolic link has zero size"); } if (offset < start_data) { start_data = offset; } if (next > end_data) { end_data = next; } size = uncompress_block(romfs_read(curr), next - curr); if (size != i->size) { die(FSCK_UNCORRECTED, 0, "size error in symlink: %s", path); } outbuffer[size] = 0; if (opt_verbose) { char *str; asprintf(&str, "%s -> %s", path, outbuffer); print_node('l', i, str); if (opt_verbose > 1) { printf(" uncompressing block at %ld to %ld (%ld)\n", curr, next, next - curr); } free(str); } if (opt_extract) { if (symlink(outbuffer, path) < 0) { die(FSCK_ERROR, 1, "symlink failed: %s", path); } change_file_status(path, i); }}static void do_special_inode(char *path, struct cramfs_inode *i){ dev_t devtype = 0; char type; if (i->offset) { /* no need to shift offset */ die(FSCK_UNCORRECTED, 0, "special file has non-zero offset: %s", path); } if (S_ISCHR(i->mode)) { devtype = i->size; type = 'c'; } else if (S_ISBLK(i->mode)) { devtype = i->size; type = 'b'; } else if (S_ISFIFO(i->mode)) { if (i->size != 0) { die(FSCK_UNCORRECTED, 0, "fifo has non-zero size: %s", path); } type = 'p'; } else if (S_ISSOCK(i->mode)) { if (i->size != 0) { die(FSCK_UNCORRECTED, 0, "socket has non-zero size: %s", path); } type = 's'; } else { die(FSCK_UNCORRECTED, 0, "bogus mode: %s (%o)", path, i->mode); return; /* not reached */ } if (opt_verbose) { print_node(type, i, path); } if (opt_extract) { if (mknod(path, i->mode, devtype) < 0) { die(FSCK_ERROR, 1, "mknod failed: %s", path); } change_file_status(path, i); }}static void expand_fs(char *path, struct cramfs_inode *inode){ if (S_ISDIR(inode->mode)) { do_directory(path, inode); } else if (S_ISREG(inode->mode)) { do_file(path, inode); } else if (S_ISLNK(inode->mode)) { do_symlink(path, inode); } else { do_special_inode(path, inode); }}static void test_fs(int start){ struct cramfs_inode *root; root = read_super(); umask(0); euid = geteuid(); stream.next_in = NULL; stream.avail_in = 0; inflateInit(&stream); expand_fs(extract_dir, root); inflateEnd(&stream); if (start_data != ~0UL) { if (start_data < (sizeof(struct cramfs_super) + start)) { die(FSCK_UNCORRECTED, 0, "directory data start (%ld) < sizeof(struct cramfs_super) + start (%ld)", start_data, sizeof(struct cramfs_super) + start); } if (end_dir != start_data) { die(FSCK_UNCORRECTED, 0, "directory data end (%ld) != file data start (%ld)", end_dir, start_data); } } if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) { if (end_data > super.size) { die(FSCK_UNCORRECTED, 0, "invalid file data offset"); } } iput(root); /* free(root) */}#endif /* INCLUDE_FS_TESTS */int main(int argc, char **argv){ int c; /* for getopt */ int start = 0; size_t length; if (argc) progname = argv[0]; /* command line options */ while ((c = getopt(argc, argv, "hx:v")) != EOF) { switch (c) { case 'h': usage(FSCK_OK); case 'x':#ifdef INCLUDE_FS_TESTS opt_extract = 1; extract_dir = optarg; break;#else /* not INCLUDE_FS_TESTS */ die(FSCK_USAGE, 0, "compiled without -x support");#endif /* not INCLUDE_FS_TESTS */ case 'v': opt_verbose++; break; } } if ((argc - optind) != 1) usage(FSCK_USAGE); filename = argv[optind]; test_super(&start, &length); test_crc(start);#ifdef INCLUDE_FS_TESTS test_fs(start);#endif /* INCLUDE_FS_TESTS */ if (opt_verbose) { printf("%s: OK\n", filename); } exit(FSCK_OK);}/* * Local variables: * c-file-style: "linux" * End: */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -