mirror of
https://github.com/ksherlock/afp.git
synced 2025-01-14 18:29:42 +00:00
add static write / remove functions for resource forks.
This commit is contained in:
parent
2c68e8e473
commit
3d031fe451
@ -30,10 +30,19 @@ 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);
|
||||||
|
static bool remove(const std::string &path, std::error_code &ec);
|
||||||
|
|
||||||
|
static size_t write(const std::string &path, const void *buffer, size_t n, std::error_code &ec);
|
||||||
|
|
||||||
#ifdef AFP_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);
|
||||||
|
static bool remove(const std::wstring &path, std::error_code &ec);
|
||||||
|
|
||||||
|
static size_t write(const std::wstring &path, const void *buffer, size_t n, std::error_code &ec);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool open(const std::string &s, open_mode mode, std::error_code &ec);
|
bool open(const std::string &s, open_mode mode, std::error_code &ec);
|
||||||
|
|
||||||
bool open(const std::string &s, std::error_code &ec) {
|
bool open(const std::string &s, std::error_code &ec) {
|
||||||
|
@ -84,6 +84,8 @@ extern "C" int remap_os_error(unsigned long);
|
|||||||
}
|
}
|
||||||
|
|
||||||
#undef CreateFile
|
#undef CreateFile
|
||||||
|
#undef DeleteFile
|
||||||
|
|
||||||
template<class ...Args>
|
template<class ...Args>
|
||||||
HANDLE CreateFile(const std::string &s, Args... args) {
|
HANDLE CreateFile(const std::string &s, Args... args) {
|
||||||
return CreateFileA(s.c_str(), std::forward<Args>(args)...);
|
return CreateFileA(s.c_str(), std::forward<Args>(args)...);
|
||||||
@ -121,6 +123,15 @@ extern "C" int remap_os_error(unsigned long);
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL DeleteFile(const std::string &path) { return DeleteFileA(path.c_str()); }
|
||||||
|
BOOL DeleteFile(const std::wstring &path) { return DeleteFileW(path.c_str()); }
|
||||||
|
|
||||||
|
template<class StringType>
|
||||||
|
bool DeleteFileX(const StringType &path, std::error_code &ec) {
|
||||||
|
return _(DeleteFile(path), ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DWORD GetFileAttributesX(const std::string &path) {
|
DWORD GetFileAttributesX(const std::string &path) {
|
||||||
return GetFileAttributesA(path.c_str());
|
return GetFileAttributesA(path.c_str());
|
||||||
}
|
}
|
||||||
@ -258,6 +269,104 @@ namespace afp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t resource_fork::write(const std::string &path, const void *buffer, size_t n, std::error_code &ec) {
|
||||||
|
|
||||||
|
ec.clear();
|
||||||
|
|
||||||
|
if (!regular_file(path, ec)) return 0;
|
||||||
|
|
||||||
|
std::string s(path);
|
||||||
|
s += ":" XATTR_RESOURCEFORK_NAME;
|
||||||
|
|
||||||
|
HANDLE h = CreateFileX(path, read_only, ec);
|
||||||
|
if (ec) return 0;
|
||||||
|
|
||||||
|
|
||||||
|
HANDLE fd = _(CreateFile(s, GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr), ec);
|
||||||
|
if (ec) return 0;
|
||||||
|
|
||||||
|
DWORD transferred = 0;
|
||||||
|
BOOL ok = _(WriteFile(fd, buffer, n, &transferred, nullptr), ec);
|
||||||
|
|
||||||
|
|
||||||
|
CloseHandle(h);
|
||||||
|
CloseHandle(fd);
|
||||||
|
|
||||||
|
|
||||||
|
if (ec) return 0;
|
||||||
|
return transferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t resource_fork::write(const std::wstring &path, const void *buffer, size_t n, std::error_code &ec) {
|
||||||
|
|
||||||
|
ec.clear();
|
||||||
|
|
||||||
|
if (!regular_file(path, ec)) return 0;
|
||||||
|
|
||||||
|
std::wstring s(path);
|
||||||
|
s += L":" XATTR_RESOURCEFORK_NAME;
|
||||||
|
|
||||||
|
HANDLE h = CreateFileX(path, read_only, ec);
|
||||||
|
if (ec) return 0;
|
||||||
|
|
||||||
|
|
||||||
|
HANDLE fd = _(CreateFile(s, GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr), ec);
|
||||||
|
if (ec) return 0;
|
||||||
|
|
||||||
|
DWORD transferred = 0;
|
||||||
|
BOOL ok = _(WriteFile(fd, buffer, n, &transferred, nullptr), ec);
|
||||||
|
|
||||||
|
|
||||||
|
CloseHandle(h);
|
||||||
|
CloseHandle(fd);
|
||||||
|
|
||||||
|
|
||||||
|
if (ec) return 0;
|
||||||
|
return transferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool resource_fork::remove(const std::string &path, std::error_code &ec) {
|
||||||
|
ec.clear();
|
||||||
|
|
||||||
|
if (!regular_file(path, ec)) return false;
|
||||||
|
|
||||||
|
std::string s(path);
|
||||||
|
s += ":" XATTR_RESOURCEFORK_NAME;
|
||||||
|
|
||||||
|
HANDLE h = CreateFileX(path, read_only, ec);
|
||||||
|
if (ec) return false;
|
||||||
|
CloseHandle(h);
|
||||||
|
|
||||||
|
bool ok = DeleteFileX(s, ec);
|
||||||
|
if (ec.value() == ERROR_FILE_NOT_FOUND) {
|
||||||
|
ec = std::make_error_code(std::errc::no_message_available);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool resource_fork::remove(const std::wstring &path, std::error_code &ec) {
|
||||||
|
ec.clear();
|
||||||
|
|
||||||
|
if (!regular_file(path, ec)) return false;
|
||||||
|
|
||||||
|
std::wstring s(path);
|
||||||
|
s += L":" XATTR_RESOURCEFORK_NAME;
|
||||||
|
|
||||||
|
HANDLE h = CreateFileX(path, read_only, ec);
|
||||||
|
if (ec) return false;
|
||||||
|
CloseHandle(h);
|
||||||
|
|
||||||
|
bool ok = DeleteFileX(s, ec);
|
||||||
|
if (ec.value() == ERROR_FILE_NOT_FOUND) {
|
||||||
|
ec = std::make_error_code(std::errc::no_message_available);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void resource_fork::close() {
|
void resource_fork::close() {
|
||||||
CloseHandle(_fd);
|
CloseHandle(_fd);
|
||||||
_fd = INVALID_HANDLE_VALUE;
|
_fd = INVALID_HANDLE_VALUE;
|
||||||
@ -340,7 +449,7 @@ namespace afp {
|
|||||||
int fd = openX(path, ec);
|
int fd = openX(path, ec);
|
||||||
if (ec) return false;
|
if (ec) return false;
|
||||||
|
|
||||||
_fd = ::openat(path.c_str(), XATTR_RESOURCEFORK_NAME, umode | O_XATTR, 0666);
|
_fd = _(::openat(path.c_str(), XATTR_RESOURCEFORK_NAME, umode | O_XATTR, 0666), ec);
|
||||||
::close(fd);
|
::close(fd);
|
||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
@ -352,6 +461,54 @@ namespace afp {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool resource_fork::remove(const std::string &path, std::error_code &ec) {
|
||||||
|
ec.clear();
|
||||||
|
|
||||||
|
|
||||||
|
int fd = openX(path, ec);
|
||||||
|
if (ec) return false;
|
||||||
|
|
||||||
|
int dirfd = _(::openat(fd, ".", O_RDONLY | O_XATTR), ec);
|
||||||
|
|
||||||
|
::close(fd);
|
||||||
|
if (ec) return false;
|
||||||
|
|
||||||
|
int ok = _(::unlinkat(dirfd, XATTR_RESOURCEFORK_NAME), ec);
|
||||||
|
::close(dirfd);
|
||||||
|
|
||||||
|
if (ec.value() == ENOENT) {
|
||||||
|
ec = std::make_error_code(std::errc::no_message_available); // ENODATA.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return ok == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t resource_fork::write(const std::string &path, const void *buffer, size_t n, std::error_code &ec) {
|
||||||
|
|
||||||
|
ec.clear();
|
||||||
|
|
||||||
|
int fd = openX(path, ec);
|
||||||
|
if (ec) return 0;
|
||||||
|
|
||||||
|
rfd = _(::openat(path.c_str(), XATTR_RESOURCEFORK_NAME, O_WRONLY | O_CREAT | O_TRUNC | O_XATTR, 0666), ec);
|
||||||
|
::close(fd);
|
||||||
|
|
||||||
|
if (ec) {
|
||||||
|
if (ec.value() == ENOENT)
|
||||||
|
ec = std::make_error_code(std::errc::no_message_available); // ENODATA.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rv = _(::write(rfd, buffer, n), ec);
|
||||||
|
::close(rfd);
|
||||||
|
if (rv < 0) return 0;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -385,6 +542,44 @@ namespace afp {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool resource_fork::remove(const std::string &path, std::error_code &ec) {
|
||||||
|
ec.clear();
|
||||||
|
|
||||||
|
std::string s(path);
|
||||||
|
s += _PATH_RSRCFORKSPEC;
|
||||||
|
|
||||||
|
int fd = openX(path, ec);
|
||||||
|
if (ec) return false;
|
||||||
|
::close(fd);
|
||||||
|
|
||||||
|
int ok = _(::unlink(s.c_str()), ec);
|
||||||
|
if (ec.value() == ENOENT) {
|
||||||
|
ec = std::make_error_code(std::errc::no_message_available);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return ok == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t resource_fork::write(const std::string &path, const void *buffer, size_t n, std::error_code &ec) {
|
||||||
|
|
||||||
|
ec.clear();
|
||||||
|
|
||||||
|
std::string s(path);
|
||||||
|
s += _PATH_RSRCFORKSPEC;
|
||||||
|
|
||||||
|
int fd = openX(path, ec);
|
||||||
|
if (ec) return false;
|
||||||
|
::close(fd);
|
||||||
|
|
||||||
|
int rfd = _(::open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666), ec);
|
||||||
|
if (rfd < 0) return 0;
|
||||||
|
|
||||||
|
auto rv = _(::write(rfd, buffer, n), ec);
|
||||||
|
::close(rfd);
|
||||||
|
if (rv < 0) return 0;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FD_RESOURCE_FORK
|
#ifdef FD_RESOURCE_FORK
|
||||||
@ -474,7 +669,7 @@ namespace afp {
|
|||||||
auto rv = _(::size_xattr(_fd, XATTR_RESOURCEFORK_NAME), ec);
|
auto rv = _(::size_xattr(_fd, XATTR_RESOURCEFORK_NAME), ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
remap_enoattr(ec);
|
remap_enoattr(ec);
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -576,6 +771,42 @@ namespace afp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool resource_fork::remove(const std::string &path, std::error_code &ec) {
|
||||||
|
ec.clear();
|
||||||
|
|
||||||
|
int fd = openX(path, ec);
|
||||||
|
if (ec) return false;
|
||||||
|
|
||||||
|
int rv = _(::remove_xattr(fd, XATTR_RESOURCEFORK_NAME), ec);
|
||||||
|
::close(fd);
|
||||||
|
|
||||||
|
if (rv < 0) {
|
||||||
|
remap_enoattr(ec);
|
||||||
|
if (ec.value() == ENODATA) return true;
|
||||||
|
}
|
||||||
|
return rv == 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t resource_fork::write(const std::string &path, const void *buffer, size_t n, std::error_code &ec) {
|
||||||
|
ec.clear();
|
||||||
|
|
||||||
|
int fd = openX(path, ec);
|
||||||
|
if (ec) return false;
|
||||||
|
|
||||||
|
auto rv = _(::write_xattr(fd, XATTR_RESOURCEFORK_NAME, buffer, n), ec);
|
||||||
|
::close(fd);
|
||||||
|
|
||||||
|
if (rv < 0) {
|
||||||
|
remap_enoattr(ec);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t resource_fork::size(const std::string &path, std::error_code &ec) {
|
size_t resource_fork::size(const std::string &path, std::error_code &ec) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user