Ejemplo n.º 1
0
FileInfo FileSourceZip::Lookup(const std::string &path)
{
	const Directory *dir;
	std::string filename;
	if (!FindDirectoryAndFile(path, dir, filename))
		return MakeFileInfo(path, FileInfo::FT_NON_EXISTENT);

	std::map<std::string,FileStat>::const_iterator i = dir->files.find(filename);
	if (i == dir->files.end())
		return MakeFileInfo(path, FileInfo::FT_NON_EXISTENT);

	return (*i).second.info;
}
Ejemplo n.º 2
0
	RefCountedPtr<FileData> FileSourceFS::ReadFile(const std::string &path)
	{
		const std::string fullpath = JoinPathBelow(GetRoot(), path);
		FILE *fl = fopen(fullpath.c_str(), "rb");
		if (!fl) {
			return RefCountedPtr<FileData>(0);
		} else {
			fseek(fl, 0, SEEK_END);
			long sz = ftell(fl);
			fseek(fl, 0, SEEK_SET);
			char *data = reinterpret_cast<char*>(std::malloc(sz));
			if (!data) {
				// XXX handling memory allocation failure gracefully is too hard right now
				fprintf(stderr, "failed when allocating buffer for '%s'\n", fullpath.c_str());
				fclose(fl);
				abort();
			}
			size_t read_size = fread(data, 1, sz, fl);
			if (read_size != size_t(sz)) {
				fprintf(stderr, "file '%s' truncated!\n", fullpath.c_str());
				memset(data + read_size, 0xee, sz - read_size);
			}
			fclose(fl);
			return RefCountedPtr<FileData>(new FileDataMalloc(MakeFileInfo(path, FileInfo::FT_FILE), sz, data));
		}
	}
Ejemplo n.º 3
0
FileSourceZip::FileSourceZip(FileSourceFS &fs, const std::string &zipPath) : FileSource(zipPath), m_archive(0)
{
	mz_zip_archive *zip = static_cast<mz_zip_archive*>(std::calloc(1, sizeof(mz_zip_archive)));
	FILE *file = fs.OpenReadStream(zipPath);
	if (!mz_zip_reader_init_file_stream(zip, file, 0)) {
		Output("FileSourceZip: unable to open '%s'\n", zipPath.c_str());
		std::free(zip);
		return;
	}

	mz_zip_archive_file_stat zipStat;

	Uint32 numFiles = mz_zip_reader_get_num_files(zip);
	for (Uint32 i = 0; i < numFiles; i++) {
		if (mz_zip_reader_file_stat(zip, i, &zipStat)) {
			bool is_dir = mz_zip_reader_is_file_a_directory(zip, i);
			if (!mz_zip_reader_is_file_encrypted(zip, i)) {
				std::string fname = zipStat.m_filename;
				if ((fname.size() > 1) && (fname[fname.size()-1] == '/')) {
					fname.resize(fname.size() - 1);
				}
				AddFile(zipStat.m_filename, FileStat(i, zipStat.m_uncomp_size,
					MakeFileInfo(fname, is_dir ? FileInfo::FT_DIR : FileInfo::FT_FILE)));
			}
		}
	}

	m_archive = static_cast<void*>(zip);
}
Ejemplo n.º 4
0
void FileSourceZip::AddFile(const std::string &path, const FileStat &fileStat)
{
	std::vector<std::string> fragments;
	SplitPath(path, fragments);

	assert(fragments.size() > 0);

	Directory *dir = &m_root;

	if (fragments.size() > 1) {
		std::string fullPath;

		for (unsigned int i = 0; i < fragments.size()-1; i++) {
			fullPath += ((i > 0) ? "/" : "") + fragments[i];

			std::map<std::string,FileStat>::const_iterator it = dir->files.find(fragments[i]);
			if (it == dir->files.end())
				dir->files.insert(std::make_pair(fragments[i], FileStat(Uint32(-1), 0, MakeFileInfo(fullPath, FileInfo::FT_DIR))));
			dir = &(dir->subdirs[fragments[i]]);
		}
	}

	const std::string &filename = fragments.back();

	if (fileStat.info.IsDir())
		dir->subdirs.insert(std::make_pair(filename, Directory()));
	
	dir->files.insert(std::make_pair(filename, fileStat));
}
Ejemplo n.º 5
0
	FileInfo FileSourceUnion::Lookup(const std::string &path)
	{
		for (std::vector<FileSource*>::const_iterator
			it = m_sources.begin(); it != m_sources.end(); ++it)
		{
			FileInfo info = (*it)->Lookup(path);
			if (info.Exists()) { return info; }
		}
		return MakeFileInfo(path, FileInfo::FT_NON_EXISTENT);
	}
