Merge pull request #3677 from MarcZX100/carry/libkernel-delete-sharing-3316
fix(libkernel): allow delete sharing for open Windows files
This commit is contained in:
commit
6c6c5552dc
|
|
@ -21,8 +21,55 @@
|
|||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <sys/stat.h>
|
||||
#include <windows.h>
|
||||
static int OpenError(DWORD error) {
|
||||
switch (error) {
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
case ERROR_INVALID_DRIVE:
|
||||
case ERROR_BAD_NETPATH:
|
||||
case ERROR_BAD_NET_NAME:
|
||||
case ERROR_BAD_PATHNAME:
|
||||
case ERROR_FILENAME_EXCED_RANGE:
|
||||
return ENOENT;
|
||||
case ERROR_ACCESS_DENIED:
|
||||
case ERROR_SHARING_VIOLATION:
|
||||
case ERROR_LOCK_VIOLATION:
|
||||
case ERROR_WRITE_PROTECT:
|
||||
case ERROR_NETWORK_ACCESS_DENIED:
|
||||
case ERROR_CANNOT_MAKE:
|
||||
case ERROR_DRIVE_LOCKED:
|
||||
return EACCES;
|
||||
case ERROR_FILE_EXISTS:
|
||||
case ERROR_ALREADY_EXISTS:
|
||||
return EEXIST;
|
||||
case ERROR_TOO_MANY_OPEN_FILES:
|
||||
return EMFILE;
|
||||
case ERROR_NOT_ENOUGH_MEMORY:
|
||||
case ERROR_OUTOFMEMORY:
|
||||
return ENOMEM;
|
||||
case ERROR_DISK_FULL:
|
||||
return ENOSPC;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
static int NativeOpen(const std::filesystem::path& p, int nativeFlags, std::uint16_t mode) {
|
||||
return ::_wopen(p.wstring().c_str(), nativeFlags, static_cast<int>(mode));
|
||||
const int access = nativeFlags & (_O_RDONLY | _O_WRONLY | _O_RDWR);
|
||||
const DWORD desired = access == _O_RDONLY ? GENERIC_READ : access == _O_WRONLY ? GENERIC_WRITE : GENERIC_READ | GENERIC_WRITE;
|
||||
DWORD disposition = OPEN_EXISTING;
|
||||
if (nativeFlags & _O_CREAT) disposition = (nativeFlags & _O_EXCL) ? CREATE_NEW : (nativeFlags & _O_TRUNC) ? CREATE_ALWAYS : OPEN_ALWAYS;
|
||||
else if (nativeFlags & _O_TRUNC) disposition = TRUNCATE_EXISTING;
|
||||
const DWORD attributes = (nativeFlags & _O_CREAT) && !(mode & _S_IWRITE) ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL;
|
||||
SECURITY_ATTRIBUTES security{sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE};
|
||||
const auto handle = CreateFileW(p.c_str(), desired, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &security, disposition, attributes, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
errno = OpenError(GetLastError());
|
||||
return -1;
|
||||
}
|
||||
const int descriptor = ::_open_osfhandle(reinterpret_cast<std::intptr_t>(handle), nativeFlags & (_O_APPEND | _O_RDONLY | _O_BINARY));
|
||||
if (descriptor < 0) CloseHandle(handle);
|
||||
return descriptor;
|
||||
}
|
||||
static std::int64_t NativeLseek(int fd, std::int64_t offset, int whence) {
|
||||
return ::_lseeki64(fd, offset, whence);
|
||||
|
|
|
|||
|
|
@ -230,6 +230,21 @@ int main() {
|
|||
Require(mkdir_nid_postfix(nullptr, 0700) == -1 && *__error_nid_postfix() == 14);
|
||||
const auto file = root / "file.txt";
|
||||
{ std::ofstream stream(file); stream << "retained until removal"; }
|
||||
const auto held = root / "held.txt";
|
||||
const auto heldName = held.string();
|
||||
{ std::ofstream stream(held); stream << "held"; }
|
||||
const int heldDescriptor = sceKernelOpen(heldName.c_str(), 2, 0);
|
||||
Require(heldDescriptor >= 0 && sceKernelUnlink(heldName.c_str()) == 0 && !std::filesystem::exists(held));
|
||||
char heldBytes[4]{};
|
||||
Require(read_nid_postfix(heldDescriptor, heldBytes, sizeof(heldBytes)) == sizeof(heldBytes) && std::memcmp(heldBytes, "held", 4) == 0);
|
||||
const int recreated = sceKernelOpen(heldName.c_str(), 0x0a01, 0644);
|
||||
Require(recreated >= 0 && sceKernelClose(heldDescriptor) == 0 && std::filesystem::file_size(held) == 0);
|
||||
const auto moved = root / "moved.txt";
|
||||
Require(rename_nid_postfix(heldName.c_str(), moved.string().c_str()) == 0 && !std::filesystem::exists(held));
|
||||
Require(write_nid_postfix(recreated, "moved", 5) == 5 && sceKernelClose(recreated) == 0 && std::filesystem::file_size(moved) == 5);
|
||||
const int removing = open_nid_postfix(moved.string().c_str(), 0, 0);
|
||||
Require(removing >= 0 && remove_nid_postfix(moved.string().c_str()) == 0 && !std::filesystem::exists(moved));
|
||||
Require(close_nid_postfix(removing) == 0);
|
||||
Require(remove_nid_postfix(root.string().c_str()) == -1);
|
||||
Require(*__error_nid_postfix() == 66);
|
||||
Require(std::filesystem::is_regular_file(file));
|
||||
|
|
|
|||
Loading…
Reference in New Issue