Beispiel #1
0
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);
	}
}
Beispiel #2
0
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);
	}
}
Beispiel #3
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;
	}
}
Beispiel #4
0
int main(int argc, char **argv)
{
	int errors = 0;
	int verbose = 0;
	char *prog_name = argv[0];

	two_pass = 1;

	++argv; --argc;
	if (argc != 2)
	{
		usage(prog_name);
		return 1;
	}

	FILE *fd = fopen(argv[0], "r");
	if (!fd)
	{
		perror(argv[0]);
		return 1;
	}

	while (1)
	{
		union jffs2_node_union node;
		int off = ftell(fd);
		if (fread(&node, 1, sizeof(node), fd) != sizeof(node))
			break;

		if (node.u.magic == KSAMTIB_CIGAM_2SFFJ)
		{
			fprintf(stderr, "ERROR: reverse endianess detected!\n");
			break;
		}
		if (node.u.magic == 0xFFFF)
		{
			if (verbose)
				printf("%08x: empty marker - going to next eraseblock\n", off);
			if (fseek(fd, (off + ES + 1) & ~ES , SEEK_SET) < 0)
				break;
			continue;
		}
		if (verbose)
			printf("at %08x: %04x | %04x (%lu bytes): ", off, node.u.magic, node.u.nodetype, node.u.totlen);

		if (crc32_no_comp(0, (unsigned char*)&node, sizeof(node.u) - 4) != node.u.hdr_crc)
		{
			++errors;
			printf(" ** wrong crc **\n");
		}

		switch (node.u.nodetype)
		{
		case JFFS2_NODETYPE_DIRENT:
		{
			fseek(fd, off + sizeof(struct jffs2_raw_dirent), SEEK_SET);
			char name[node.d.nsize + 1];
			fread(name, node.d.nsize, 1, fd);
			name[node.d.nsize] = 0;
			if (verbose)
				printf("DIRENT, ino %lu (%s), parent=%lu\n", node.d.ino, name, node.d.pino);

			inodes[node.d.ino] = name;
			node_type[node.d.ino] = node.d.type;
			childs[node.d.pino].push_back(node.d.ino);
			break;
		}
		case JFFS2_NODETYPE_INODE:
		{
			if (verbose)
				printf("\n");
			if (crc32_no_comp(0, (unsigned char*)&node.i, sizeof(struct jffs2_raw_inode) - 8) != node.i.node_crc)
			{
				errors++;
				printf("  ** wrong node crc **\n");
			}
			if (verbose)
			{
				printf("  INODE, ino %lu (version %lu) at %08lx\n", node.i.ino, node.i.version, node.i.offset);
				printf("  compression: %d, user compression requested: %d\n", node.i.compr, node.i.usercompr);
			}
			int compr_size = node.i.csize;
			int uncompr_size = node.i.dsize;
			if (verbose)
				printf("  compr_size: %d, uncompr_size: %d\n", compr_size, uncompr_size);
			unsigned char compr[compr_size], uncomp[uncompr_size];
			off_t whence = ftello(fd);
			fread(compr, compr_size, 1, fd);
			if (crc32_no_comp(0, compr, compr_size) != node.i.data_crc)
			{
				errors++;
				printf("  ** wrong data crc **\n");
			} else
			{
				if (verbose)
					printf("  data crc ok\n");
				if (!two_pass) {
					if (do_uncompress(uncomp, uncompr_size, compr, compr_size, node.i.compr) != uncompr_size)
					{
						errors++;
						printf("  ** data uncompress failed!\n");
					} else
					{
						nodedata[node.i.ino][node.i.version] = nodedata_s(uncomp,
							uncompr_size, node.i.offset, node.i.isize,
							node.i.gid, node.i.uid, node.i.mode);
					}
				} else
				{
					nodedata[node.i.ino][node.i.version] = nodedata_s(fd, whence, uncompr_size, node.i.compr,
						uncompr_size, node.i.offset, node.i.isize,
						node.i.gid, node.i.uid, node.i.mode);
				}
			}
			break;
		}
		case JFFS2_NODETYPE_CLEANMARKER:
			if (verbose)
	 			printf("CLEANMARKER\n");
			break;
		case JFFS2_NODETYPE_PADDING:
			if (verbose)
				printf("PADDING\n");
			break;
		default:
			errors++;
			printf(" ** INVALID ** - nodetype %04x\n", node.u.nodetype);
		}

		if (node.u.totlen)
			fseek(fd, (off + node.u.totlen + 3) &~3 , SEEK_SET);
		else
		{
			errors++;
			printf(" ** INVALID NODE SIZE. skipping to next eraseblock\n");
			fseek(fd, (off + ES + 1) & ~ES , SEEK_SET);
		}
	}

	if (errors)
	{
		if (!inodes.empty())
			printf("there were errors, but some valid stuff was detected. continuing.\n");
		else
		{
			fprintf(stderr, "errors present and no valid data.\n");
			return 2;
		}
	}
	node_type[1] = DT_DIR;
	prefix = argv[1];
	do_list(1);

	return 0;
}
Beispiel #5
0
void do_list(int inode, std::string root="")
{
	std::string pathname = prefix + root + inodes[inode];

	std::map<int, struct nodedata_s> &data = nodedata[inode];

	int max_size = 0, gid = 0, uid = 0, mode = 0755;
	if (!data.empty())
	{
		std::map<int, struct nodedata_s>::iterator last = data.end();
		--last;
		max_size = last->second.isize;
		mode = last->second.mode;
		gid = last->second.gid;
		uid = last->second.uid;
	}

	if ((node_type[inode] == DT_BLK) || (node_type[inode] == DT_CHR))
		max_size = 2;

	unsigned char *merged_data = (unsigned char*)calloc(1, max_size + 1);
	int major = 0, minor = 0;

	for (std::map<int, struct nodedata_s>::iterator i(data.begin()); i != data.end(); ++i)
	{
		int size = i->second.size;
		int offset = i->second.offset;
		if (offset + size > max_size)
			size = max_size - offset;
		if (size > 0)
		{
			if (!i->second.data)
			{
				unsigned char compr[i->second.size], uncomp[i->second.uncompr_size];
				fseeko(i->second.f, i->second.foffset, SEEK_SET);
				fread(compr, i->second.size, 1, i->second.f);
				if (do_uncompress(uncomp, i->second.uncompr_size, compr, i->second.size, i->second.compr) != i->second.uncompr_size)
						fprintf(stderr, "  ** data uncompress failed!\n");
				else
					memcpy(merged_data + i->second.offset, uncomp, i->second.size);
			} else
				memcpy(merged_data + i->second.offset, i->second.data, i->second.size);
		}
	}

	switch (node_type[inode])
	{
	case DT_DIR:
		if (mkdir(pathname.c_str(), mode & 0777))
			perror(pathname.c_str());
		break;

	case DT_REG:
	{
		FILE *f = fopen(pathname.c_str(), "wb");
		if (!f)
			perror(pathname.c_str());
		else
		{
			fwrite(merged_data, max_size, 1, f);
			fclose(f);
		}
		break;
	}
	case DT_LNK:
	{
		symlink((char*)merged_data, pathname.c_str());
		break;
	}
	case DT_CHR:
	case DT_BLK:
	{
		major = merged_data[1];
		minor = merged_data[0];
		if (mknod(pathname.c_str(), ((node_type[inode] == DT_BLK) ? S_IFBLK : S_IFCHR) | (mode & 07777), makedev(major, minor)))
		{
			if (!whine++)
				perror("mknod");
		}
		break;
	}
	case DT_UNKNOWN:
	case DT_FIFO:
	case DT_SOCK:
	case DT_WHT:
		printf("unhandled inode type!\n");
		break;
	}

	free(merged_data);

	if (node_type[inode] != DT_LNK)
	{
		if (chmod(pathname.c_str(), mode))
			if (!whine++)
				perror("chmod");

		if (chown(pathname.c_str(), uid, gid))
			if (!whine++)
				perror("chown");
	}
//	printf("%s (%d)\n", pathname.c_str(), max_size);
	std::list<int> &child = childs[inode];
	for (std::list<int>::iterator i(child.begin()); i != child.end(); ++i)
		do_list(*i, root + inodes[inode].c_str() + "/");
}
Beispiel #6
0
int
compress_filter( void *opaque, int control,
		 IOBUF a, byte *buf, size_t *ret_len)
{
    size_t size = *ret_len;
    compress_filter_context_t *zfx = opaque;
    z_stream *zs = zfx->opaque;
    int rc=0;

    if( control == IOBUFCTRL_UNDERFLOW ) {
	if( !zfx->status ) {
	    zs = zfx->opaque = m_alloc_clear( sizeof *zs );
	    init_uncompress( zfx, zs );
	    zfx->status = 1;
	}

#ifndef __riscos__
	zs->next_out = buf;
#else /* __riscos__ */
	zs->next_out = (Bytef *) buf;
#endif /* __riscos__ */
	zs->avail_out = size;
	zfx->outbufsize = size; /* needed only for calculation */
	rc = do_uncompress( zfx, zs, a, ret_len );
    }
    else if( control == IOBUFCTRL_FLUSH ) {
	if( !zfx->status ) {
	    PACKET pkt;
	    PKT_compressed cd;

	    if( !zfx->algo )
	        zfx->algo = DEFAULT_COMPRESS_ALGO;
	    if( zfx->algo != 1 && zfx->algo != 2 )
	      BUG();
	    memset( &cd, 0, sizeof cd );
	    cd.len = 0;
	    cd.algorithm = zfx->algo;
	    init_packet( &pkt );
	    pkt.pkttype = PKT_COMPRESSED;
	    pkt.pkt.compressed = &cd;
	    if( build_packet( a, &pkt ))
		log_bug("build_packet(PKT_COMPRESSED) failed\n");
	    zs = zfx->opaque = m_alloc_clear( sizeof *zs );
	    init_compress( zfx, zs );
	    zfx->status = 2;
	}

#ifndef __riscos__
	zs->next_in = buf;
#else /* __riscos__ */
	zs->next_in = (Bytef *) buf;
#endif /* __riscos__ */
	zs->avail_in = size;
	rc = do_compress( zfx, zs, Z_NO_FLUSH, a );
    }
    else if( control == IOBUFCTRL_FREE ) {
	if( zfx->status == 1 ) {
	    inflateEnd(zs);
	    m_free(zs);
	    zfx->opaque = NULL;
	    m_free(zfx->outbuf); zfx->outbuf = NULL;
	}
	else if( zfx->status == 2 ) {
#ifndef __riscos__
	    zs->next_in = buf;
#else /* __riscos__ */
	    zs->next_in = (Bytef *) buf;
#endif /* __riscos__ */
	    zs->avail_in = 0;
	    do_compress( zfx, zs, Z_FINISH, a );
	    deflateEnd(zs);
	    m_free(zs);
	    zfx->opaque = NULL;
	    m_free(zfx->outbuf); zfx->outbuf = NULL;
	}
        if (zfx->release)
          zfx->release (zfx);
    }
    else if( control == IOBUFCTRL_DESC )
	*(char**)buf = "compress_filter";
    return rc;
}
Beispiel #7
0
int
compress_filter_bz2( void *opaque, int control,
		     IOBUF a, byte *buf, size_t *ret_len)
{
  size_t size = *ret_len;
  compress_filter_context_t *zfx = opaque;
  bz_stream *bzs = zfx->opaque;
  int rc=0;

  if( control == IOBUFCTRL_UNDERFLOW )
    {
      if( !zfx->status )
	{
	  bzs = zfx->opaque = xmalloc_clear( sizeof *bzs );
	  init_uncompress( zfx, bzs );
	  zfx->status = 1;
	}

      bzs->next_out = buf;
      bzs->avail_out = size;
      zfx->outbufsize = size; /* needed only for calculation */
      rc = do_uncompress( zfx, bzs, a, ret_len );
    }
  else if( control == IOBUFCTRL_FLUSH )
    {
      if( !zfx->status )
	{
	  PACKET pkt;
	  PKT_compressed cd;

	  if( zfx->algo != COMPRESS_ALGO_BZIP2 )
	    BUG();
	  memset( &cd, 0, sizeof cd );
	  cd.len = 0;
	  cd.algorithm = zfx->algo;
	  init_packet( &pkt );
	  pkt.pkttype = PKT_COMPRESSED;
	  pkt.pkt.compressed = &cd;
/*	  if( build_packet( a, &pkt ))
	    log_bug("build_packet(PKT_COMPRESSED) failed\n"); */ //FIXME
	  bzs = zfx->opaque = xmalloc_clear( sizeof *bzs );
	  init_compress( zfx, bzs );
	  zfx->status = 2;
	}

      bzs->next_in = buf;
      bzs->avail_in = size;
      rc = do_compress( zfx, bzs, BZ_RUN, a );
    }
  else if( control == IOBUFCTRL_FREE )
    {
      if( zfx->status == 1 )
	{
	  BZ2_bzDecompressEnd(bzs);
	  xfree(bzs);
	  zfx->opaque = NULL;
	  xfree(zfx->outbuf); zfx->outbuf = NULL;
	}
      else if( zfx->status == 2 )
	{
	  bzs->next_in = buf;
	  bzs->avail_in = 0;
	  do_compress( zfx, bzs, BZ_FINISH, a );
	  BZ2_bzCompressEnd(bzs);
	  xfree(bzs);
	  zfx->opaque = NULL;
	  xfree(zfx->outbuf); zfx->outbuf = NULL;
	}
      if (zfx->release)
	zfx->release (zfx);
    }
  else if( control == IOBUFCTRL_DESC )
    *(char**)buf = "compress_filter";
  return rc;
}