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) errx(FSCK_EX_UNCORRECTED, _("file inode has zero offset and non-zero size")); if (i->size == 0 && offset != 0) errx(FSCK_EX_UNCORRECTED, _("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 (*extract_dir != '\0') { fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, i->mode); if (fd < 0) err(FSCK_EX_ERROR, _("cannot open %s"), path); } if (i->size) do_uncompress(path, fd, offset, i->size); if ( *extract_dir != '\0') { if (close_fd(fd) != 0) err(FSCK_EX_ERROR, _("write failed: %s"), path); change_file_status(path, i); } }
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_special_inode(char *path, struct cramfs_inode *i) { dev_t devtype = 0; char type; 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)) type = 'p'; else if (S_ISSOCK(i->mode)) type = 's'; else { fprintf(stderr, "%s: bogus mode on `%s' (%o)\n", filename, path, i->mode); exit(4); } if (opt_verbose) { print_node(type, i, path); } if (opt_extract) { if (mknod(path, i->mode, devtype) < 0) { perror(path); exit(8); } change_file_status(path, i); } }
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 = xmalloc(pathlen + 256); if (offset == 0 && count != 0) errx(FSCK_EX_UNCORRECTED, _("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 (*extract_dir != '\0') { if (mkdir(path, i->mode) < 0) err(FSCK_EX_ERROR, _("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) errx(FSCK_EX_UNCORRECTED, _("filename length is zero")); if ((pathlen + newlen) - strlen(newpath) > 3) errx(FSCK_EX_UNCORRECTED, _("bad filename length")); expand_fs(newpath, child); offset += newlen; if (offset <= start_dir) errx(FSCK_EX_UNCORRECTED, _("bad inode offset")); if (offset > end_dir) end_dir = offset; iput(child); /* free(child) */ } free(newpath); }
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 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 */ errx(FSCK_EX_UNCORRECTED, _("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) errx(FSCK_EX_UNCORRECTED, _("fifo has non-zero size: %s"), path); type = 'p'; } else if (S_ISSOCK(i->mode)) { if (i->size != 0) errx(FSCK_EX_UNCORRECTED, _("socket has non-zero size: %s"), path); type = 's'; } else { errx(FSCK_EX_UNCORRECTED, _("bogus mode: %s (%o)"), path, i->mode); return; /* not reached */ } if (opt_verbose) print_node(type, i, path); if (*extract_dir != '\0') { if (mknod(path, i->mode, devtype) < 0) err(FSCK_EX_ERROR, _("mknod failed: %s"), path); 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_toggle_endianness(cramfs_is_big_endian, *(uint32_t *) romfs_read(offset)); unsigned long size; if (offset == 0) errx(FSCK_EX_UNCORRECTED, _("symbolic link has zero offset")); if (i->size == 0) errx(FSCK_EX_UNCORRECTED, _("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) errx(FSCK_EX_UNCORRECTED, _("size error in symlink: %s"), path); outbuffer[size] = 0; if (opt_verbose) { char *str; xasprintf(&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 (*extract_dir != '\0') { if (symlink(outbuffer, path) < 0) err(FSCK_EX_ERROR, _("symlink failed: %s"), path); 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 = *(unsigned long *) romfs_read(offset); unsigned long size; if (next > end_data) { end_data = next; } size = uncompress_block(romfs_read(curr), next - curr); if (size != i->size) { fprintf(stderr, "%s: size error in symlink `%s'\n", filename, path); exit(4); } outbuffer[size] = 0; if (opt_verbose) { char *str; str = malloc(strlen(outbuffer) + strlen(path) + 5); strcpy(str, path); strncat(str, " -> ", 4); strncat(str, outbuffer, size); print_node('l', i, str); if (opt_verbose > 1) { printf(" uncompressing block at %ld to %ld (%ld)\n", curr, next, next - curr); } } if (opt_extract) { symlink(outbuffer, path); change_file_status(path, i); } }
static void expand_fs(int pathlen, char *path, struct cramfs_inode *inode) { if (S_ISDIR(inode->mode)) { int count = inode->size; unsigned long offset = inode->offset << 2; char *newpath = malloc(pathlen + 256); if (count > 0 && offset < start_inode) { start_inode = offset; } /* XXX - need to check end_inode for empty case? */ memcpy(newpath, path, pathlen); newpath[pathlen] = '/'; pathlen++; if (opt_verbose) { print_node('d', inode, path); } if (opt_extract) { mkdir(path, inode->mode); change_file_status(path, inode); } 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 ((pathlen + newlen) - strlen(newpath) > 3) { fprintf(stderr, "%s: invalid cramfs--bad path length\n", filename); exit(4); } expand_fs(strlen(newpath), newpath, child); offset += newlen; if (offset > end_inode) { end_inode = offset; } } return; } if (S_ISREG(inode->mode)) { int fd = 0; unsigned long offset = inode->offset << 2; if (offset > 0 && offset < start_data) { start_data = offset; } if (opt_verbose) { print_node('f', inode, path); } if (opt_extract) { fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, inode->mode); } if (inode->size) { do_uncompress(fd, offset, inode->size); } if (opt_extract) { close(fd); change_file_status(path, inode); } return; } if (S_ISLNK(inode->mode)) { unsigned long offset = inode->offset << 2; if (offset < start_data) { start_data = offset; } do_symlink(path, inode); return; } else { do_special_inode(path, inode); return; } }