示例#1
0
int read_chunk(void) {
	ssize_t s, len, offset;

	chunk_no++;
	len = chunk_size + spare_size;
	offset = 0;
	memset(chunk_data, 0xff, sizeof(chunk_data));

	if (buf_len > buf_idx) {		/* copy from buffer */
		s = buf_len - buf_idx;
		if (s > len) s = len;
		memcpy(data, buffer+buf_idx, s);
		buf_idx += s; offset += s;
	}

	if (offset < len) {			/* read from file */
		s = xread(img_file, data+offset, len-offset);
		if (s < 0)
			prt_err(1, errno, "Read image file");
		offset += s;
	}

	if (offset != 0 && offset != len)	/* partial chunk */
		prt_err(1, 0, "Broken image file");

	return offset != 0;
}
示例#2
0
int read_chunk(void) {
	ssize_t s, len, offset;

	chunk_no++;
	len = chunk_size + spare_size;
	offset = 0;
	memset(data, 0xff, len);

	if (buf_len > buf_idx) {		/* copy from buffer */
		s = buf_len - buf_idx;
		if (s > len) s = len;
		memcpy(data, buffer+buf_idx, s);
		buf_idx += s; offset += s;
	}

	if (offset < len) {			/* read from file */
		s = safe_read(img_file, data+offset, len-offset);
		if (s < 0)
			prt_err(1, errno, "Read image file");
		offset += s;
	}

	if (offset != 0 && offset != len)	/* partial chunk */
		prt_err(1, 0, "Broken image file");

	if (offset == len && spare_off != 0) {	/* bad block info */
		memmove(data+chunk_size, data+chunk_size+spare_off,
		        spare_size-spare_off);
		memset(data+len-spare_off, 0xff, spare_off);
	}

	return offset != 0;
}
示例#3
0
/*
 * save_lchown - call lchown and check result
 */
