Beispiel #1
0
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) */
}
Beispiel #2
0
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) */
}
Beispiel #4
0
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);
}
Beispiel #5
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;
}