Ejemplo n.º 6
0
	bool FileSourceFS::ReadDirectory(const std::string &dirpath, std::vector<FileInfo> &output)
	{
		const std::string fulldirpath = JoinPathBelow(GetRoot(), dirpath);
		DIR *dir = opendir(fulldirpath.c_str());
		if (!dir) { return false; }
		struct dirent *entry;

		const size_t output_head_size = output.size();

		while ((entry = readdir(dir))) {
			if (strcmp(entry->d_name, ".") == 0) continue;
			if (strcmp(entry->d_name, "..") == 0) continue;

			const std::string fullpath = JoinPath(fulldirpath, entry->d_name);

			FileInfo::FileType ty;
			switch (entry->d_type) {
				case DT_DIR: ty = FileInfo::FT_DIR; break;
				case DT_REG: ty = FileInfo::FT_FILE; break;
				case DT_LNK: case DT_UNKNOWN:
				{
					// if readdir() can't tell us whether we've got a file or directory then we need to stat
					// also stat for links to traverse them
					struct stat statinfo;
					if (stat(fullpath.c_str(), &statinfo) == 0) {
						if (S_ISREG(statinfo.st_mode)) {
							ty = FileInfo::FT_FILE;
						} else if (S_ISDIR(statinfo.st_mode)) {
							ty = FileInfo::FT_DIR;
						} else {
							ty = FileInfo::FT_SPECIAL;
						}
					} else {
						// XXX error out here?
						ty = FileInfo::FT_NON_EXISTENT;
					}
					break;
				}
				default: ty = FileInfo::FT_SPECIAL; break;
			}

			output.push_back(MakeFileInfo(fullpath.substr(GetRoot().size() + 1), ty));
		}

		closedir(dir);

		std::sort(output.begin() + output_head_size, output.end());
		return true;
	}
