Changeset - r21002:46db63e452df
[Not reviewed]
master
0 1 0
rubidium - 11 years ago 2013-11-23 21:42:45
rubidium@openttd.org
(svn r26077) -Codechange: handle strings like strings when scanning a tar instead of merely blobs of memory
1 file changed with 7 insertions and 16 deletions:
0 comments (0 inline, 0 general)
src/fileio.cpp
Show inline comments
 
@@ -752,66 +752,58 @@ bool TarScanner::AddFile(const char *fil
 
	 * Most common case is when we simply have not
 
	 * been given read access. */
 
	if (f == NULL) return false;
 

	
 
	const char *dupped_filename = strdup(filename);
 
	_tar_list[this->subdir][filename].filename = dupped_filename;
 
	_tar_list[this->subdir][filename].dirname = NULL;
 

	
 
	TarLinkList links; ///< Temporary list to collect links
 

	
 
	TarHeader th;
 
	char buf[sizeof(th.name) + 1], *end;
 
	char name[sizeof(th.prefix) + 1 + sizeof(th.name) + 1];
 
	char name[sizeof(th.prefix) + 1 + sizeof(th.name) + 1] = "";
 
	char link[sizeof(th.linkname) + 1];
 
	char dest[sizeof(th.prefix) + 1 + sizeof(th.name) + 1 + 1 + sizeof(th.linkname) + 1];
 
	size_t num = 0, pos = 0;
 

	
 
	/* Make a char of 512 empty bytes */
 
	char empty[512];
 
	memset(&empty[0], 0, sizeof(empty));
 

	
 
	for (;;) { // Note: feof() always returns 'false' after 'fseek()'. Cool, isn't it?
 
		size_t num_bytes_read = fread(&th, 1, 512, f);
 
		if (num_bytes_read != 512) break;
 
		pos += num_bytes_read;
 

	
 
		/* Check if we have the new tar-format (ustar) or the old one (a lot of zeros after 'link' field) */
 
		if (strncmp(th.magic, "ustar", 5) != 0 && memcmp(&th.magic, &empty[0], 512 - offsetof(TarHeader, magic)) != 0) {
 
			/* If we have only zeros in the block, it can be an end-of-file indicator */
 
			if (memcmp(&th, &empty[0], 512) == 0) continue;
 

	
 
			DEBUG(misc, 0, "The file '%s' isn't a valid tar-file", filename);
 
			return false;
 
		}
 

	
 
		name[0] = '\0';
 
		size_t len = 0;
 

	
 
		/* The prefix contains the directory-name */
 
		if (th.prefix[0] != '\0') {
 
			memcpy(name, th.prefix, sizeof(th.prefix));
 
			name[sizeof(th.prefix)] = '\0';
 
			len = strlen(name);
 
			name[len] = PATHSEPCHAR;
 
			len++;
 
			ttd_strlcpy(name, th.prefix, lengthof(name));
 
			ttd_strlcat(name, PATHSEP, lengthof(name));
 
		}
 

	
 
		/* Copy the name of the file in a safe way at the end of 'name' */
 
		memcpy(&name[len], th.name, sizeof(th.name));
 
		name[len + sizeof(th.name)] = '\0';
 
		ttd_strlcat(name, th.name, lengthof(name));
 

	
 
		/* Calculate the size of the file.. for some strange reason this is stored as a string */
 
		memcpy(buf, th.size, sizeof(th.size));
 
		buf[sizeof(th.size)] = '\0';
 
		ttd_strlcpy(buf, th.size, lengthof(buf));
 
		size_t skip = strtoul(buf, &end, 8);
 

	
 
		switch (th.typeflag) {
 
			case '\0':
 
			case '0': { // regular file
 
				/* Ignore empty files */
 
				if (skip == 0) break;
 

	
 
				if (strlen(name) == 0) break;
 

	
 
				/* Store this entry in the list */
 
				TarFileListEntry entry;
 
@@ -822,42 +814,41 @@ bool TarScanner::AddFile(const char *fil
 
				/* Convert to lowercase and our PATHSEPCHAR */
 
				SimplifyFileName(name);
 

	
 
				DEBUG(misc, 6, "Found file in tar: %s (" PRINTF_SIZE " bytes, " PRINTF_SIZE " offset)", name, skip, pos);
 
				if (_tar_filelist[this->subdir].insert(TarFileList::value_type(name, entry)).second) num++;
 

	
 
				break;
 
			}
 

	
 
			case '1': // hard links
 
			case '2': { // symbolic links
 
				/* Copy the destination of the link in a safe way at the end of 'linkname' */
 
				memcpy(link, th.linkname, sizeof(th.linkname));
 
				link[sizeof(th.linkname)] = '\0';
 
				ttd_strlcpy(link, th.linkname, lengthof(link));
 

	
 
				if (strlen(name) == 0 || strlen(link) == 0) break;
 

	
 
				/* Convert to lowercase and our PATHSEPCHAR */
 
				SimplifyFileName(name);
 
				SimplifyFileName(link);
 

	
 
				/* Only allow relative links */
 
				if (link[0] == PATHSEPCHAR) {
 
					DEBUG(misc, 1, "Ignoring absolute link in tar: %s -> %s", name, link);
 
					break;
 
				}
 

	
 
				/* Process relative path.
 
				 * Note: The destination of links must not contain any directory-links. */
 
				strecpy(dest, name, lastof(dest));
 
				ttd_strlcpy(dest, name, lengthof(dest));
 
				char *destpos = strrchr(dest, PATHSEPCHAR);
 
				if (destpos == NULL) destpos = dest;
 
				*destpos = '\0';
 

	
 
				char *pos = link;
 
				while (*pos != '\0') {
 
					char *next = strchr(link, PATHSEPCHAR);
 
					if (next == NULL) next = pos + strlen(pos);
 

	
 
					/* Skip '.' (current dir) */
 
					if (next != pos + 1 || pos[0] != '.') {
 
						if (next == pos + 2 && pos[0] == '.' && pos[1] == '.') {
0 comments (0 inline, 0 general)