Example #1
0
static int parse_tile(xmlTextReaderPtr reader, tmx_tile **tile_headadr, const char *filename) {
	tmx_tile *res = NULL;
	int curr_depth;
	const char *name;
	char *value;

	curr_depth = xmlTextReaderDepth(reader);

	if (!(res = alloc_tile())) return 0;

	while (*tile_headadr) {
		tile_headadr = &((*tile_headadr)->next);
	}
	*tile_headadr = res;

	if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"id"))) { /* id */
		res->id = atoi(value);
		tmx_free_func(value);
	}
	else {
		tmx_err(E_MISSEL, "xml parser: missing 'id' attribute in the 'tile' element");
		return 0;
	}

	do {
		if (xmlTextReaderRead(reader) != 1) return 0; /* error_handler has been called */

		if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
			name = (char*)xmlTextReaderConstName(reader);
			if (!strcmp(name, "properties")) {
				if (!parse_properties(reader, &(res->properties))) return 0;
			}
			else if (!strcmp(name, "image")) {
				if (!parse_image(reader, &(res->image), 0, filename)) return 0;
			}
			else {
				/* Unknow element, skip its tree */
				if (xmlTextReaderNext(reader) != 1) return 0;
			}
		}
	} while (xmlTextReaderNodeType(reader) != XML_READER_TYPE_END_ELEMENT ||
		xmlTextReaderDepth(reader) != curr_depth);

	return 1;
}
Example #2
0
/* parses a tileset within the tmx file or in a dedicated tsx file */
static int parse_tileset_sub(xmlTextReaderPtr reader, tmx_tileset *ts_addr, const char *filename) {
	int curr_depth;
	const char *name;
	char *value;

	curr_depth = xmlTextReaderDepth(reader);

	/* parses each attribute */
	if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"name"))) { /* name */
		ts_addr->name = value;
	} else {
		tmx_err(E_MISSEL, "xml parser: missing 'name' attribute in the 'tileset' element");
		return 0;
	}

	if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"tilewidth"))) { /* tile_width */
		ts_addr->tile_width = atoi(value);
		tmx_free_func(value);
	} else {
		tmx_err(E_MISSEL, "xml parser: missing 'tilewidth' attribute in the 'tileset' element");
		return 0;
	}

	if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"tileheight"))) { /* tile_height */
		ts_addr->tile_height = atoi(value);
		tmx_free_func(value);
	} else {
		tmx_err(E_MISSEL, "xml parser: missing 'tileheight' attribute in the 'tileset' element");
		return 0;
	}

	if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"spacing"))) { /* spacing */
		ts_addr->spacing = atoi(value);
		tmx_free_func(value);
	}

	if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"margin"))) { /* margin */
		ts_addr->margin = atoi(value);
		tmx_free_func(value);
	}

	/* Parse each child */
	do {
		if (xmlTextReaderRead(reader) != 1) return 0; /* error_handler has been called */

		if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
			name = (char*)xmlTextReaderConstName(reader);
			if (!strcmp(name, "image")) {
				if (!parse_image(reader, &(ts_addr->image), 1, filename)) return 0;
			} else if (!strcmp(name, "tileoffset")) {
				if (!parse_tileoffset(reader, &(ts_addr->x_offset), &(ts_addr->y_offset))) return 0;
			} else if (!strcmp(name, "properties")) {
				if (!parse_properties(reader, &(ts_addr->properties))) return 0;
			} else if (!strcmp(name, "tile")) {
				if (!parse_tile(reader, &(ts_addr->tiles), filename)) return 0;
			} else {
				/* Unknown element, skip its tree */
				if (xmlTextReaderNext(reader) != 1) return 0;
			}
		}
	} while (xmlTextReaderNodeType(reader) != XML_READER_TYPE_END_ELEMENT ||
	         xmlTextReaderDepth(reader) != curr_depth);

	return 1;
}
Example #3
0
/* parse layers and objectgroups */
static int parse_layer(xmlTextReaderPtr reader, tmx_layer **layer_headadr, int map_h, int map_w, enum tmx_layer_type type, const char *filename) {
	tmx_layer *res;
	tmx_object *obj;
	int curr_depth;
	const char *name;
	char *value;

	curr_depth = xmlTextReaderDepth(reader);

	if (!(res = alloc_layer())) return 0;
	res->type = type;
	while(*layer_headadr) {
		layer_headadr = &((*layer_headadr)->next);
	}
	*layer_headadr = res;

	/* parses each attribute */
	if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"name"))) { /* name */
		res->name = value;
	} else {
		tmx_err(E_MISSEL, "xml parser: missing 'name' attribute in the 'layer' element");
		return 0;
	}

	if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"visible"))) { /* visible */
		res->visible = (char)atoi(value);
		tmx_free_func(value);
	}

	if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"opacity"))) { /* opacity */
		res->opacity = (float)strtod(value, NULL);
		tmx_free_func(value);
	}

	if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"color"))) { /* color */
		res->color = get_color_rgb(value);
		tmx_free_func(value);
	}

	if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"x"))) { /* x_offset */
		res->x_offset = (int)atoi(value);
		tmx_free_func(value);
	}

	if ((value = (char*)xmlTextReaderGetAttribute(reader, (xmlChar*)"y"))) { /* y_offset */
		res->y_offset = (int)atoi(value);
		tmx_free_func(value);
	}

	do {
		if (xmlTextReaderRead(reader) != 1) return 0; /* error_handler has been called */

		if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
			name = (char*)xmlTextReaderConstName(reader);
			if (!strcmp(name, "properties")) {
				if (!parse_properties(reader, &(res->properties))) return 0;
			} else if (!strcmp(name, "data")) {
				if (!parse_data(reader, &(res->content.gids), map_h * map_w)) return 0;
			} else if (!strcmp(name, "image")) {
				if (!parse_image(reader, &(res->content.image), 0, filename)) return 0;
			} else if (!strcmp(name, "object")) {
				if (!(obj = alloc_object())) return 0;

				obj->next = res->content.head;
				res->content.head = obj;

				if (!parse_object(reader, obj)) return 0;
			} else {
				/* Unknow element, skip its tree */
				if (xmlTextReaderNext(reader) != 1) return 0;
			}
		}
	} while (xmlTextReaderNodeType(reader) != XML_READER_TYPE_END_ELEMENT ||
	         xmlTextReaderDepth(reader) != curr_depth);

	return 1;
}
Example #4
0
/**
 * @brief Parse gif from a file
 *
 * @param f file to parse from
 *
 * @return true on success
 */