static void safe_lchown(const char *path, uid_t owner, gid_t group) {
	if (lchown(path, owner, group) < 0) {
		if (errno == EPERM || errno == EINVAL)
			warn_chown = 1;
		else
			prt_err(1, errno, "Can't chown %s", path);
	}
}
示例#4
0
void detect_flash_layout(int show, int first) {
	int cnt;
	int chunk, spare, off;

	memset(buffer, 0xff, sizeof(buffer));
	buf_len = safe_read(img_file, buffer, sizeof(buffer));
	if (buf_len < 0)
		prt_err(1, errno, "Read image file");

	if (show)
		printf("Detected flash layout(s):\n");

	cnt = 0;
	for (chunk = MIN_CHUNK_SIZE; chunk <= MAX_CHUNK_SIZE; chunk *= 2) {
		for (spare = MIN_SPARE_SIZE; spare <= MAX_SPARE_SIZE; spare += 16) {
			for (off = 0; off <= 2; off += 2) {
				if (check_layout(chunk, spare, off)) {
					cnt++;
					if (show) {
						printf("%2s -c %-2d -s %-3d : chunk size = %2dK, spare size = %3d, %sbad block info\n",
						       off ? "-b" : "", chunk / 1024, spare,
						       chunk / 1024, spare, off ? "" : "no ");
					}
					if (first) {
						chunk_size = chunk;
						spare_size = spare;
						spare_off  = off;
						return;
					}
				}
			}
		}
	}

	if (cnt == 0) {
		if (show) {
			printf("-- none --\n");
			exit(1);
		} else {
			prt_err(1, 0, "Can't determine flash layout, perhaps not a yaffs2 image");
		}
	}
}
示例#5
0
void detect_chunk_size(void) {
	yaffs_ObjectHeader *oh;
	yaffs_PackedTags2  *pt, *pt2;
	int      i;

	memset(buffer, 0xff, sizeof(buffer));
	buf_len = xread(img_file, buffer, sizeof(buffer));
	if (buf_len < 0)
		prt_err(1, errno, "Read image file");

	oh = (yaffs_ObjectHeader *)buffer;
	if (oh->parentObjectId != YAFFS_OBJECTID_ROOT ||
	    (oh->type          != YAFFS_OBJECT_TYPE_FILE &&
	     oh->type          != YAFFS_OBJECT_TYPE_DIRECTORY &&
	     oh->type          != YAFFS_OBJECT_TYPE_SYMLINK &&
	     oh->type          != YAFFS_OBJECT_TYPE_HARDLINK &&
	     oh->type          != YAFFS_OBJECT_TYPE_SPECIAL))
		prt_err(1, 0, "Not a yaffs2 image");

	for (i = 0; i < max_layout; i++) {
 		pt  = (yaffs_PackedTags2 *)
		      (buffer + possible_layouts[i].chunk_size);
		pt2 = (yaffs_PackedTags2 *)
		      (buffer + 2 * possible_layouts[i].chunk_size +
		       possible_layouts[i].spare_size);

		if (pt->t.byteCount == 0xffff && pt->t.chunkId == 0 &&
		    ((pt2->t.byteCount == 0xffff && pt2->t.chunkId == 0) ||
		     (pt2->t.objectId == pt->t.objectId && pt2->t.chunkId == 1)))
			break;
	}

	if (i >= max_layout)
		prt_err(1, 0, "Can't determine chunk size");

	chunk_size = possible_layouts[i].chunk_size;
	spare_size = possible_layouts[i].spare_size;
	if (opt_verbose)
		fprintf(stderr,
		        "Header check OK, chunk size = %d, spare size = %d.\n",
		        chunk_size, spare_size);
}
示例#6
0
static void init_obj_list(void) {
	object *obj;
	unsigned idx;

	for (idx = 0; idx < HASH_SIZE; idx++)
		obj_list[idx] = NULL;
	last_dir_id = 0;

	obj = malloc(offsetof(object, path_name) + 2);
	if (obj == NULL)
		prt_err(1, 0, "Malloc struct object failed.");

	obj->id = YAFFS_OBJECTID_ROOT;
	obj->type = YAFFS_OBJECT_TYPE_DIRECTORY;
	obj->prev_dir_id = 0;
	obj->atime = obj->mtime = 0;
	strcpy(obj->path_name, ".");
	idx = obj->id % HASH_SIZE;
	obj->next = obj_list[idx];
	obj_list[idx] = obj;
}
示例#7
0
int main(int argc, char **argv) {
	int ch;
	int layout = 0;

	/* handle command line options */
	opt_list = 0;
	opt_verbose = 0;
	opt_skip = 0;
	while ((ch = getopt(argc, argv, "l:tsvVh?")) > 0) {
		switch (ch) {
			case 'l':
				if (optarg[0] < '0' ||
				    optarg[0] > '0' + max_layout ||
				    optarg[1] != '\0') usage();
				layout = optarg[0] - '0';
				break;
			case 't':
				opt_list = 1;
				break;
			case 'v':
				opt_verbose = 1;
				break;
			case 's':
				opt_skip = 1;
				break;
			case 'V':
				printf("V%s\n", VERSION);
				exit(0);
				break;
			case 'h':
			case '?':
			default:
				usage();
				break;
    		}
	}

	/* extract rest of command line parameters */
	if ((argc - optind) < 1 || (argc - optind) > 2)
		usage();

	if (strcmp(argv[optind], "-") == 0) {	/* image file from stdin ? */
		img_file = 0;
	} else {
		img_file = open(argv[optind], O_RDONLY);
		if (img_file < 0)
			prt_err(1, errno, "Open image file failed");
	}

	if (layout == 0) {
		detect_chunk_size();
	} else {
		chunk_size = possible_layouts[layout-1].chunk_size;
		spare_size = possible_layouts[layout-1].spare_size;
	}
	spare_data = data + chunk_size;

	// Skip first chunk
	if (opt_skip)
		lseek(img_file, chunk_size+spare_size, SEEK_SET);

	if ((argc - optind) == 2 && !opt_list) {
		if (mkdirpath(argv[optind+1]) < 0)
			prt_err(1, errno, "Can't mkdir %s", argv[optind+1]);
		if (chdir(argv[optind+1]) < 0)
			prt_err(1, errno, "Can't chdir to %s", argv[optind+1]);
	}

	umask(0);

	init_obj_list();
	while (read_chunk()) {
		process_chunk();
	}
	set_dirs_utime();
	close(img_file);
	return 0;
}
示例#8
0
void process_chunk(void) {
	yaffs_ObjectHeader oh;
	yaffs_PackedTags2 *pt;
	object *obj, *eq_obj;
	int out_file, remain, s;

	oh = *(yaffs_ObjectHeader *)chunk_data;
	pt = (yaffs_PackedTags2 *)spare_data;

	if (pt->t.byteCount == 0xffffffff)	/* empty object */
		return;
	else if (pt->t.byteCount != 0xffff) {	/* not a new object */
		prt_err(0, 0, "Warning: Invalid header at chunk #%d, skipping...",
		        chunk_no);
		if (++warn_count >= MAX_WARN)
			prt_err(1, 0, "Giving up");
		return;
	}

	obj = add_object(&oh, pt);

	/* listing */
	if (opt_verbose)
		prt_node(obj->path_name, &oh);
	else if (opt_list)
		printf("%s\n", obj->path_name);
	if (opt_list) {
		if (oh.type == YAFFS_OBJECT_TYPE_FILE) {
			remain = oh.fileSize;	/* skip over data chunks */
			while(remain > 0) {
				if (!read_chunk())
					prt_err(1, 0, "Broken image file");
				remain -= pt->t.byteCount;
			}
		}
		return;
	}

	switch(oh.type) {
		case YAFFS_OBJECT_TYPE_FILE:
			remain = oh.fileSize;
			out_file = creat(obj->path_name, oh.yst_mode & STD_PERMS);
			if (out_file < 0)
				prt_err(1, errno, "Can't create file %s", obj->path_name);
			while(remain > 0) {
				if (!read_chunk())
					prt_err(1, 0, "Broken image file");
				s = (remain < pt->t.byteCount) ? remain : pt->t.byteCount;
				if (xwrite(out_file, chunk_data, s) < 0)
					prt_err(1, errno, "Can't write to %s", obj->path_name);
				remain -= s;
			}
			close(out_file);
			lchown(obj->path_name, oh.yst_uid, oh.yst_gid);
			if ((oh.yst_mode & EXTRA_PERMS) != 0 &&
			    chmod(obj->path_name, oh.yst_mode) < 0)
				prt_err(0, errno, "Warning: Can't chmod %s", obj->path_name);
			break;
		case YAFFS_OBJECT_TYPE_SYMLINK:
			if (symlink(oh.alias, obj->path_name) < 0)
				prt_err(1, errno, "Can't create symlink %s", obj->path_name);
			lchown(obj->path_name, oh.yst_uid, oh.yst_gid);
			break;
		case YAFFS_OBJECT_TYPE_DIRECTORY:
			if (pt->t.objectId != YAFFS_OBJECTID_ROOT &&
			    mkdir(obj->path_name, oh.yst_mode & STD_PERMS) < 0)
					prt_err(1, errno, "Can't create directory %s", obj->path_name);
			lchown(obj->path_name, oh.yst_uid, oh.yst_gid);
			if ((pt->t.objectId == YAFFS_OBJECTID_ROOT ||
			     (oh.yst_mode & EXTRA_PERMS) != 0) &&
			    chmod(obj->path_name, oh.yst_mode) < 0)
				prt_err(0, errno, "Warning: Can't chmod %s", obj->path_name);
			break;
		case YAFFS_OBJECT_TYPE_HARDLINK:
			eq_obj = get_object(oh.equivalentObjectId);
			if (eq_obj == NULL)
				prt_err(1, 0, "Invalid equivalentObjectId %u in object %u (%s)",
				        oh.equivalentObjectId, pt->t.objectId, oh.name);
			if (link(eq_obj->path_name, obj->path_name) < 0)
				prt_err(1, errno, "Can't create hardlink %s", obj->path_name);
			break;
		case YAFFS_OBJECT_TYPE_SPECIAL:
			if (mknod(obj->path_name, oh.yst_mode, oh.yst_rdev) < 0) {
				if (errno == EPERM || errno == EINVAL)
					prt_err(0, errno, "Warning: Can't create device %s", obj->path_name);
				else
					prt_err(1, errno, "Can't create device %s", obj->path_name);
			}
			lchown(obj->path_name, oh.yst_uid, oh.yst_gid);
			break;
		case YAFFS_OBJECT_TYPE_UNKNOWN:
			break;
	}

	/* set file date and time */
	switch(oh.type) {
		case YAFFS_OBJECT_TYPE_FILE:
		case YAFFS_OBJECT_TYPE_SPECIAL:
#ifdef HAS_LUTIMES
		case YAFFS_OBJECT_TYPE_SYMLINK:
#endif
			set_utime(obj->path_name,
			          oh.yst_atime, oh.yst_mtime);
			break;
		case YAFFS_OBJECT_TYPE_DIRECTORY:
		default:
			break;
	}
}
示例#9
0
static object *add_object(yaffs_ObjectHeader *oh, yaffs_PackedTags2 *pt) {
	object *obj, *parent;
	unsigned idx;