Ejemplo n.º 7
0
	RefCountedPtr<FileData> FileSourceFS::ReadFile(const std::string &path)
	{
		const std::string fullpath = JoinPathBelow(GetRoot(), path);
		const std::wstring wfullpath = transcode_utf8_to_utf16(fullpath);
		HANDLE filehandle = CreateFileW(wfullpath.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
		if (filehandle == INVALID_HANDLE_VALUE)
			return RefCountedPtr<FileData>(0);
		else {
			const Time::DateTime modtime = file_modtime_for_handle(filehandle);

			LARGE_INTEGER large_size;
			if (!GetFileSizeEx(filehandle, &large_size)) {
				Output("failed to get file size for '%s'\n", fullpath.c_str());
				CloseHandle(filehandle);
				abort();
			}
			size_t size = size_t(large_size.QuadPart);

			char *data = static_cast<char*>(std::malloc(size));
			if (!data) {
				// XXX handling memory allocation failure gracefully is too hard right now
				Output("failed when allocating buffer for '%s'\n", fullpath.c_str());
				CloseHandle(filehandle);
				abort();
			}

			if (size > 0x7FFFFFFFull) {
				Output("file '%s' is too large (can't currently cope with files > 2GB)\n", fullpath.c_str());
				CloseHandle(filehandle);
				abort();
			}

			DWORD read_size;
			BOOL ret = ::ReadFile(filehandle, static_cast<LPVOID>(data), (DWORD)size, &read_size, 0);
			if (!ret) {
				Output("error while reading file '%s'\n", fullpath.c_str());
				CloseHandle(filehandle);
				abort();
			}
			if (size_t(read_size) != size) {
				Output("file '%s' truncated\n", fullpath.c_str());
				memset(data + read_size, 0xee, size - read_size);
			}

			CloseHandle(filehandle);

			return RefCountedPtr<FileData>(new FileDataMalloc(MakeFileInfo(path, FileInfo::FT_FILE, modtime), size, data));
		}
	}
Ejemplo n.º 8
0
	FileInfo FileSourceFS::Lookup(const std::string &path)
	{
		const std::string fullpath = JoinPathBelow(GetRoot(), path);
		const std::wstring wfullpath = transcode_utf8_to_utf16(fullpath);
		DWORD attrs = GetFileAttributesW(wfullpath.c_str());
		const FileInfo::FileType ty = file_type_for_attributes(attrs);
		Time::DateTime modtime;
		if (ty == FileInfo::FT_FILE || ty == FileInfo::FT_DIR) {
			HANDLE hfile = CreateFileW(wfullpath.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
			if (hfile != INVALID_HANDLE_VALUE) {
				modtime = file_modtime_for_handle(hfile);
				CloseHandle(hfile);
			}
		}
		return MakeFileInfo(path, ty, modtime);
	}
Ejemplo n.º 9
0
	FileInfo FileSourceFS::Lookup(const std::string &path)
	{
		const std::string fullpath = JoinPathBelow(GetRoot(), path);
		struct stat statinfo;
		FileInfo::FileType ty;
		if (stat(fullpath.c_str(), &statinfo) == 0) {
			if (S_ISREG(statinfo.st_mode)) {
				ty = FileInfo::FT_FILE;
			} else if (S_ISDIR(statinfo.st_mode)) {
				ty = FileInfo::FT_DIR;
			} else {
				ty = FileInfo::FT_SPECIAL;
			}
		} else {
			ty = FileInfo::FT_NON_EXISTENT;
		}
		return MakeFileInfo(path, ty);
	}
Ejemplo n.º 10
0
FileSourceZip::FileSourceZip(const std::string &zipPath) : FileSource(zipPath), m_archive(0)
{
	mz_zip_archive *zip = reinterpret_cast<mz_zip_archive*>(std::calloc(1, sizeof(mz_zip_archive)));
	if (!mz_zip_reader_init_file(zip, zipPath.c_str(), 0)) {
		printf("FileSourceZip: unable to open '%s'\n", zipPath.c_str());
		std::free(zip);
		return;
	}

	mz_zip_archive_file_stat zipStat;

	Uint32 numFiles = mz_zip_reader_get_num_files(zip);
	for (Uint32 i = 0; i < numFiles; i++) {
		if (mz_zip_reader_file_stat(zip, i, &zipStat)) {
			bool is_dir = mz_zip_reader_is_file_a_directory(zip, i);
			if (!mz_zip_reader_is_file_encrypted(zip, i))
				AddFile(zipStat.m_filename, FileStat(i, zipStat.m_uncomp_size, MakeFileInfo(zipStat.m_filename, is_dir ? FileInfo::FT_DIR : FileInfo::FT_FILE)));
		}
	}

	m_archive = reinterpret_cast<void*>(zip);
}
Ejemplo n.º 11
0
	bool FileSourceFS::ReadDirectory(const std::string &dirpath, std::vector<FileInfo> &output)
	{
		size_t output_head_size = output.size();
		const std::wstring wsearchglob = transcode_utf8_to_utf16(JoinPathBelow(GetRoot(), dirpath)) + L"/*";
		WIN32_FIND_DATAW findinfo;
		HANDLE dirhandle = FindFirstFileW(wsearchglob.c_str(), &findinfo);
		DWORD err;

		if (dirhandle == INVALID_HANDLE_VALUE) {
			err = GetLastError();
			// if the directory was empty we succeeded even though FindFirstFile failed
			return (err == ERROR_FILE_NOT_FOUND);
		}

		do {
			std::string fname = transcode_utf16_to_utf8(findinfo.cFileName, wcslen(findinfo.cFileName));
			if (fname != "." && fname != "..") {
				const FileInfo::FileType ty = file_type_for_attributes(findinfo.dwFileAttributes);
				const Time::DateTime modtime = datetime_for_filetime(findinfo.ftLastWriteTime);
				output.push_back(MakeFileInfo(JoinPath(dirpath, fname), ty, modtime));
			}

			if (! FindNextFileW(dirhandle, &findinfo)) {
				err = GetLastError();
			} else
				err = ERROR_SUCCESS;
		} while (err == ERROR_SUCCESS);
		FindClose(dirhandle);

		if (err != ERROR_NO_MORE_FILES) {
			output.resize(output_head_size);
			return false;
		}

		std::sort(output.begin() + output_head_size, output.end());
		return true;
	}
Ejemplo n.º 12
0
	FileInfo FileSource::MakeFileInfo(const std::string &path, FileInfo::FileType fileType)
	{
		return MakeFileInfo(path, fileType, Time::DateTime());
	}