⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cramfsck.c

📁 制作cramfs文件系统的工具
💻 C
📖 第 1 页 / 共 2 页
字号:
		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 + -