	obj = get_object(pt->t.objectId);
	if (pt->t.objectId == YAFFS_OBJECTID_ROOT) {
		if (obj == NULL)
			prt_err(1, 0, "Missing root object");
		if (oh->type != YAFFS_OBJECT_TYPE_DIRECTORY)
			prt_err(1, 0, "Root object must be directory");
		if (last_dir_id == 0)
			last_dir_id = YAFFS_OBJECTID_ROOT;
	} else {
		if (oh->type != YAFFS_OBJECT_TYPE_FILE &&
		    oh->type != YAFFS_OBJECT_TYPE_DIRECTORY &&
		    oh->type != YAFFS_OBJECT_TYPE_SYMLINK &&
		    oh->type != YAFFS_OBJECT_TYPE_HARDLINK &&
		    oh->type != YAFFS_OBJECT_TYPE_SPECIAL &&
		    oh->type != YAFFS_OBJECT_TYPE_UNKNOWN)
			prt_err(1, 0, "Illegal type %d in object %u (%s)",
			        oh->type, pt->t.objectId, oh->name);
		if (oh->name[0] == '\0' || strchr(oh->name, '/') != NULL ||
		    strcmp(oh->name, ".") == 0 || strcmp(oh->name, "..") == 0)
			prt_err(1, 0, "Illegal file name %s in object %u",
			        oh->name, pt->t.objectId);
		if (obj != NULL)
			prt_err(1, 0, "Duplicate objectId %u", pt->t.objectId);
		parent = get_object(oh->parentObjectId);
		if (parent == NULL)
			prt_err(1, 0, "Invalid parentObjectId %u in object %u (%s)",
	        		oh->parentObjectId, pt->t.objectId, oh->name);
		if (parent->type != YAFFS_OBJECT_TYPE_DIRECTORY)
			prt_err(1, ENOTDIR, "File %s can't be created in %s",
	        		oh->name, parent->path_name);
		obj = malloc(offsetof(object, path_name) +
		             strlen(parent->path_name) + strlen(oh->name) + 2);
		if (obj == NULL)
			prt_err(1, 0, "Malloc struct object failed.");

		obj->id = pt->t.objectId;
		obj->type = oh->type;
		if (obj->type == YAFFS_OBJECT_TYPE_DIRECTORY) {
			obj->prev_dir_id = last_dir_id;
			last_dir_id = obj->id;
		} else
			obj->prev_dir_id = 0;
		if (strcmp(parent->path_name, ".") == 0) {
			strcpy(obj->path_name, oh->name);
		} else {
			strcpy(obj->path_name, parent->path_name);
			strcat(obj->path_name, "/");
			strcat(obj->path_name, oh->name);
		}
		idx = obj->id % HASH_SIZE;
		obj->next = obj_list[idx];
		obj_list[idx] = obj;
	}

