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)) errx(FSCK_EX_UNCORRECTED, _("directory data start (%lu) < sizeof(struct cramfs_super) + start (%zu)"), start_data, sizeof(struct cramfs_super) + start); if (end_dir != start_data) errx(FSCK_EX_UNCORRECTED, _("directory data end (%lu) != file data start (%lu)"), end_dir, start_data); } if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) if (end_data > super.size) errx(FSCK_EX_UNCORRECTED, _("invalid file data offset")); iput(root); /* free(root) */ }
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 test_fs(int start) { struct cramfs_inode *root; unsigned long root_offset; root = cramfs_iget(&super.root); root_offset = root->offset << 2; if (!S_ISDIR(root->mode)) die(FSCK_UNCORRECTED, 0, "root inode is not directory"); if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && ((root_offset != sizeof(struct cramfs_super)) && (root_offset != PAD_SIZE + sizeof(struct cramfs_super)))) { die(FSCK_UNCORRECTED, 0, "bad root offset (%lu)", root_offset); } 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) */ }
int main(int argc, char **argv) { void *buf; size_t length; struct stat st; unsigned long crc_old, crc_new; #ifdef INCLUDE_FS_TESTS struct cramfs_inode *root; #endif /* INCLUDE_FS_TESTS */ int c; /* for getopt */ int start = 0; if (argc) progname = argv[0]; /* command line options */ while ((c = getopt(argc, argv, "hx:v")) != EOF) { switch (c) { case 'h': usage(0); case 'x': #ifdef INCLUDE_FS_TESTS opt_extract = 1; extract_dir = malloc(strlen(optarg) + 1); strcpy(extract_dir, optarg); break; #else /* not INCLUDE_FS_TESTS */ fprintf(stderr, "%s: compiled without -x support\n", progname); exit(16); #endif /* not INCLUDE_FS_TESTS */ case 'v': opt_verbose++; break; } } if ((argc - optind) != 1) usage(16); filename = argv[optind]; /* find the physical size of the file or block device */ if (lstat(filename, &st) < 0) { perror(filename); exit(8); } fd = open(filename, O_RDONLY); if (fd < 0) { perror(filename); exit(8); } if (S_ISBLK(st.st_mode)) { if (ioctl(fd, BLKGETSIZE, &length) < 0) { fprintf(stderr, "%s: warning--unable to determine filesystem size \n", filename); exit(4); } length = length * 512; } else if (S_ISREG(st.st_mode)) { length = st.st_size; } else { fprintf(stderr, "%s is not a block device or file\n", filename); exit(8); } if (length < sizeof(struct cramfs_super)) { fprintf(stderr, "%s: invalid cramfs--file length too short\n", filename); exit(4); } if (S_ISBLK(st.st_mode)) { /* nasty because mmap of block devices fails */ buf = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); read(fd, buf, length); } else { /* nice and easy */ buf = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); } /* XXX - this could be cleaner... */ if (((struct cramfs_super *) buf)->magic == CRAMFS_MAGIC) { start = 0; super = (struct cramfs_super *) buf; } else if (length >= (PAD_SIZE + sizeof(struct cramfs_super)) && ((((struct cramfs_super *) (buf + PAD_SIZE))->magic == CRAMFS_MAGIC))) { start = PAD_SIZE; super = (struct cramfs_super *) (buf + PAD_SIZE); } else { fprintf(stderr, "%s: invalid cramfs--wrong magic\n", filename); exit(4); } if (super->flags & CRAMFS_FLAG_FSID_VERSION_2) { /* length test */ if (length < super->size) { fprintf(stderr, "%s: invalid cramfs--file length too short\n", filename); exit(4); } else if (length > super->size) { fprintf(stderr, "%s: warning--file length too long, padded image?\n", filename); } /* CRC test */ crc_old = super->fsid.crc; super->fsid.crc = crc32(0L, Z_NULL, 0); crc_new = crc32(0L, Z_NULL, 0); crc_new = crc32(crc_new, (unsigned char *) buf+start, super->size - start); if (crc_new != crc_old) { fprintf(stderr, "%s: invalid cramfs--crc error\n", filename); exit(4); } } else { fprintf(stderr, "%s: warning--old cramfs image, no CRC\n", filename); } #ifdef INCLUDE_FS_TESTS super = (struct cramfs_super *) malloc(sizeof(struct cramfs_super)); if (((struct cramfs_super *) buf)->magic == CRAMFS_MAGIC) { memcpy(super, buf, sizeof(struct cramfs_super)); } else if (length >= (PAD_SIZE + sizeof(struct cramfs_super)) && ((((struct cramfs_super *) (buf + PAD_SIZE))->magic == CRAMFS_MAGIC))) { memcpy(super, (buf + PAD_SIZE), sizeof(struct cramfs_super)); } munmap(buf, length); /* file format test, uses fake "blocked" accesses */ root = read_super(); umask(0); euid = geteuid(); if (!root) { fprintf(stderr, "%s: invalid cramfs--bad superblock\n", filename); exit(4); } stream.next_in = NULL; stream.avail_in = 0; inflateInit(&stream); if (!extract_dir) { extract_dir = "root"; } expand_fs(strlen(extract_dir), extract_dir, root); inflateEnd(&stream); if (start_data != 1 << 28 && end_inode != start_data) { fprintf(stderr, "%s: invalid cramfs--directory data end (%ld) != file data start (%ld)\n", filename, end_inode, start_data); exit(4); } if (super->flags & CRAMFS_FLAG_FSID_VERSION_2) { if (end_data > super->size) { fprintf(stderr, "%s: invalid cramfs--invalid file data offset\n", filename); exit(4); } } #endif /* INCLUDE_FS_TESTS */ exit(0); }
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; } }
int main(int argc, char *argv[]) { char * bytes_count_str = NULL; char * devname; reiserfs_filsys_t fs; struct reiserfs_super_block * rs; int c; int error; struct reiserfs_super_block *sb_old; unsigned long block_count_new; print_banner ("resize_reiserfs"); while ((c = getopt(argc, argv, "fvcqs:")) != EOF) { switch (c) { case 's' : if (!optarg) die("%s: Missing argument to -s option", argv[0]); bytes_count_str = optarg; break; case 'f': opt_force = 1; break; case 'v': opt_verbose++; break; case 'n': /* no nowrite option at this moment */ /* opt_nowrite = 1; */ break; case 'c': opt_safe = 1; break; case 'q': opt_verbose = 0; break; default: print_usage_and_exit (); } } if (optind == argc ) print_usage_and_exit(); devname = argv[optind]; fs = reiserfs_open(devname, O_RDONLY, &error, 0); if (!fs) die ("%s: can not open '%s': %s", argv[0], devname, strerror(error)); if (no_reiserfs_found (fs)) { die ("resize_reiserfs: no reiserfs found on the device"); } if (!spread_bitmaps (fs)) { die ("resize_reiserfs: cannot resize reiserfs in old (not spread bitmap) format.\n"); } rs = fs->s_rs; if(bytes_count_str) { /* new fs size is specified by user */ block_count_new = calc_new_fs_size(rs_block_count(rs), fs->s_blocksize, bytes_count_str); } else { /* use whole device */ block_count_new = count_blocks(devname, fs->s_blocksize, -1); } if (is_mounted (devname)) { reiserfs_close(fs); return resize_fs_online(devname, block_count_new); } if (rs_state(rs) != REISERFS_VALID_FS) die ("%s: the file system isn't in valid state\n", argv[0]); if(!valid_offset(fs->s_dev, (loff_t) block_count_new * fs->s_blocksize - 1)) die ("%s: %s too small", argv[0], devname); sb_old = 0; /* Needed to keep idiot compiler from issuing false warning */ /* save SB for reporting */ if(opt_verbose) { sb_old = getmem(SB_SIZE); memcpy(sb_old, SB_DISK_SUPER_BLOCK(fs), SB_SIZE); } if (block_count_new == SB_BLOCK_COUNT(fs)) die ("%s: Calculated fs size is the same as the previous one.", argv[0]); if (block_count_new > SB_BLOCK_COUNT(fs)) expand_fs(fs, block_count_new); else shrink_fs(fs, block_count_new); if(opt_verbose) { sb_report(rs, sb_old); freemem(sb_old); } set_state (rs, REISERFS_VALID_FS); bwrite_cond(SB_BUFFER_WITH_SB(fs)); if (opt_verbose) { printf("\nSyncing.."); fflush(stdout); } reiserfs_close (fs); if (opt_verbose) printf("done\n"); return 0; }
int main(int argc, char *argv[]) { char * bytes_count_str = NULL; char * devname; struct stat statbuf; int c; int dev; struct reiserfs_super_block *sb, *sb_old; while ((c = getopt(argc, argv, "fvcqs:")) != EOF) { switch (c) { case 's' : if (!optarg) die("%s: Missing argument to -s option", argv[0]); bytes_count_str = optarg; break; case 'f': opt_force = 1; break; case 'v': opt_verbose++; break; case 'n': /* no nowrite option at this moment */ /* opt_nowrite = 1; */ break; case 'c': opt_safe = 1; break; case 'q': opt_verbose = 0; break; default: print_usage_and_exit (); } } if (optind == argc || (!bytes_count_str)) print_usage_and_exit(); devname = argv[optind]; /* open_device will die if it could not open device */ dev = open (devname, O_RDWR); if (dev == -1) die ("%s: can not open '%s': %s", argv[0], devname, strerror (errno)); if (fstat (dev, &statbuf) < 0) die ("%s: unable to stat %s", argv[0], devname); if (!S_ISBLK (statbuf.st_mode) && opt_force ) die ("%s: '%s (%o)' is not a block device", argv[0], devname, statbuf.st_mode); read_superblock(dev); sb = (struct reiserfs_super_block *) g_sb_bh->b_data; g_block_count_new = calc_new_fs_size(sb->s_block_count, sb->s_blocksize, bytes_count_str); if (is_mounted (devname)) { close(dev); if (!opt_force) die ("%s: '%s' contains a mounted file system,\n" "\tspecify -f option to resize the fs online\n", argv[0], devname); resize_fs_online(devname, g_block_count_new); return 0; } if (sb->s_state != REISERFS_VALID_FS) die ("%s: the file system isn't in valid state\n", argv[0]); if(!valid_offset(dev, (loff_t) g_block_count_new * sb->s_blocksize - 1)) die ("%s: %s too small", argv[0], devname); sb_old = 0; /* Needed to keep idiot compiler from issuing false warning */ /* save SB for reporting */ if(opt_verbose) { sb_old = getmem(sizeof(struct reiserfs_super_block)); memcpy(sb_old, sb, sizeof(struct reiserfs_super_block)); } if (g_block_count_new == sb->s_block_count) die ("%s: Calculated fs size is the same as the previous one.", argv[0]); if (g_block_count_new > sb->s_block_count) expand_fs(); else shrink_fs(g_block_count_new); if(opt_verbose) { sb_report(sb, sb_old); freemem(sb_old); } check_and_free_mem (); if (opt_verbose) { printf("\nSyncing.."); fflush(stdout); } fsync (dev); if (opt_verbose) printf("done\n"); close(dev); return 0; }