Beispiel #1
0
extern unsigned char archive_xread_char(const archive_handle_t *archive_handle)
{
	unsigned char tmp;
	
	archive_xread(archive_handle, &tmp, 1);

	return(tmp);
}
Beispiel #2
0
extern ssize_t archive_xread_all_eof(archive_handle_t *archive_handle, unsigned char *buf, size_t count)
{
	ssize_t size;

	size = archive_xread(archive_handle, buf, count);
	if ((size != 0) && (size != count)) {
		bb_perror_msg_and_die("Short read, read %d of %d", size, count);
	}
	return(size);
}
Beispiel #3
0
extern char get_header_tar(archive_handle_t *archive_handle)
{
	file_header_t *file_header = archive_handle->file_header;
	union {
		unsigned char raw[512];
		struct {
			char name[100];	/*   0-99 */
			char mode[8];	/* 100-107 */
			char uid[8];	/* 108-115 */
			char gid[8];	/* 116-123 */
			char size[12];	/* 124-135 */
			char mtime[12];	/* 136-147 */
			char chksum[8];	/* 148-155 */
			char typeflag;	/* 156-156 */
			char linkname[100];	/* 157-256 */
			char magic[6];	/* 257-262 */
			char version[2];	/* 263-264 */
			char uname[32];	/* 265-296 */
			char gname[32];	/* 297-328 */
			char devmajor[8];	/* 329-336 */
			char devminor[8];	/* 337-344 */
			char prefix[155];	/* 345-499 */
			char padding[12];	/* 500-512 */
		} formated;
	} tar;
	long sum = 0;
	long i;
	char *tmp;

	/* Align header */
	data_align(archive_handle, 512);

	if (archive_xread(archive_handle, tar.raw, 512) != 512) {
		/* Assume end of file */
		return(EXIT_FAILURE);
	}
	archive_handle->offset += 512;

	/* If there is no filename its an empty header */
	if (tar.formated.name[0] == 0) {
		return(EXIT_SUCCESS);
	}

	/* Check header has valid magic, "ustar" is for the proper tar
	 * 0's are for the old tar format
	 */
	if (strncmp(tar.formated.magic, "ustar", 5) != 0) {
#ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY
		if (strncmp(tar.formated.magic, "\0\0\0\0\0", 5) != 0)
#endif
			bb_error_msg_and_die("Invalid tar magic");
	}
	/* Do checksum on headers */
	for (i =  0; i < 148 ; i++) {
		sum += tar.raw[i];
	}
	sum += ' ' * 8;
	for (i =  156; i < 512 ; i++) {
		sum += tar.raw[i];
	}
	if (sum != strtol(tar.formated.chksum, NULL, 8)) {
		bb_error_msg("Invalid tar header checksum");
		return(EXIT_FAILURE);
	}

#ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
	if (longname) {
		file_header->name = longname;
		longname = NULL;
	}
	else if (linkname) {
		file_header->name = linkname;
		linkname = NULL;
	} else
#endif
	if (tar.formated.prefix[0] == 0) {
		file_header->name = strdup(tar.formated.name);
	} else {
		file_header->name = concat_path_file(tar.formated.prefix, tar.formated.name);
	}
	tmp = last_char_is(archive_handle->file_header->name, '/');
	if (tmp) {
		*tmp = '\0';
	}

	file_header->mode = strtol(tar.formated.mode, NULL, 8);
	file_header->uid = strtol(tar.formated.uid, NULL, 8);
	file_header->gid = strtol(tar.formated.gid, NULL, 8);
	file_header->size = strtol(tar.formated.size, NULL, 8);
	file_header->mtime = strtol(tar.formated.mtime, NULL, 8);
	file_header->link_name = (tar.formated.linkname[0] != '\0') ? 
	    bb_xstrdup(tar.formated.linkname) : NULL;
	file_header->device = (dev_t) ((strtol(tar.formated.devmajor, NULL, 8) << 8) +
				 strtol(tar.formated.devminor, NULL, 8));

	if (tar.formated.typeflag == '1') {
		bb_error_msg("WARNING: Converting hard link to symlink");
		file_header->mode |= S_IFLNK;
	}
#if defined CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY || defined CONFIG_FEATURE_TAR_GNU_EXTENSIONS
	/* Fix mode, used by the old format */
	switch (tar.formated.typeflag) {
# ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY
	case 0:
	case '0':
		file_header->mode |= S_IFREG;
		break;
	case '1':
//		bb_error_msg("Internal hard link not supported");
		break;
	case '2':
		file_header->mode |= S_IFLNK;
		break;
	case '3':
		file_header->mode |= S_IFCHR;
		break;
	case '4':
		file_header->mode |= S_IFBLK;
		break;
	case '5':
		file_header->mode |= S_IFDIR;
		break;
	case '6':
		file_header->mode |= S_IFIFO;
		break;
# endif
# ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
	case 'L': {
			longname = xmalloc(file_header->size + 1);
			archive_xread_all(archive_handle, longname, file_header->size);
			longname[file_header->size] = '\0';
			archive_handle->offset += file_header->size;

			return(get_header_tar(archive_handle));
		}
	case 'K': {
			linkname = xmalloc(file_header->size + 1);
			archive_xread_all(archive_handle, linkname, file_header->size);
			linkname[file_header->size] = '\0';
			archive_handle->offset += file_header->size;

			file_header->name = linkname;
			return(get_header_tar(archive_handle));
		}
	case 'D':
	case 'M':
	case 'N':
	case 'S':
	case 'V':
		bb_error_msg("Ignoring GNU extension type %c", tar.formated.typeflag);
# endif
	}
#endif
	if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
		archive_handle->action_header(archive_handle->file_header);
		archive_handle->flags |= ARCHIVE_EXTRACT_QUIET;
		archive_handle->action_data(archive_handle);
		archive_handle->passed = llist_add_to(archive_handle->passed, archive_handle->file_header->name);
	} else {
		data_skip(archive_handle);			
	}
	archive_handle->offset += file_header->size;

	return(EXIT_SUCCESS);
}