mirror of
https://github.com/ksherlock/afp.git
synced 2025-01-13 11:30:12 +00:00
libstdc++ (mingw, cygwin, msys, etc) don't support windows errors. remap to posix.
This commit is contained in:
parent
d7660c16cc
commit
92070e2e65
@ -1,12 +1,17 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
set(PROJECT_NAME afp)
|
||||
set(PROJECT_TYPE CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
||||
set(CMAKE_CXX_EXTENSIONS FALSE)
|
||||
|
||||
if (CYGWIN OR MSYS OR MINGW)
|
||||
set(REMAP src/remap_os_error.c)
|
||||
endif()
|
||||
|
||||
add_library(afp src/finder_info.cpp src/resource_fork.cpp src/xattr.c)
|
||||
add_library(afp src/finder_info.cpp src/resource_fork.cpp src/xattr.c ${REMAP})
|
||||
|
||||
target_include_directories(afp INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include/)
|
||||
target_include_directories(afp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/afp)
|
||||
|
@ -6,8 +6,11 @@
|
||||
|
||||
#include <system_error>
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MSYS__)
|
||||
#define AFP_WIN32
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(AFP_WIN32)
|
||||
#pragma pack(push, 2)
|
||||
struct AFP_Info {
|
||||
uint32_t magic;
|
||||
@ -56,7 +59,7 @@ namespace afp {
|
||||
}
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(AFP_WIN32)
|
||||
bool read(const std::wstring &path, std::error_code &ec) {
|
||||
return open(path, read_only, ec);
|
||||
}
|
||||
@ -75,7 +78,7 @@ namespace afp {
|
||||
uint32_t creator_type() const;
|
||||
uint32_t file_type() const;
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(AFP_WIN32)
|
||||
const uint8_t *data() const {
|
||||
return _afp.finder_info;
|
||||
}
|
||||
@ -114,11 +117,12 @@ namespace afp {
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
|
||||
void close();
|
||||
|
||||
#if defined(_WIN32)
|
||||
private:
|
||||
|
||||
|
||||
#if defined(AFP_WIN32)
|
||||
void *_fd = (void *)-1;
|
||||
AFP_Info _afp;
|
||||
#else
|
||||
@ -130,6 +134,8 @@ namespace afp {
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#undef AFP_WIN32
|
||||
|
||||
#endif
|
||||
|
@ -4,6 +4,10 @@
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MSYS__)
|
||||
#define AFP_WIN32
|
||||
#endif
|
||||
|
||||
namespace afp {
|
||||
|
||||
class resource_fork {
|
||||
@ -26,7 +30,7 @@ namespace afp {
|
||||
~resource_fork() { close(); }
|
||||
|
||||
static size_t size(const std::string &path, std::error_code &ec);
|
||||
#ifdef _WIN32
|
||||
#ifdef AFP_WIN32
|
||||
static size_t size(const std::wstring &path, std::error_code &ec);
|
||||
#endif
|
||||
|
||||
@ -36,7 +40,7 @@ namespace afp {
|
||||
return open(s, read_only, ec);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef AFP_WIN32
|
||||
bool open(const std::wstring &s, open_mode mode, std::error_code &ec);
|
||||
bool open(const std::wstring &s, std::error_code &ec) {
|
||||
return open(s, read_only, ec);
|
||||
@ -53,7 +57,7 @@ namespace afp {
|
||||
|
||||
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
#ifdef AFP_WIN32
|
||||
void *_fd = (void *)-1;
|
||||
#else
|
||||
int _fd = -1;
|
||||
@ -66,5 +70,6 @@ namespace afp {
|
||||
};
|
||||
|
||||
}
|
||||
#undef AFP_WIN32
|
||||
|
||||
#endif
|
||||
|
@ -6,6 +6,13 @@
|
||||
#include <cctype>
|
||||
#include <string>
|
||||
|
||||
#if defined(__CYGWIN__) || defined(__MSYS__)
|
||||
#if !defined(_WIN32)
|
||||
#define _WIN32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (_WIN32)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
@ -13,6 +20,7 @@
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
@ -51,22 +59,28 @@ namespace {
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
|
||||
#ifdef MSVC
|
||||
#define AFP_ERROR_FILE_NOT_FOUND ERROR_FILE_NOT_FOUND
|
||||
#define remap_os_error(x) x
|
||||
#else
|
||||
#define AFP_ERROR_FILE_NOT_FOUND ENOENT
|
||||
extern "C" int remap_os_error(unsigned long);
|
||||
#endif
|
||||
|
||||
BOOL _(BOOL x, std::error_code &ec) {
|
||||
if (!x) ec = std::error_code(GetLastError(), std::system_category());
|
||||
if (!x) ec = std::error_code(remap_os_error(GetLastError()), std::system_category());
|
||||
return x;
|
||||
}
|
||||
|
||||
HANDLE _(HANDLE x, std::error_code &ec) {
|
||||
if (x == INVALID_HANDLE_VALUE)
|
||||
ec = std::error_code(GetLastError(), std::system_category());
|
||||
ec = std::error_code(remap_os_error(GetLastError()), std::system_category());
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
template<class ...Args>
|
||||
HANDLE CreateFileX(const std::string &s, Args... args) {
|
||||
return CreateFileA(s.c_str(), std::forward<Args>(args)...);
|
||||
@ -80,7 +94,6 @@ namespace {
|
||||
template<class StringType>
|
||||
HANDLE CreateFileX(const StringType &s, afp::finder_info::open_mode mode, std::error_code &ec) {
|
||||
|
||||
|
||||
DWORD access = 0;
|
||||
DWORD create = 0;
|
||||
|
||||
@ -102,6 +115,33 @@ namespace {
|
||||
return _(CreateFileX(s, access, FILE_SHARE_READ, nullptr, create, FILE_ATTRIBUTE_NORMAL, nullptr), ec);
|
||||
}
|
||||
|
||||
DWORD GetFileAttributesX(const std::string &path) {
|
||||
return GetFileAttributesA(path.c_str());
|
||||
}
|
||||
DWORD GetFileAttributesX(const std::wstring &path) {
|
||||
return GetFileAttributesW(path.c_str());
|
||||
}
|
||||
|
||||
template<class StringType>
|
||||
bool regular_file(const StringType &path, std::error_code &ec) {
|
||||
|
||||
// make sure this isn't a directory.
|
||||
DWORD st = GetFileAttributesX(path);
|
||||
if (st == INVALID_FILE_ATTRIBUTES) {
|
||||
ec = std::error_code(remap_os_error(GetLastError()), std::system_category());
|
||||
return false;
|
||||
}
|
||||
if (st & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
ec = std::make_error_code(std::errc::is_a_directory);
|
||||
return false;
|
||||
}
|
||||
if (st & FILE_ATTRIBUTE_DEVICE) {
|
||||
ec = std::make_error_code(std::errc::invalid_seek);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
@ -111,6 +151,31 @@ namespace {
|
||||
return x;
|
||||
}
|
||||
|
||||
bool regular_file(int fd, std::error_code &ec) {
|
||||
struct stat st;
|
||||
if (_(::fstat(fd, &st), ec) < 0) {
|
||||
return false;
|
||||
}
|
||||
if (S_ISREG(st.st_mode)) return true;
|
||||
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
ec = std::make_error_code(std::errc::is_a_directory);
|
||||
} else {
|
||||
ec = std::make_error_code(std::errc::invalid_seek); // ESPIPE.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* opens a file read-only and verifies it's a regular file */
|
||||
int openX(const std::string &path, std::error_code &ec) {
|
||||
int fd = _(::open(path.c_str(), O_RDONLY, O_NONBLOCK), ec);
|
||||
if (fd >= 0 && !regular_file(fd, ec)) {
|
||||
::close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -423,13 +488,17 @@ bool finder_info::open(const std::string &path, open_mode mode, std::error_code
|
||||
s += ":" XATTR_FINDERINFO_NAME;
|
||||
|
||||
/* open the base file, then the finder info, so we can clarify the error */
|
||||
if (!regular_file(path, ec)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HANDLE h = CreateFileX(path, read_only, ec);
|
||||
if (ec) return false;
|
||||
|
||||
_fd = CreateFileX(s, mode, ec);
|
||||
CloseHandle(h);
|
||||
if (ec) {
|
||||
if (ec.value() == ERROR_FILE_NOT_FOUND)
|
||||
if (ec.value() == AFP_ERROR_FILE_NOT_FOUND)
|
||||
ec = std::make_error_code(std::errc::no_message_available);
|
||||
return false;
|
||||
}
|
||||
@ -466,13 +535,17 @@ bool finder_info::open(const std::wstring &path, open_mode mode, std::error_code
|
||||
s += L":" XATTR_FINDERINFO_NAME;
|
||||
|
||||
/* open the base file, then the finder info, so we can clarify the error */
|
||||
if (!regular_file(path, ec)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HANDLE h = CreateFileX(path, read_only, ec);
|
||||
if (ec) return false;
|
||||
|
||||
_fd = CreateFileX(s, mode, ec);
|
||||
CloseHandle(h);
|
||||
if (ec) {
|
||||
if (ec.value() == ERROR_FILE_NOT_FOUND)
|
||||
if (ec.value() == AFP_ERROR_FILE_NOT_FOUND)
|
||||
ec = std::make_error_code(std::errc::no_message_available);
|
||||
return false;
|
||||
}
|
||||
@ -584,7 +657,7 @@ bool finder_info::open(const std::string &path, open_mode mode, std::error_code
|
||||
// attropen is a front end for open / openat.
|
||||
// do it ourselves so we can distinguish file doesn't exist vs attr doesn't exist.
|
||||
|
||||
int fd = _(::open(path.c_str(), O_RDONLY), ec);
|
||||
int fd = openX(path, ec);
|
||||
if (ec) return false;
|
||||
|
||||
_fd = _(::openat(fd, XATTR_FINDERINFO_NAME, umode | O_XATTR, 0666), ec);
|
||||
@ -631,7 +704,7 @@ bool finder_info::open(const std::string &path, open_mode mode, std::error_code
|
||||
close();
|
||||
clear();
|
||||
|
||||
_fd = _(::open(path.c_str(), O_RDONLY), ec);
|
||||
_fd = openX(path, ec);
|
||||
if (ec) return false;
|
||||
|
||||
if (mode == read_only || mode == read_write) {
|
||||
|
100
src/remap_os_error.c
Normal file
100
src/remap_os_error.c
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* libstdc++ (cygwin, msys, mingw, etc) use posix errno for std::system_category()
|
||||
* rather than create a new category, just remap to a posix errno.
|
||||
*/
|
||||
#include <errno.h>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
int remap_os_error(unsigned long e) {
|
||||
|
||||
switch(e) {
|
||||
case NO_ERROR: return 0;
|
||||
default: return EIO;
|
||||
|
||||
case ERROR_INVALID_HANDLE:
|
||||
return EBADF;
|
||||
|
||||
case ERROR_CANTOPEN:
|
||||
case ERROR_CANTREAD:
|
||||
case ERROR_CANTWRITE:
|
||||
case ERROR_OPEN_FAILED:
|
||||
case ERROR_READ_FAULT:
|
||||
case ERROR_SEEK:
|
||||
case ERROR_WRITE_FAULT:
|
||||
return EIO;
|
||||
|
||||
|
||||
case ERROR_ACCESS_DENIED:
|
||||
case ERROR_CANNOT_MAKE:
|
||||
case ERROR_CURRENT_DIRECTORY:
|
||||
case ERROR_INVALID_ACCESS:
|
||||
case ERROR_NOACCESS:
|
||||
case ERROR_SHARING_VIOLATION:
|
||||
case ERROR_WRITE_PROTECT:
|
||||
return EACCES;
|
||||
|
||||
case ERROR_ALREADY_EXISTS:
|
||||
case ERROR_FILE_EXISTS:
|
||||
return EEXIST;
|
||||
|
||||
case ERROR_BAD_UNIT:
|
||||
case ERROR_DEV_NOT_EXIST:
|
||||
case ERROR_INVALID_DRIVE:
|
||||
return ENODEV;
|
||||
|
||||
case ERROR_BUFFER_OVERFLOW:
|
||||
return ENAMETOOLONG;
|
||||
|
||||
case ERROR_BUSY:
|
||||
case ERROR_BUSY_DRIVE:
|
||||
case ERROR_DEVICE_IN_USE:
|
||||
case ERROR_OPEN_FILES:
|
||||
return EBUSY;
|
||||
|
||||
case ERROR_DIR_NOT_EMPTY:
|
||||
return ENOTEMPTY;
|
||||
|
||||
case ERROR_DIRECTORY:
|
||||
case ERROR_INVALID_NAME:
|
||||
case ERROR_NEGATIVE_SEEK:
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
return EINVAL;
|
||||
|
||||
case ERROR_DISK_FULL:
|
||||
case ERROR_HANDLE_DISK_FULL:
|
||||
return ENOSPC;
|
||||
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
case ERROR_BAD_NETPATH:
|
||||
case ERROR_BAD_NET_NAME:
|
||||
return ENOENT;
|
||||
|
||||
case ERROR_INVALID_FUNCTION:
|
||||
return ENOSYS;
|
||||
|
||||
case ERROR_LOCK_VIOLATION:
|
||||
case ERROR_LOCKED:
|
||||
return ENOLCK;
|
||||
|
||||
case ERROR_NOT_ENOUGH_MEMORY:
|
||||
case ERROR_OUTOFMEMORY:
|
||||
case ERROR_NOT_ENOUGH_QUOTA:
|
||||
return ENOMEM;
|
||||
|
||||
case ERROR_NOT_READY:
|
||||
case ERROR_RETRY:
|
||||
return EAGAIN;
|
||||
|
||||
case ERROR_NOT_SAME_DEVICE:
|
||||
return EXDEV;
|
||||
|
||||
case ERROR_OPERATION_ABORTED:
|
||||
return ECANCELED;
|
||||
|
||||
case ERROR_TOO_MANY_OPEN_FILES:
|
||||
return EMFILE;
|
||||
}
|
||||
|
||||
}
|
@ -3,6 +3,13 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#if defined(__CYGWIN__) || defined(__MSYS__)
|
||||
#if !defined(_WIN32)
|
||||
#define _WIN32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
Loading…
x
Reference in New Issue
Block a user