ppsspp/Core/FileLoaders/LocalFileLoader.cpp
Henrik Rydgård ff8148dd92 Move native/util, native/data and native/i18 to Common/Data.
Also move colorutil.cpp/h

linking build fix experiment

Delete a bunch of unused CMakeLists.txt files

CMakeLists.txt linking fix

Don't include NativeApp.h from any headers.

Android.mk buildfix

Half of the UWP fix

Buildfix

Minor project file cleanup

Buildfixes

Guess what? More buildfixes!
2020-10-04 07:28:29 +02:00

153 lines
4.5 KiB
C++

// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <cstdio>
#include "ppsspp_config.h"
#include "Common/Data/Encoding/Utf8.h"
#include "file/file_util.h"
#include "Common/FileUtil.h"
#include "Core/FileLoaders/LocalFileLoader.h"
#ifdef _WIN32
#include "Common/CommonWindows.h"
#else
#include <fcntl.h>
#endif
LocalFileLoader::LocalFileLoader(const std::string &filename)
: filesize_(0), filename_(filename) {
if (filename.empty()) {
ERROR_LOG(FILESYS, "LocalFileLoader can't load empty filenames");
return;
}
#ifndef _WIN32
fd_ = open(filename.c_str(), O_RDONLY | O_CLOEXEC);
if (fd_ == -1) {
return;
}
#if PPSSPP_PLATFORM(ANDROID) || (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS < 64)
off64_t off = lseek64(fd_, 0, SEEK_END);
filesize_ = off;
lseek64(fd_, 0, SEEK_SET);
#else
off_t off = lseek(fd_, 0, SEEK_END);
filesize_ = off;
lseek(fd_, 0, SEEK_SET);
#endif
#else // _WIN32
const DWORD access = GENERIC_READ, share = FILE_SHARE_READ, mode = OPEN_EXISTING, flags = FILE_ATTRIBUTE_NORMAL;
#if PPSSPP_PLATFORM(UWP)
handle_ = CreateFile2(ConvertUTF8ToWString(filename).c_str(), access, share, mode, nullptr);
#else
handle_ = CreateFile(ConvertUTF8ToWString(filename).c_str(), access, share, nullptr, mode, flags, nullptr);
#endif
if (handle_ == INVALID_HANDLE_VALUE) {
return;
}
LARGE_INTEGER end_offset;
const LARGE_INTEGER zero = { 0 };
if (SetFilePointerEx(handle_, zero, &end_offset, FILE_END) == 0) {
// Couldn't seek in the file. Close it and give up? This should never happen.
CloseHandle(handle_);
handle_ = INVALID_HANDLE_VALUE;
return;
}
filesize_ = end_offset.QuadPart;
SetFilePointerEx(handle_, zero, nullptr, FILE_BEGIN);
#endif // _WIN32
}
LocalFileLoader::~LocalFileLoader() {
#ifndef _WIN32
if (fd_ != -1) {
close(fd_);
}
#else
if (handle_ != INVALID_HANDLE_VALUE) {
CloseHandle(handle_);
}
#endif
}
bool LocalFileLoader::Exists() {
// If we couldn't open it for reading, we say it does not exist.
#ifndef _WIN32
if (fd_ != -1 || IsDirectory()) {
#else
if (handle_ != INVALID_HANDLE_VALUE || IsDirectory()) {
#endif
FileInfo info;
return getFileInfo(filename_.c_str(), &info);
}
return false;
}
bool LocalFileLoader::IsDirectory() {
FileInfo info;
if (getFileInfo(filename_.c_str(), &info)) {
return info.isDirectory;
}
return false;
}
s64 LocalFileLoader::FileSize() {
return filesize_;
}
std::string LocalFileLoader::Path() const {
return filename_;
}
size_t LocalFileLoader::ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags) {
#if PPSSPP_PLATFORM(SWITCH)
// Toolchain has no fancy IO API. We must lock.
std::lock_guard<std::mutex> guard(readLock_);
lseek(fd_, absolutePos, SEEK_SET);
return read(fd_, data, bytes * count) / bytes;
#elif PPSSPP_PLATFORM(ANDROID)
// pread64 doesn't appear to actually be 64-bit safe, though such ISOs are uncommon. See #10862.
if (absolutePos <= 0x7FFFFFFF) {
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS < 64
return pread64(fd_, data, bytes * count, absolutePos) / bytes;
#else
return pread(fd_, data, bytes * count, absolutePos) / bytes;
#endif
} else {
// Since pread64 doesn't change the file offset, it should be safe to avoid the lock in the common case.
std::lock_guard<std::mutex> guard(readLock_);
lseek64(fd_, absolutePos, SEEK_SET);
return read(fd_, data, bytes * count) / bytes;
}
#elif !defined(_WIN32)
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS < 64
return pread64(fd_, data, bytes * count, absolutePos) / bytes;
#else
return pread(fd_, data, bytes * count, absolutePos) / bytes;
#endif
#else
DWORD read = -1;
OVERLAPPED offset = { 0 };
offset.Offset = (DWORD)(absolutePos & 0xffffffff);
offset.OffsetHigh = (DWORD)((absolutePos & 0xffffffff00000000) >> 32);
auto result = ReadFile(handle_, data, (DWORD)(bytes * count), &read, &offset);
return result == TRUE ? (size_t)read / bytes : -1;
#endif
}