	obj->atime = oh->yst_atime;
	obj->mtime = oh->yst_mtime;

	return obj;
}
示例#10
0
int main(int argc, char **argv) {
	int ch;
	char *ep;

	int opt_detect;
	int opt_bad;
	int opt_chunk;
	int opt_spare;

	/* handle command line options */
	opt_detect = 0;
	opt_bad = 0;
	opt_chunk = 0;
	opt_spare = 0;
	opt_list = 0;
	opt_verbose = 0;
	while ((ch = getopt(argc, argv, "dbc:s:tvVh?")) > 0) {
		switch (ch) {
			case 'd':
				opt_detect = 1;
				break;
			case 'b':
				opt_bad = 1;
				break;
			case 'c':
				opt_chunk = strtol(optarg, &ep, 0);
				if (*ep != '\0' ||
				    opt_chunk < 0 ||
				    opt_chunk > (MAX_CHUNK_SIZE / 1024) )
					usage();
				break;
			case 's':
				opt_spare = strtol(optarg, &ep, 0);
				if (*ep != '\0' ||
				    opt_spare < 0 ||
				    opt_spare > MAX_SPARE_SIZE)
					usage();
				break;
			case 't':
				opt_list = 1;
				break;
			case 'v':
				opt_verbose = 1;
				break;
			case 'V':
				printf("V%s\n", VERSION);
				exit(0);
				break;
			case 'h':
			case '?':
			default:
				usage();
				break;
    		}
	}

	/* extract rest of command line parameters */
	if ((argc - optind) < 1 || (argc - optind) > 2)
		usage();

	if (strcmp(argv[optind], "-") == 0) {	/* image file from stdin ? */
		img_file = 0;
	} else {
		img_file = open(argv[optind], O_RDONLY);
		if (img_file < 0)
			prt_err(1, errno, "Open image file failed");
	}

	if (opt_detect) {
		detect_flash_layout(1, 0);
		return 0;
	}

	if (opt_chunk == 0 || opt_spare == 0) {
		detect_flash_layout(0, 1);
		if (opt_verbose)
			prt_err(0, 0,
		        	"Header check OK, chunk size = %dK, spare size = %d, %sbad block info.",
		        	chunk_size/1024, spare_size, spare_off ? "" : "no ");
	} else {
		chunk_size = opt_chunk * 1024;
		spare_size = opt_spare;
		spare_off  = opt_bad ? 2 : 0;
	}
	spare_data = data + chunk_size;

	if ((argc - optind) == 2 && !opt_list) {
		if (mkdirpath(argv[optind+1], 0755) < 0)
			prt_err(1, errno, "Can't mkdir %s", argv[optind+1]);
		if (chdir(argv[optind+1]) < 0)
			prt_err(1, errno, "Can't chdir to %s", argv[optind+1]);
	}

	umask(0);

	init_obj_list();
	saved_chunk.objectId = 0;
	while (read_chunk()) {
		process_chunk();
	}
	set_dirs_utime();
	close(img_file);

	if (warn_chown)
#ifdef __CYGWIN__
		prt_err(0, 0, "Warning: Can't restore owner/group attribute (limitation of Cygwin/Windows)");
#else
		prt_err(0, 0, "Warning: Can't restore owner/group attribute, run unyaffs as root");
#endif

	return 0;
}