bool Gif::parse(FILE * f) {
	/*
	 * Read header
	 */
	if (fread(&m_header, kHeaderSize, 1, f) != 1) {
		err() << "Failed to read header!\n";
		return false;
	}

	/*
	 * Check correct GIF img
	 */
	if (! is_gif()) { err() << "Input file is not a GIF file!\n"; return false; }
	if (! is_gif89a()) { err() << "Unsupported GIF version!\n"; return false; }
	//if (! is_gif8bit()) { err() << "Not GIF 8bit!\n"; return false; }

	/*
	 * Read color table
	 */
	if (has_global_color_table()) {
		struct color_item_t item;
		for (size_t i = 0; i < get_global_table_size(); ++i) {
			if (fread(&item.data, kColorTableSize, 1, f) != 1) {
				err() << "Failed to read global table!\n";
				return false;
			}
			item.cc = item.eoi = false;
			global_color_table.push_back(item);
		}
		//dbg_global_color();
	}

	/*
	 * Check start byte. Note than *_extension() functions access data without
	 * entry byte!
	 */
	int c;
	while ((c = fgetc(f)) != EOF) {
		switch (c) {
			case kExtensionStartByte:
					/* FALLTRHU*/
			case kImageDescriptor:
				if (c != kImageDescriptor) c = fgetc(f);
				switch((c)) {
					case kExtensionComment:
						if (! parse_comment_extension(f))
							return false;
						break;
					case kExtensionApplication:
						if (! parse_application_extension(f))
							return false;
						break;
					case kExtensionGraphicControl:
						if (! parse_graphic_control_extension(f))
							return false;
						break;
					case kImageDescriptor:
						/* FALLTRHU*/
					case kExtensionPlainText:
						if (c == kImageDescriptor) {
							if (! parse_image(f))
								return false;
						} else if (c == kExtensionPlainText) {
							if (! parse_plain_text_extension(f))
								return false;
						}
						break;
					default:
						err() << "Unknown extension type '"
								<< std::hex << (unsigned) c << "'!\n";
						UNREACHABLE();
						return false;
				}
				break;
			case kStopByte:
				if (fgetc(f) != EOF) {
					err() << "Stop byte is not last byte!\n";
					return false;
				}
				break;
			default:
				err() << "Unknown start byte '"
					<< std::hex << (unsigned) c
					<< "', extension or EOF expected!\n";
				return false;
		}
	}

	//dbg_imgs();

	return true;
}
Example #5
0
static GList*
feed_rss_handler_parse (FeedHandler *self, GrssFeedChannel *feed, xmlDocPtr doc, gboolean do_items, GError **error)
{
	gchar *tmp;
	gboolean rdf;
	time_t now;
	GList *items;
	xmlNodePtr cur;
	GrssFeedItem *item;
	FeedRssHandler *parser;

	items = NULL;
	rdf = FALSE;
	now = time (NULL);
	parser = FEED_RSS_HANDLER (self);

	cur = xmlDocGetRootElement (doc);
	while (cur && xmlIsBlankNode (cur))
		cur = cur->next;

	if (!xmlStrcmp (cur->name, BAD_CAST"rss")) {
		cur = cur->xmlChildrenNode;
		rdf = FALSE;
	}
	else if (!xmlStrcmp (cur->name, BAD_CAST"rdf") ||
	         !xmlStrcmp (cur->name, BAD_CAST"RDF")) {
		cur = cur->xmlChildrenNode;
		rdf = TRUE;
	}
	else if (!xmlStrcmp (cur->name, BAD_CAST"Channel")) {
		rdf = FALSE;
	}
	else {
		g_set_error (error, FEED_RSS_HANDLER_ERROR, FEED_RSS_HANDLER_PARSE_ERROR, "Could not find RDF/RSS header!");
		return NULL;
	}

	while (cur && xmlIsBlankNode (cur))
		cur = cur->next;

	while (cur) {
		if (!cur->name) {
			g_warning ("invalid XML: parser returns NULL value -> tag ignored!");
			cur = cur->next;
			continue;
		}

		if ((!xmlStrcmp (cur->name, BAD_CAST"channel")) ||
		    (!xmlStrcmp (cur->name, BAD_CAST"Channel"))) {
			parse_channel (parser, feed, doc, cur);
			if (rdf == FALSE)
				cur = cur->xmlChildrenNode;
			break;
		}

		cur = cur->next;
	}

	/* For RDF (rss 0.9 or 1.0), cur now points to the item after the channel tag. */
	/* For RSS, cur now points to the first item inside of the channel tag */
	/* This ends up being the thing with the items, (and images/textinputs for RDF) */

	/* parse channel contents */
	while (cur) {
		if (cur->type != XML_ELEMENT_NODE || NULL == cur->name) {
			cur = cur->next;
			continue;
		}

		/* save link to channel image */
		if ((!xmlStrcmp (cur->name, BAD_CAST"image"))) {
			if (NULL != (tmp = parse_image (cur))) {
				grss_feed_channel_set_image (feed, tmp);
				g_free (tmp);
			}
		}
		else if (do_items == TRUE && (!xmlStrcmp (cur->name, BAD_CAST"items"))) { /* RSS 1.1 */
			xmlNodePtr iter = cur->xmlChildrenNode;

			while (iter) {
				item = parse_rss_item (parser, feed, doc, iter);

				if (item != NULL) {
					if (grss_feed_item_get_publish_time (item) == 0)
						grss_feed_item_set_publish_time (item, now);
					items = g_list_append (items, item);
				}

				iter = iter->next;
			}
		}
		else if (do_items == TRUE && (!xmlStrcmp (cur->name, BAD_CAST"item"))) { /* RSS 1.0, 2.0 */
			item = parse_rss_item (parser, feed, doc, cur);

			if (item != NULL) {
				if (grss_feed_item_get_publish_time (item) == 0)
					grss_feed_item_set_publish_time (item, now);
				items = g_list_append (items, item);
			}
		}

		cur = cur->next;
	}

	grss_feed_channel_set_format (feed, "application/rss+xml");

	if (items != NULL)
		items = g_list_reverse (items);
	return items;
}
Example #6
0
int main(int argc, char *argv[])
{
	FILE *fp;
	struct disk_side *sides, *curr_side;
	struct disk_track *curr_track;
	struct disk_sector *curr_sector;
		
	DSK_GEOMETRY geom;
	DSK_PDRIVER newdisk;
	DSK_FORMAT *format;
	dsk_err_t err;
	
	int i;
	char *secdata;
		
	
	
	if (argc != 3)
	{
		fprintf(stderr, "usage: %s infile outfile\n", argv[0]);
		exit(1);
	}
	
	fp = fopen(argv[1], "r");
	if (fp == NULL)
	{
		fprintf(stderr, "unable to open file: %s\n", argv[1]);
		exit(1);
	}
	
	sides = parse_image(fp);

	memset(&geom, 0, sizeof(DSK_GEOMETRY));
	geom.dg_cylinders = max_tracks;
	geom.dg_heads = max_sides;
	geom.dg_sectors = max_sectors;
	geom.dg_secbase = 1;  /* perhaps this should be determined from file? */
	geom.dg_secsize = sector_size;
	
	format = malloc(geom.dg_sectors*sizeof(DSK_FORMAT));
	secdata = malloc(geom.dg_secsize);
	if ((format == NULL) || (secdata == NULL))
	{
		fprintf(stderr, "main: out of memory\n");
		exit(1);
	}
	
	
	if (dsk_creat(&newdisk, argv[2], "dsk", NULL) != DSK_ERR_OK)
	{
		fprintf(stderr, "main: error in dsk_creat\n");
		exit(1);
	}

    for (i=0; i<max_sides; i++)
		if (dsk_apform(newdisk, &geom, 0, i, 0xE5) != DSK_ERR_OK)
		{
			fprintf(stderr, "main: error formatting inital cylinder\n");
			exit(1);
		}
	
	curr_side = sides;
	while (curr_side != NULL)
	{
/*	printf("Side = %i\n", curr_side->id); */
		curr_track = curr_side->tracks;
		
		while (curr_track != NULL)
		{
			/*printf("   Track = %i\n", curr_track->id); */
			curr_sector = curr_track->sectors;
			i = 0;
			while (curr_sector != NULL)
			{
			/*	printf("      Sector = %i\n", curr_sector->id);*/
				format[i].fmt_cylinder = curr_sector->logical_track;
				format[i].fmt_head = curr_sector->logical_side;
				format[i].fmt_sector = curr_sector->id;
				format[i].fmt_secsize = curr_sector->length;
				
				curr_sector = curr_sector->next;
				i++;
			}
			
			if ((err = dsk_pformat(newdisk, &geom, curr_track->id, curr_side->id, format, 0xE5)) != DSK_ERR_OK)
			{
				fprintf(stderr, "main: error in dsk_pformat(%i)\n", err);
				exit(1);
			}
			
			curr_sector = curr_track->sectors;
			while (curr_sector != NULL)
			{
				fseek(fp, curr_sector->ofs, SEEK_SET);
				if (fread(secdata, 1, curr_sector->length, fp) != curr_sector->length)
				{
					fprintf(stderr, "main: error reading input file sector\n");
					exit(1);
				}
				if ((err = dsk_xwrite(newdisk, &geom, secdata, curr_track->id, curr_side->id, curr_sector->logical_track, curr_sector->logical_side, curr_sector->id, curr_sector->length, 0)) != DSK_ERR_OK)
				{
					fprintf(stderr, "main: error in dsk_pwrite (%i, sec=%i, side=%i, track=%i) \n", err, curr_sector->id, curr_sector->logical_side, curr_sector->logical_track);
					exit(1);
				}
				curr_sector = curr_sector->next;
			}
				
			curr_track = curr_track->next;
		}
		
		curr_side = curr_side->next;
	}
	
	

	printf("Sides: %2i  Tracks: %2i  Sectors: %2i\n", max_sides, max_tracks, max_sectors);

	
	dsk_close(&newdisk);
	fclose(fp);
	return 0;
}
Example #7
0
std::string load_shader_impl(ShaderInitializationParams& params, const std::vector<std::string>& data, const std::string& tag, LoadContext& load_context)
{
    std::string actual_data;

    enum
    {
        state_not_found,
        state_found,
        state_incorrect_found
    };

    int state = state_not_found;

    for (size_t i = 0; i < data.size(); ++i)
    {
        const std::string& s = utils::trim_copy(data[i]);

        if (s.find(include_tag) != std::string::npos)
        {
            ++load_context.level;
            actual_data += parse_include(params, s, tag, load_context);
            --load_context.level;
            continue;
        }

        if (s.find(defs_tag) != std::string::npos)
            continue;

        if (s.find(sampler_tag) != std::string::npos)
        {
            actual_data += parse_sampler(params, s);
            continue;
        }

        if (s.find(uniform_tag) != std::string::npos)
        {
            actual_data += parse_uniform(params, s);
            continue;
        }

        if (s.find(image_tag) != std::string::npos)
        {
            actual_data += parse_image(params, s);
            continue;
        }

        if (s.find(var_tag) != std::string::npos)
        {
            actual_data += parse_variable(params, s);
            continue;
        }

        if (s.find(version_tag) != std::string::npos)
        {
            actual_data += parse_version(params, s);
            continue;
        }

        if (s == tag)
            state = state_found;
        else
        {
            for (size_t j = 0; j < 4; ++j)
            {
                if (s == tags[j])
                {
                    if (state == state_found)
                        return actual_data;
                    else state = state_incorrect_found;
                    break;
                }
            }

            if (state != state_incorrect_found)
                actual_data += (s + "\n");
        }
    }
    if (state == state_found)
        load_context.tag_found = true;
    if (!load_context.tag_found && load_context.level == 0)
        actual_data.clear();
    return actual_data;
}
Example #8
0
int main(int argc, char **argv)
{
	int c, opt;
	char *cwd;
	struct stat sb;
	FILE *devtable = NULL;
	struct filesystem_entry *root;
        char *compr_name = NULL;
        int compr_prior  = -1;

        jffs2_compressors_init();

	while ((opt = getopt_long(argc, argv,
					"D:d:r:s:o:qUPfh?vVe:lbp::nc:m:x:X:Lty:i:", long_options, &c)) >= 0)
	{
		switch (opt) {
			case 'D':
				devtable = xfopen(optarg, "r");
				if (fstat(fileno(devtable), &sb) < 0)
					perror_msg_and_die(optarg);
				if (sb.st_size < 10)
					error_msg_and_die("%s: not a proper device table file", optarg);
				break;

			case 'r':
			case 'd':	/* for compatibility with mkfs.jffs, genext2fs, etc... */
				if (rootdir != default_rootdir) {
					error_msg_and_die("root directory specified more than once");
				}
				rootdir = xstrdup(optarg);
				break;

			case 's':
				page_size = strtol(optarg, NULL, 0);
				break;

			case 'o':
				if (out_fd != -1) {
					error_msg_and_die("output filename specified more than once");
				}
				out_fd = open(optarg, O_CREAT | O_TRUNC | O_RDWR, 0644);
				if (out_fd == -1) {
					perror_msg_and_die("open output file");
				}
				break;

			case 'q':
				squash_uids = 1;
				squash_perms = 1;
				break;

			case 'U':
				squash_uids = 1;
				break;

			case 'P':
				squash_perms = 1;
				break;

			case 'f':
				fake_times = 1;
				break;

			case 'h':
			case '?':
				error_msg_and_die(helptext);

			case 'v':
				verbose = 1;
				break;

			case 'V':
				error_msg_and_die("revision %.*s\n",
						(int) strlen(revtext) - 13, revtext + 11);

			case 'e': {
				char *next;
				unsigned units = 0;
				erase_block_size = strtol(optarg, &next, 0);
				if (!erase_block_size)
					error_msg_and_die("Unrecognisable erase size\n");

				if (*next) {
					if (!strcmp(next, "KiB")) {
						units = 1024;
					} else if (!strcmp(next, "MiB")) {
						units = 1024 * 1024;
					} else {
						error_msg_and_die("Unknown units in erasesize\n");
					}
				} else {
					if (erase_block_size < 0x1000)
						units = 1024;
					else
						units = 1;
				}
				erase_block_size *= units;

				/* If it's less than 8KiB, they're not allowed */
				if (erase_block_size < 0x2000) {
					fprintf(stderr, "Erase size 0x%x too small. Increasing to 8KiB minimum\n",
						erase_block_size);
					erase_block_size = 0x2000;
				}
				break;
			}

			case 'l':
				target_endian = __LITTLE_ENDIAN;
				break;

			case 'b':
				target_endian = __BIG_ENDIAN;
				break;

			case 'p':
				if (optarg)
					pad_fs_size = strtol(optarg, NULL, 0);
				else
					pad_fs_size = -1;
				break;
			case 'n':
				add_cleanmarkers = 0;
				break;
			case 'c':
				cleanmarker_size = strtol(optarg, NULL, 0);
				if (cleanmarker_size < sizeof(cleanmarker)) {
					error_msg_and_die("cleanmarker size must be >= 12");
				}
				if (cleanmarker_size >= erase_block_size) {
					error_msg_and_die("cleanmarker size must be < eraseblock size");
				}
				break;
                        case 'm':
                                if (jffs2_set_compression_mode_name(optarg)) {
					error_msg_and_die("Unknown compression mode %s", optarg);
				}
                                break;
                        case 'x':
                                if (jffs2_disable_compressor_name(optarg)) {
                                        error_msg_and_die("Unknown compressor name %s",optarg);
                                }
                                break;
                        case 'X':
                                if (jffs2_enable_compressor_name(optarg)) {
                                        error_msg_and_die("Unknown compressor name %s",optarg);
                                }
                                break;
                        case 'L':
                                error_msg_and_die("\n%s",jffs2_list_compressors());
                                break;
                        case 't':
                                jffs2_compression_check_set(1);
                                break;
                        case 'y':
                                compr_name = malloc(strlen(optarg));
                                sscanf(optarg,"%d:%s",&compr_prior,compr_name);
                                if ((compr_prior>=0)&&(compr_name)) {
                                        if (jffs2_set_compressor_priority(compr_name, compr_prior))
	                                        exit(EXIT_FAILURE);
                                }
                                else {
                                        error_msg_and_die("Cannot parse %s",optarg);
                                }
                                free(compr_name);
                                break;
			case 'i':
				if (in_fd != -1) {
					error_msg_and_die("(incremental) filename specified more than once");
				}
				in_fd = open(optarg, O_RDONLY);
				if (in_fd == -1) {
					perror_msg_and_die("cannot open (incremental) file");
				}
				break;
			case 1000:	/* --with-xattr  */
				enable_xattr |= (1 << JFFS2_XPREFIX_USER)
						| (1 << JFFS2_XPREFIX_SECURITY)
						| (1 << JFFS2_XPREFIX_ACL_ACCESS)
						| (1 << JFFS2_XPREFIX_ACL_DEFAULT)
						| (1 << JFFS2_XPREFIX_TRUSTED);
				break;
			case 1001:	/*  --with-selinux  */
				enable_xattr |= (1 << JFFS2_XPREFIX_SECURITY);
				break;
			case 1002:	/*  --with-posix-acl  */
				enable_xattr |= (1 << JFFS2_XPREFIX_ACL_ACCESS)
						| (1 << JFFS2_XPREFIX_ACL_DEFAULT);
				break;
		}
	}
	if (out_fd == -1) {
		if (isatty(1)) {
			error_msg_and_die(helptext);
		}
		out_fd = 1;
	}
	if (lstat(rootdir, &sb)) {
		perror_msg_and_die("%s", rootdir);
	}
	if (chdir(rootdir))
		perror_msg_and_die("%s", rootdir);

	if (!(cwd = getcwd(0, GETCWD_SIZE)))
		perror_msg_and_die("getcwd failed");

	if(in_fd != -1)
		parse_image();

	root = recursive_add_host_directory(NULL, "/", cwd);

	if (devtable)
		parse_device_table(root, devtable);

	create_target_filesystem(root);

	cleanup(root);

	if (rootdir != default_rootdir)
		free(rootdir);

	close(out_fd);

        if (verbose) {
                char *s = jffs2_stats();
                fprintf(stderr,"\n\n%s",s);
                free(s);
        }
        if ((verbose)||(jffs2_compression_check_get()&&(jffs2_compression_check_errorcnt_get()))) {
                fprintf(stderr,"Compression errors: %d\n",jffs2_compression_check_errorcnt_get());
        }

        jffs2_compressors_exit();

	return 0;
}