std::string GetExecutablePath() { #if defined(__linux__) std::string path; android::base::Readlink("/proc/self/exe", &path); return path; #elif defined(__APPLE__) char path[PATH_MAX + 1]; uint32_t path_len = sizeof(path); int rc = _NSGetExecutablePath(path, &path_len); if (rc < 0) { std::unique_ptr<char> path_buf(new char[path_len]); _NSGetExecutablePath(path_buf.get(), &path_len); return path_buf.get(); } return path; #elif defined(_WIN32) char path[PATH_MAX + 1]; DWORD result = GetModuleFileName(NULL, path, sizeof(path) - 1); if (result == 0 || result == sizeof(path) - 1) return ""; path[PATH_MAX - 1] = 0; return path; #else #error unknown OS #endif }
UNKNOWN_IMPL_END // *** IInArchive *** // read archive contents from IInStream // return S_FALSE if format is not recognized STDMETHODIMP Open(IInStream* stream, const UInt64* max_check_start_position, IArchiveOpenCallback* open_archive_callback) { COM_ERROR_HANDLER_BEGIN in_stream = stream; UInt64 file_size = 0; CHECK_COM(in_stream->Seek(0, STREAM_SEEK_END, &file_size)); CHECK_COM(in_stream->Seek(0, STREAM_SEEK_SET, nullptr)); CHECK_COM(open_archive_callback->SetTotal(nullptr, &file_size)); char sig_buf[c_sig_size]; if (read_stream(in_stream, sig_buf, c_sig_size) != c_sig_size) return S_FALSE; if (memcmp(c_sig, sig_buf, c_sig_size) != 0) return S_FALSE; if (read_stream(in_stream, &comp_level, sizeof(comp_level)) != sizeof(comp_level)) return S_FALSE; UInt64 file_count = 0; list<FileInfo> file_list; size_t path_buf_size = MAX_PATH; unique_ptr<wchar_t[]> path_buf(new wchar_t[path_buf_size]); while (true) { FileInfo file_info; UInt32 path_size; UInt32 size_read = read_stream(in_stream, &path_size, sizeof(path_size)); if (size_read == 0) break; if (size_read != sizeof(path_size)) return S_FALSE; if (path_size > 32000) return S_FALSE; if (path_size > path_buf_size) { path_buf_size = path_size; path_buf.reset(new wchar_t[path_buf_size]); } if (read_stream(in_stream, path_buf.get(), path_size * sizeof(wchar_t)) != path_size * sizeof(wchar_t)) return S_FALSE; file_info.path.assign(path_buf.get(), path_size); if (read_stream(in_stream, &file_info.size, sizeof(file_info.size)) != sizeof(file_info.size)) return S_FALSE; CHECK_COM(in_stream->Seek(0, STREAM_SEEK_CUR, &file_info.offset)); UInt64 file_pos; if (in_stream->Seek(file_info.size, STREAM_SEEK_CUR, &file_pos) != S_OK) return S_FALSE; file_list.push_back(file_info); file_count++; CHECK_COM(open_archive_callback->SetCompleted(&file_count, &file_pos)); } files.reserve(file_list.size()); copy(file_list.begin(), file_list.end(), back_inserter(files)); return S_OK; COM_ERROR_HANDLER_END }