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

📄 cramfsck.c

📁 制作cramfs文件系统的工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * cramfsck - check a cramfs file system * * Copyright (C) 2000-2002 Transmeta Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * 1999/12/03: Linus Torvalds (cramfs tester and unarchive program) * 2000/06/03: Daniel Quinlan (CRC and length checking program) * 2000/06/04: Daniel Quinlan (merged programs, added options, support *                            for special files, preserve permissions and *                            ownership, cramfs superblock v2, bogus mode *                            test, pathname length test, etc.) * 2000/06/06: Daniel Quinlan (support for holes, pretty-printing, *                            symlink size test) * 2000/07/11: Daniel Quinlan (file length tests, start at offset 0 or 512, *                            fsck-compatible exit codes) * 2000/07/15: Daniel Quinlan (initial support for block devices) * 2002/01/10: Daniel Quinlan (additional checks, test more return codes, *                            use read if mmap fails, standardize messages) *//* compile-time options */#define INCLUDE_FS_TESTS	/* include cramfs checking and extraction */#define _GNU_SOURCE#include <sys/types.h>#include <stdio.h>#include <stdarg.h>#include <sys/stat.h>#include <unistd.h>#include <sys/mman.h>#include <fcntl.h>#include <dirent.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <sys/sysmacros.h>#include <utime.h>#include <sys/ioctl.h>#define _LINUX_STRING_H_#include <linux/fs.h>#include <linux/cramfs_fs.h>#include <zlib.h>/* Exit codes used by fsck-type programs */#define FSCK_OK          0	/* No errors */#define FSCK_NONDESTRUCT 1	/* File system errors corrected */#define FSCK_REBOOT      2	/* System should be rebooted */#define FSCK_UNCORRECTED 4	/* File system errors left uncorrected */#define FSCK_ERROR       8	/* Operational error */#define FSCK_USAGE       16	/* Usage or syntax error */#define FSCK_LIBRARY     128	/* Shared library error */#define PAD_SIZE 512#define PAGE_CACHE_SIZE (4096)static const char *progname = "cramfsck";static int fd;			/* ROM image file descriptor */static char *filename;		/* ROM image filename */struct cramfs_super super;	/* just find the cramfs superblock once */static int opt_verbose = 0;	/* 1 = verbose (-v), 2+ = very verbose (-vv) */#ifdef INCLUDE_FS_TESTSstatic int opt_extract = 0;		/* extract cramfs (-x) */static char *extract_dir = "root";	/* extraction directory (-x) */static uid_t euid;			/* effective UID *//* (cramfs_super + start) <= start_dir < end_dir <= start_data <= end_data */static unsigned long start_dir = ~0UL;	/* start of first non-root inode */static unsigned long end_dir = 0;	/* end of the directory structure */static unsigned long start_data = ~0UL;	/* start of the data (256 MB = max) */static unsigned long end_data = 0;	/* end of the data *//* Guarantee access to at least 8kB at a time */#define ROMBUFFER_BITS	13#define ROMBUFFERSIZE	(1 << ROMBUFFER_BITS)#define ROMBUFFERMASK	(ROMBUFFERSIZE-1)static char read_buffer[ROMBUFFERSIZE * 2];static unsigned long read_buffer_block = ~0UL;/* Uncompressing data structures... */static char outbuffer[PAGE_CACHE_SIZE*2];static z_stream stream;/* Prototypes */static void expand_fs(char *, struct cramfs_inode *);#endif /* INCLUDE_FS_TESTS *//* Input status of 0 to print help and exit without an error. */static void usage(int status){	FILE *stream = status ? stderr : stdout;	fprintf(stream, "usage: %s [-hv] [-x dir] file\n"		" -h         print this help\n"		" -x dir     extract into dir\n"		" -v         be more verbose\n"		" file       file to test\n", progname);	exit(status);}static void die(int status, int syserr, const char *fmt, ...){	va_list arg_ptr;	int save = errno;	fflush(0);	va_start(arg_ptr, fmt);	fprintf(stderr, "%s: ", progname);	vfprintf(stderr, fmt, arg_ptr);	if (syserr) {		fprintf(stderr, ": %s", strerror(save));	}	fprintf(stderr, "\n");	va_end(arg_ptr);	exit(status);}static void test_super(int *start, size_t *length) {	struct stat st;	/* find the physical size of the file or block device */	if (stat(filename, &st) < 0) {		die(FSCK_ERROR, 1, "stat failed: %s", filename);	}	fd = open(filename, O_RDONLY);	if (fd < 0) {		die(FSCK_ERROR, 1, "open failed: %s", filename);	}	if (S_ISBLK(st.st_mode)) {		if (ioctl(fd, BLKGETSIZE, length) < 0) {			die(FSCK_ERROR, 1, "ioctl failed: unable to determine device size: %s", filename);		}		*length = *length * 512;	}	else if (S_ISREG(st.st_mode)) {		*length = st.st_size;	}	else {		die(FSCK_ERROR, 0, "not a block device or file: %s", filename);	}	if (*length < sizeof(struct cramfs_super)) {		die(FSCK_UNCORRECTED, 0, "file length too short");	}	/* find superblock */	if (read(fd, &super, sizeof(super)) != sizeof(super)) {		die(FSCK_ERROR, 1, "read failed: %s", filename);	}	if (super.magic == CRAMFS_MAGIC) {		*start = 0;	}	else if (*length >= (PAD_SIZE + sizeof(super))) {		lseek(fd, PAD_SIZE, SEEK_SET);		if (read(fd, &super, sizeof(super)) != sizeof(super)) {			die(FSCK_ERROR, 1, "read failed: %s", filename);		}		if (super.magic == CRAMFS_MAGIC) {			*start = PAD_SIZE;		}	}	/* superblock tests */	if (super.magic != CRAMFS_MAGIC) {		die(FSCK_UNCORRECTED, 0, "superblock magic not found");	}	if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) {		die(FSCK_ERROR, 0, "unsupported filesystem features");	}	if (super.size < PAGE_CACHE_SIZE) {		die(FSCK_UNCORRECTED, 0, "superblock size (%d) too small", super.size);	}	if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) {		if (super.fsid.files == 0) {			die(FSCK_UNCORRECTED, 0, "zero file count");		}		if (*length < super.size) {			die(FSCK_UNCORRECTED, 0, "file length too short");		}		else if (*length > super.size) {			fprintf(stderr, "warning: file extends past end of filesystem\n");		}	}	else {		fprintf(stderr, "warning: old cramfs format\n");	}}static void test_crc(int start){	void *buf;	u32 crc;	if (!(super.flags & CRAMFS_FLAG_FSID_VERSION_2)) {#ifdef INCLUDE_FS_TESTS		return;#else /* not INCLUDE_FS_TESTS */		die(FSCK_USAGE, 0, "unable to test CRC: old cramfs format");#endif /* not INCLUDE_FS_TESTS */	}	crc = crc32(0L, Z_NULL, 0);	buf = mmap(NULL, super.size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);	if (buf == MAP_FAILED) {		buf = mmap(NULL, super.size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);		if (buf != MAP_FAILED) {			lseek(fd, 0, SEEK_SET);			read(fd, buf, super.size);		}	}	if (buf != MAP_FAILED) {		((struct cramfs_super *) (buf+start))->fsid.crc = crc32(0L, Z_NULL, 0);		crc = crc32(crc, buf+start, super.size-start);		munmap(buf, super.size);	}	else {		int retval;		size_t length = 0;		buf = malloc(4096);		if (!buf) {			die(FSCK_ERROR, 1, "malloc failed");		}		lseek(fd, start, SEEK_SET);		for (;;) {			retval = read(fd, buf, 4096);			if (retval < 0) {				die(FSCK_ERROR, 1, "read failed: %s", filename);			}			else if (retval == 0) {				break;			}			if (length == 0) {				((struct cramfs_super *) buf)->fsid.crc = crc32(0L, Z_NULL, 0);			}			length += retval;			if (length > (super.size-start)) {				crc = crc32(crc, buf, retval - (length - (super.size-start)));				break;			}			crc = crc32(crc, buf, retval);		}		free(buf);	}	if (crc != super.fsid.crc) {		die(FSCK_UNCORRECTED, 0, "crc error");	}}#ifdef INCLUDE_FS_TESTSstatic void print_node(char type, struct cramfs_inode *i, char *name){	char info[10];	if (S_ISCHR(i->mode) || (S_ISBLK(i->mode))) {		/* major/minor numbers can be as high as 2^12 or 4096 */		snprintf(info, 10, "%4d,%4d", major(i->size), minor(i->size));	}	else {		/* size be as high as 2^24 or 16777216 */		snprintf(info, 10, "%9d", i->size);	}	printf("%c %04o %s %5d:%-3d %s\n",	       type, i->mode & ~S_IFMT, info, i->uid, i->gid, name);}/* * Create a fake "blocked" access */static void *romfs_read(unsigned long offset){	unsigned int block = offset >> ROMBUFFER_BITS;	if (block != read_buffer_block) {		read_buffer_block = block;		lseek(fd, block << ROMBUFFER_BITS, SEEK_SET);		read(fd, read_buffer, ROMBUFFERSIZE * 2);	}	return read_buffer + (offset & ROMBUFFERMASK);}static struct cramfs_inode *cramfs_iget(struct cramfs_inode * i){	struct cramfs_inode *inode = malloc(sizeof(struct cramfs_inode));	if (!inode) {		die(FSCK_ERROR, 1, "malloc failed");	}	*inode = *i;	return inode;}static struct cramfs_inode *iget(unsigned int ino){	return cramfs_iget(romfs_read(ino));}static void iput(struct cramfs_inode *inode){	free(inode);}/* * Return the offset of the root directory */static struct cramfs_inode *read_super(void){	unsigned long offset = super.root.offset << 2;	if (!S_ISDIR(super.root.mode))		die(FSCK_UNCORRECTED, 0, "root inode is not directory");	if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) &&	    ((offset != sizeof(struct cramfs_super)) &&	     (offset != PAD_SIZE + sizeof(struct cramfs_super))))	{		die(FSCK_UNCORRECTED, 0, "bad root offset (%lu)", offset);	}	return cramfs_iget(&super.root);}static int uncompress_block(void *src, int len){	int err;	stream.next_in = src;	stream.avail_in = len;	stream.next_out = (unsigned char *) outbuffer;	stream.avail_out = PAGE_CACHE_SIZE*2;	inflateReset(&stream);	if (len > PAGE_CACHE_SIZE*2) {		die(FSCK_UNCORRECTED, 0, "data block too large");	}	err = inflate(&stream, Z_FINISH);	if (err != Z_STREAM_END) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -