mirror of
https://github.com/ksherlock/afp.git
synced 2025-01-14 03:31:07 +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)
|
cmake_minimum_required(VERSION 3.1)
|
||||||
|
|
||||||
|
set(PROJECT_NAME afp)
|
||||||
|
set(PROJECT_TYPE CXX)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
||||||
set(CMAKE_CXX_EXTENSIONS FALSE)
|
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 INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include/)
|
||||||
target_include_directories(afp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/afp)
|
target_include_directories(afp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/afp)
|
||||||
|
@ -6,8 +6,11 @@
|
|||||||
|
|
||||||
#include <system_error>
|
#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)
|
#pragma pack(push, 2)
|
||||||
struct AFP_Info {
|
struct AFP_Info {
|
||||||
uint32_t magic;
|
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) {
|
bool read(const std::wstring &path, std::error_code &ec) {
|
||||||
return open(path, read_only, ec);
|
return open(path, read_only, ec);
|
||||||
}
|
}
|
||||||
@ -75,7 +78,7 @@ namespace afp {
|
|||||||
uint32_t creator_type() const;
|
uint32_t creator_type() const;
|
||||||
uint32_t file_type() const;
|
uint32_t file_type() const;
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(AFP_WIN32)
|
||||||
const uint8_t *data() const {
|
const uint8_t *data() const {
|
||||||
return _afp.finder_info;
|
return _afp.finder_info;
|
||||||
}
|
}
|
||||||
@ -114,11 +117,12 @@ namespace afp {
|
|||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
#if defined(_WIN32)
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(AFP_WIN32)
|
||||||
void *_fd = (void *)-1;
|
void *_fd = (void *)-1;
|
||||||
AFP_Info _afp;
|
AFP_Info _afp;
|
||||||
#else
|
#else
|
||||||
@ -130,6 +134,8 @@ namespace afp {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#undef AFP_WIN32
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MSYS__)
|
||||||
|
#define AFP_WIN32
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace afp {
|
namespace afp {
|
||||||
|
|
||||||
class resource_fork {
|
class resource_fork {
|
||||||
@ -26,7 +30,7 @@ namespace afp {
|
|||||||
~resource_fork() { close(); }
|
~resource_fork() { close(); }
|
||||||
|
|
||||||
static size_t size(const std::string &path, std::error_code &ec);
|
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);
|
static size_t size(const std::wstring &path, std::error_code &ec);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -36,7 +40,7 @@ namespace afp {
|
|||||||
return open(s, read_only, ec);
|
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, open_mode mode, std::error_code &ec);
|
||||||
bool open(const std::wstring &s, std::error_code &ec) {
|
bool open(const std::wstring &s, std::error_code &ec) {
|
||||||
return open(s, read_only, ec);
|
return open(s, read_only, ec);
|
||||||
@ -53,7 +57,7 @@ namespace afp {
|
|||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef _WIN32
|
#ifdef AFP_WIN32
|
||||||
void *_fd = (void *)-1;
|
void *_fd = (void *)-1;
|
||||||
#else
|
#else
|
||||||
int _fd = -1;
|
int _fd = -1;
|
||||||
@ -66,5 +70,6 @@ namespace afp {
|
|||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#undef AFP_WIN32
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,13 @@
|
|||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#if defined(__CYGWIN__) || defined(__MSYS__)
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
#define _WIN32
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined (_WIN32)
|
#if defined (_WIN32)
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -13,6 +20,7 @@
|
|||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
@ -51,22 +59,28 @@ namespace {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#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) {
|
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;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE _(HANDLE x, std::error_code &ec) {
|
HANDLE _(HANDLE x, std::error_code &ec) {
|
||||||
if (x == INVALID_HANDLE_VALUE)
|
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;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class ...Args>
|
template<class ...Args>
|
||||||
HANDLE CreateFileX(const std::string &s, Args... args) {
|
HANDLE CreateFileX(const std::string &s, Args... args) {
|
||||||
return CreateFileA(s.c_str(), std::forward<Args>(args)...);
|
return CreateFileA(s.c_str(), std::forward<Args>(args)...);
|
||||||
@ -80,7 +94,6 @@ namespace {
|
|||||||
template<class StringType>
|
template<class StringType>
|
||||||
HANDLE CreateFileX(const StringType &s, afp::finder_info::open_mode mode, std::error_code &ec) {
|
HANDLE CreateFileX(const StringType &s, afp::finder_info::open_mode mode, std::error_code &ec) {
|
||||||
|
|
||||||
|
|
||||||
DWORD access = 0;
|
DWORD access = 0;
|
||||||
DWORD create = 0;
|
DWORD create = 0;
|
||||||
|
|
||||||
@ -102,6 +115,33 @@ namespace {
|
|||||||
return _(CreateFileX(s, access, FILE_SHARE_READ, nullptr, create, FILE_ATTRIBUTE_NORMAL, nullptr), ec);
|
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
|
#else
|
||||||
|
|
||||||
@ -111,6 +151,31 @@ namespace {
|
|||||||
return x;
|
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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -423,13 +488,17 @@ bool finder_info::open(const std::string &path, open_mode mode, std::error_code
|
|||||||
s += ":" XATTR_FINDERINFO_NAME;
|
s += ":" XATTR_FINDERINFO_NAME;
|
||||||
|
|
||||||
/* open the base file, then the finder info, so we can clarify the error */
|
/* 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);
|
HANDLE h = CreateFileX(path, read_only, ec);
|
||||||
if (ec) return false;
|
if (ec) return false;
|
||||||
|
|
||||||
_fd = CreateFileX(s, mode, ec);
|
_fd = CreateFileX(s, mode, ec);
|
||||||
CloseHandle(h);
|
CloseHandle(h);
|
||||||
if (ec) {
|
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);
|
ec = std::make_error_code(std::errc::no_message_available);
|
||||||
return false;
|
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;
|
s += L":" XATTR_FINDERINFO_NAME;
|
||||||
|
|
||||||
/* open the base file, then the finder info, so we can clarify the error */
|
/* 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);
|
HANDLE h = CreateFileX(path, read_only, ec);
|
||||||
if (ec) return false;
|
if (ec) return false;
|
||||||
|
|
||||||
_fd = CreateFileX(s, mode, ec);
|
_fd = CreateFileX(s, mode, ec);
|
||||||
CloseHandle(h);
|
CloseHandle(h);
|
||||||
if (ec) {
|
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);
|
ec = std::make_error_code(std::errc::no_message_available);
|
||||||
return false;
|
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.
|
// attropen is a front end for open / openat.
|
||||||
// do it ourselves so we can distinguish file doesn't exist vs attr doesn't exist.
|
// 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;
|
if (ec) return false;
|
||||||
|
|
||||||
_fd = _(::openat(fd, XATTR_FINDERINFO_NAME, umode | O_XATTR, 0666), ec);
|
_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();
|
close();
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
_fd = _(::open(path.c_str(), O_RDONLY), ec);
|
_fd = openX(path, ec);
|
||||||
if (ec) return false;
|
if (ec) return false;
|
||||||
|
|
||||||
if (mode == read_only || mode == read_write) {
|
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>
|
#include <cstring>
|
||||||
|
|
||||||
|
#if defined(__CYGWIN__) || defined(__MSYS__)
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
#define _WIN32
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user