File diff r24528:a7298f737f00 → r24529:3dec691db49a
src/fileio.cpp
Show inline comments
 
@@ -243,13 +243,13 @@ static_assert(lengthof(_subdirs) == NUM_
 
 * The search paths OpenTTD could search through.
 
 * At least one of the slots has to be filled with a path.
 
 * An empty string tells that there is no such path for the
 
 * current operating system.
 
 */
 
std::array<std::string, NUM_SEARCHPATHS> _searchpaths;
 
TarList _tar_list[NUM_SUBDIRS];
 
std::array<TarList, NUM_SUBDIRS> _tar_list;
 
TarFileList _tar_filelist[NUM_SUBDIRS];
 

	
 
typedef std::map<std::string, std::string> TarLinkList;
 
static TarLinkList _tar_linklist[NUM_SUBDIRS]; ///< List of directory links
 

	
 
/**
 
@@ -387,13 +387,13 @@ static FILE *FioFOpenFileSp(const std::s
 
 * @param[out] filesize If not \c nullptr, size of the opened file.
 
 * @return File handle of the opened file, or \c nullptr if the file is not available.
 
 * @note The file is read from within the tar file, and may not return \c EOF after reading the whole file.
 
 */
 
FILE *FioFOpenFileTar(const TarFileListEntry &entry, size_t *filesize)
 
{
 
	FILE *f = fopen(entry.tar_filename, "rb");
 
	FILE *f = fopen(entry.tar_filename.c_str(), "rb");
 
	if (f == nullptr) return f;
 

	
 
	if (fseek(f, entry.position, SEEK_SET) < 0) {
 
		fclose(f);
 
		return nullptr;
 
	}
 
@@ -610,22 +610,22 @@ uint TarScanner::DoScan(Subdirectory sd)
 
/**
 
 * Add a single file to the scanned files of a tar, circumventing the scanning code.
 
 * @param sd       The sub directory the file is in.
 
 * @param filename The name of the file to add.
 
 * @return True if the additions went correctly.
 
 */
 
bool TarScanner::AddFile(Subdirectory sd, const char *filename)
 
bool TarScanner::AddFile(Subdirectory sd, const std::string &filename)
 
{
 
	this->subdir = sd;
 
	return this->AddFile(filename, 0);
 
}
 

	
 
bool TarScanner::AddFile(const char *filename, size_t basepath_length, const char *tar_filename)
 
bool TarScanner::AddFile(const std::string &filename, size_t basepath_length, const std::string &tar_filename)
 
{
 
	/* No tar within tar. */
 
	assert(tar_filename == nullptr);
 
	assert(tar_filename.empty());
 

	
 
	/* The TAR-header, repeated for every file */
 
	struct TarHeader {
 
		char name[100];      ///< Name of the file
 
		char mode[8];
 
		char uid[8];
 
@@ -647,22 +647,20 @@ bool TarScanner::AddFile(const char *fil
 
	};
 

	
 
	/* Check if we already seen this file */
 
	TarList::iterator it = _tar_list[this->subdir].find(filename);
 
	if (it != _tar_list[this->subdir].end()) return false;
 

	
 
	FILE *f = fopen(filename, "rb");
 
	FILE *f = fopen(filename.c_str(), "rb");
 
	/* Although the file has been found there can be
 
	 * a number of reasons we cannot open the file.
 
	 * Most common case is when we simply have not
 
	 * been given read access. */
 
	if (f == nullptr) return false;
 

	
 
	const char *dupped_filename = stredup(filename);
 
	_tar_list[this->subdir][filename].filename = dupped_filename;
 
	_tar_list[this->subdir][filename].dirname = nullptr;
 
	_tar_list[this->subdir][filename] = std::string{};
 

	
 
	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];
 
@@ -681,13 +679,13 @@ bool TarScanner::AddFile(const char *fil
 

	
 
		/* 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);
 
			DEBUG(misc, 0, "The file '%s' isn't a valid tar-file", filename.c_str());
 
			fclose(f);
 
			return false;
 
		}
 

	
 
		name[0] = '\0';
 

	
 
@@ -711,13 +709,13 @@ bool TarScanner::AddFile(const char *fil
 
				if (skip == 0) break;
 

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

	
 
				/* Store this entry in the list */
 
				TarFileListEntry entry;
 
				entry.tar_filename = dupped_filename;
 
				entry.tar_filename = filename;
 
				entry.size         = skip;
 
				entry.position     = pos;
 

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

	
 
@@ -779,13 +777,13 @@ bool TarScanner::AddFile(const char *fil
 
						/* Append at end of 'dest' */
 
						if (destpos != dest) destpos = strecpy(destpos, PATHSEP, lastof(dest));
 
						destpos = strecpy(destpos, pos, lastof(dest));
 
					}
 

	
 
					if (destpos >= lastof(dest)) {
 
						DEBUG(misc, 0, "The length of a link in tar-file '%s' is too large (malformed?)", filename);
 
						DEBUG(misc, 0, "The length of a link in tar-file '%s' is too large (malformed?)", filename.c_str());
 
						fclose(f);
 
						return false;
 
					}
 

	
 
					pos = next;
 
				}
 
@@ -800,31 +798,31 @@ bool TarScanner::AddFile(const char *fil
 
			case '5': // directory
 
				/* Convert to lowercase and our PATHSEPCHAR */
 
				SimplifyFileName(name);
 

	
 
				/* Store the first directory name we detect */
 
				DEBUG(misc, 6, "Found dir in tar: %s", name);
 
				if (_tar_list[this->subdir][filename].dirname == nullptr) _tar_list[this->subdir][filename].dirname = stredup(name);
 
				if (_tar_list[this->subdir][filename].empty()) _tar_list[this->subdir][filename] = name;
 
				break;
 

	
 
			default:
 
				/* Ignore other types */
 
				break;
 
		}
 

	
 
		/* Skip to the next block.. */
 
		skip = Align(skip, 512);
 
		if (fseek(f, skip, SEEK_CUR) < 0) {
 
			DEBUG(misc, 0, "The file '%s' can't be read as a valid tar-file", filename);
 
			DEBUG(misc, 0, "The file '%s' can't be read as a valid tar-file", filename.c_str());
 
			fclose(f);
 
			return false;
 
		}
 
		pos += skip;
 
	}
 

	
 
	DEBUG(misc, 1, "Found tar '%s' with " PRINTF_SIZE " new files", filename, num);
 
	DEBUG(misc, 1, "Found tar '%s' with " PRINTF_SIZE " new files", filename.c_str(), num);
 
	fclose(f);
 

	
 
	/* Resolve file links and store directory links.
 
	 * We restrict usage of links to two cases:
 
	 *  1) Links to directories:
 
	 *      Both the source path and the destination path must NOT contain any further links.
 
@@ -852,16 +850,16 @@ bool TarScanner::AddFile(const char *fil
 
bool ExtractTar(const std::string &tar_filename, Subdirectory subdir)
 
{
 
	TarList::iterator it = _tar_list[subdir].find(tar_filename);
 
	/* We don't know the file. */
 
	if (it == _tar_list[subdir].end()) return false;
 

	
 
	const char *dirname = (*it).second.dirname;
 
	const auto &dirname = (*it).second;
 

	
 
	/* The file doesn't have a sub directory! */
 
	if (dirname == nullptr) {
 
	if (dirname.empty()) {
 
		DEBUG(misc, 1, "Extracting %s failed; archive rejected, the contents must be in a sub directory", tar_filename.c_str());
 
		return false;
 
	}
 

	
 
	std::string filename = tar_filename;
 
	auto p = filename.find_last_of(PATHSEPCHAR);
 
@@ -1305,13 +1303,13 @@ static uint ScanPath(FileScanner *fs, co
 
			if (!recursive) continue;
 
			if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) continue;
 
			AppendPathSeparator(filename);
 
			num += ScanPath(fs, extension, filename.c_str(), basepath_length, recursive);
 
		} else if (S_ISREG(sb.st_mode)) {
 
			/* File */
 
			if (MatchesExtension(extension, filename.c_str()) && fs->AddFile(filename.c_str(), basepath_length, nullptr)) num++;
 
			if (MatchesExtension(extension, filename.c_str()) && fs->AddFile(filename, basepath_length, {})) num++;
 
		}
 
	}
 

	
 
	closedir(dir);
 

	
 
	return num;
 
@@ -1323,15 +1321,15 @@ static uint ScanPath(FileScanner *fs, co
 
 * @param extension the extension of files to search for.
 
 * @param tar       the tar to search in.
 
 */
 
static uint ScanTar(FileScanner *fs, const char *extension, TarFileList::iterator tar)
 
{
 
	uint num = 0;
 
	const char *filename = (*tar).first.c_str();
 
	const auto &filename = (*tar).first;
 

	
 
	if (MatchesExtension(extension, filename) && fs->AddFile(filename, 0, (*tar).second.tar_filename)) num++;
 
	if (MatchesExtension(extension, filename.c_str()) && fs->AddFile(filename, 0, (*tar).second.tar_filename)) num++;
 

	
 
	return num;
 
}
 

	
 
/**
 
 * Scan for files with the given extension in the given search path.