int main() {
  String exe_path = GetCurrentExecutableDirectory();

  TempDirectory temp_dir_1;
  TempDirectory temp_dir_2;

  // List of symbols in original libfoo.so and libfoo2.so, respectively.
  static const char* const kFooSymbols[] = {"Foo", NULL};
  static const char* const kFoo2Symbols[] = {"Foo2", NULL};

  // Copy libfoo.so to $TMPDIR1/libfoo.so
  CopyFile("libfoo.so", exe_path.c_str(), "libfoo.so", temp_dir_1.path());

  // Copy libfoo2.so to $TMPDIR2/libfoo.so
  CopyFile("libfoo2.so", exe_path.c_str(), "libfoo.so", temp_dir_2.path());

  // Create a new context object.
  crazy_context_t* context = crazy_context_create();
  crazy_library_t* library;

  // Reset search paths to a non-existing directory. Check that the library
  // can't be loaded.
  setenv("LD_LIBRARY_PATH", "/this-directory-does-not-exist", 1);
  crazy_context_reset_search_paths(context);
  CheckLibraryCantLoad("libfoo.so", context);

  // Add the search path to the current executable, this should load the
  // original
  // libfoo.so.
  crazy_context_add_search_path_for_address(context, (void*)&main);
  CheckLibrary("libfoo.so", kFooSymbols, kFoo2Symbols, context);

  // Reset search paths to use $TMPDIR2 then $TMPDIR1
  setenv("LD_LIBRARY_PATH", temp_dir_1.path(), 1);
  crazy_context_reset_search_paths(context);
  crazy_context_add_search_path(context, temp_dir_2.path());

  // Check that the copy of libfoo2.so is loaded.
  CheckLibrary("libfoo.so", kFoo2Symbols, kFooSymbols, context);

  // Reset search paths to use only $TMPDIR1
  crazy_context_reset_search_paths(context);

  // Check that the copy of libfoo.so is loaded.
  CheckLibrary("libfoo.so", kFooSymbols, kFoo2Symbols, context);

  crazy_context_destroy(context);

  return 0;
}
Exemple #2
0
bool MemFile::open (const std::string &path_, bool uncompress)
{
	MEMORY mem(MAX_IMAGE_SIZE + 1);
	size_t uRead = 0;

	// Check if zlib is available
#ifdef HAVE_ZLIBSTAT
	bool have_zlib = true;
#elif defined(HAVE_ZLIB)
	bool have_zlib = CheckLibrary("zlib", "zlibVersion") && zlibVersion()[0] == ZLIB_VERSION[0];
#else
	bool have_zlib = false;
#endif

#ifdef HAVE_ZLIB
	// Try opening as a zip file
	if (uncompress && have_zlib)
	{
		unzFile hfZip = unzOpen(path_.c_str());
		if (hfZip)
		{
			int nRet;
			unz_file_info sInfo;
			uLong ulMaxSize = 0;

			// Iterate through the contents of the zip looking for a file with a suitable size
			for (nRet = unzGoToFirstFile(hfZip); nRet == UNZ_OK; nRet = unzGoToNextFile(hfZip))
			{
				char szFile[MAX_PATH];

				// Get details of the current file
				unzGetCurrentFileInfo(hfZip, &sInfo, szFile, MAX_PATH, nullptr, 0, nullptr, 0);

				// Ignore directories and empty files
				if (!sInfo.uncompressed_size)
					continue;

				// If the file extension is recognised, read the file contents
				// ToDo: GetFileType doesn't really belong here?
				if (GetFileType(szFile) != ftUnknown && unzOpenCurrentFile(hfZip) == UNZ_OK)
				{
					nRet = unzReadCurrentFile(hfZip, mem, static_cast<unsigned int>(mem.size));
					unzCloseCurrentFile(hfZip);
					break;
				}

				// Rememeber the largest uncompressed file size
				if (sInfo.uncompressed_size > ulMaxSize)
					ulMaxSize = sInfo.uncompressed_size;
			}

			// Did we fail to find a matching extension?
			if (nRet == UNZ_END_OF_LIST_OF_FILE)
			{
				// Loop back over the archive
				for (nRet = unzGoToFirstFile(hfZip); nRet == UNZ_OK; nRet = unzGoToNextFile(hfZip))
				{
					// Get details of the current file
					unzGetCurrentFileInfo(hfZip, &sInfo, nullptr, 0, nullptr, 0, nullptr, 0);

					// Open the largest file found about
					if (sInfo.uncompressed_size == ulMaxSize && unzOpenCurrentFile(hfZip) == UNZ_OK)
					{
						nRet = unzReadCurrentFile(hfZip, mem, static_cast<unsigned int>(mem.size));
						unzCloseCurrentFile(hfZip);
						break;
					}
				}
			}

			// Close the zip archive
			unzClose(hfZip);

			// Stop if something went wrong
			if (nRet < 0)
				throw util::exception("zip extraction failed (", nRet, ")");

			uRead = nRet;
			m_compress = Compress::Zip;
		}
		else
		{
			// Open as gzipped or uncompressed
			gzFile gf = gzopen(path_.c_str(), "rb");
			if (gf == Z_NULL)
				throw posix_error(errno, path_.c_str());

			uRead = gzread(gf, mem, static_cast<unsigned>(mem.size));
			m_compress = (gztell(gf) != FileSize(path_)) ? Compress::Gzip : Compress::None;
			gzclose(gf);
		}
	}
	else
#endif // HAVE_ZLIB
	{
		// Open as normal file if we couldn't use zlib above
		FILE *f = fopen(path_.c_str(), "rb");
		if (!f)
			throw posix_error(errno, path_.c_str());

		uRead = fread(mem, 1, mem.size, f);
		fclose(f);
		m_compress = Compress::None;
	}


	// zip compressed? (and not handled above)
	if (uncompress && mem[0U] == 'P' && mem[1U] == 'K')
		throw util::exception("zlib (zlib1.dll) is required for zip support");

	// gzip compressed?
	if (uncompress && mem[0U] == 0x1f && mem[1U] == 0x8b && mem[2U] == 0x08)
	{
		if (!have_zlib)
			throw util::exception("zlib (zlib1.dll) is required for gzip support");

#ifdef HAVE_ZLIB
		MEMORY mem2(MAX_IMAGE_SIZE + 1);
		uint8_t flags = mem[3];
		auto pb = mem.pb + 10, pbEnd = mem.pb + mem.size;

		if (flags & 0x04)	// EXTRA_FIELD
		{
			if (pb < pbEnd - 1)
				pb += 2 + pb[0] + (pb[1] << 8);
		}

		if (flags & 0x08 || flags & 0x10)	// ORIG_NAME or COMMENT
		{
			while (pb < pbEnd && *pb++);
		}

		if (flags & 0x02)	// HEAD_CRC
			pb += 2;

		z_stream stream = {};
		stream.next_in = pb;
		stream.avail_in = (pb < pbEnd) ? static_cast<uInt>(pbEnd - pb) : 0;
		stream.next_out = mem2.pb;
		stream.avail_out = mem2.size;

		auto zerr = inflateInit2(&stream, -MAX_WBITS);
		if (zerr == Z_OK)
		{
			zerr = inflate(&stream, Z_FINISH);
			inflateEnd(&stream);
		}

		if (zerr != Z_STREAM_END)
			throw util::exception("gzip decompression failed (", zerr, ")");

		memcpy(mem.pb, mem2.pb, uRead = stream.total_out);
		m_compress = Compress::Zip;
#endif
	}

	// bzip2 compressed?
	if (uncompress && mem[0U] == 'B' && mem[1U] == 'Z')
	{
#ifdef HAVE_BZIP2
		if (!CheckLibrary("bzip2", "BZ2_bzBuffToBuffDecompress"))
#endif
			throw util::exception("libbz2 (bzip2.dll) is required for bzip2 support");

#ifdef HAVE_BZIP2
		MEMORY mem2(MAX_IMAGE_SIZE + 1);

		auto uBzRead = static_cast<unsigned>(mem2.size);
		auto bzerr = BZ2_bzBuffToBuffDecompress(reinterpret_cast<char *>(mem2.pb), &uBzRead, reinterpret_cast<char *>(mem.pb), uRead, 0, 0);
		if (bzerr != BZ_OK)
			throw util::exception("bzip2 decompression failed (", bzerr, ")");

		memcpy(mem.pb, mem2.pb, uRead = uBzRead);
		m_compress = Compress::Bzip2;
#endif // HAVE_BZIP2
	}

	if (uRead <= MAX_IMAGE_SIZE)
		return open(mem.pb, static_cast<int>(uRead), path_);

	throw util::exception("file size too big");
}