mirror of
https://github.com/ksherlock/dot_clean.git
synced 2025-01-03 08:29:57 +00:00
updated finder_info, mapped_file, etc
This commit is contained in:
parent
faec01b209
commit
d12a961627
@ -29,6 +29,12 @@
|
||||
#include "applefile.h"
|
||||
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if defined(__linux__)
|
||||
#define XATTR_RESOURCEFORK_NAME "user.com.apple.ResourceFork"
|
||||
#endif
|
||||
@ -78,12 +84,12 @@ std::vector<uint8_t> read_resource_fork(const std::string &path, std::error_code
|
||||
struct stat st;
|
||||
|
||||
#if defined(__sun__)
|
||||
fd = attropen(path.c_str(), XATTR_RESOURCEFORK_NAME, O_RDONLY);
|
||||
fd = attropen(path.c_str(), XATTR_RESOURCEFORK_NAME, O_RDONLY | O_BINARY);
|
||||
#else
|
||||
std::string p(path);
|
||||
p += ":" XATTR_RESOURCEFORK_NAME;
|
||||
|
||||
fd = open(p.c_str(), O_RDONLY);
|
||||
fd = open(p.c_str(), O_RDONLY | O_BINARY);
|
||||
#endif
|
||||
if (fd < 0) {
|
||||
ec = std::error_code(errno, std::generic_category());
|
||||
@ -117,7 +123,7 @@ std::vector<uint8_t> read_resource_fork(const std::string &path, std::error_code
|
||||
return rv;
|
||||
#else
|
||||
|
||||
int fd = open(path.c_str(), O_RDONLY);
|
||||
int fd = open(path.c_str(), O_RDONLY | O_BINARY);
|
||||
if (fd < 0) {
|
||||
ec = std::error_code(errno, std::generic_category());
|
||||
return rv;
|
||||
@ -127,8 +133,11 @@ std::vector<uint8_t> read_resource_fork(const std::string &path, std::error_code
|
||||
ssize_t size = size_xattr(fd, XATTR_RESOURCEFORK_NAME);
|
||||
if (size < 0) {
|
||||
if (errno == EINTR) continue;
|
||||
if (errno != ENOATTR)
|
||||
ec = std::error_code(errno, std::generic_category());
|
||||
if (errno == ENOATTR) {
|
||||
rv.clear();
|
||||
break;
|
||||
}
|
||||
ec = std::error_code(errno, std::generic_category());
|
||||
close(fd);
|
||||
return rv;
|
||||
}
|
||||
@ -138,6 +147,10 @@ std::vector<uint8_t> read_resource_fork(const std::string &path, std::error_code
|
||||
ssize_t rsize = read_xattr(fd, XATTR_RESOURCEFORK_NAME, rv.data(), size);
|
||||
if (rsize < 0) {
|
||||
if (errno == ERANGE || errno == EINTR) continue; // try again.
|
||||
if (errno == ENOATTR) {
|
||||
rv.clear();
|
||||
break;
|
||||
}
|
||||
ec = std::error_code(errno, std::generic_category());
|
||||
rv.clear();
|
||||
break;
|
||||
@ -210,13 +223,13 @@ void one_file(const std::string &infile, const std::string &outfile) {
|
||||
std::error_code ec;
|
||||
|
||||
finder_info_helper fi;
|
||||
bool fi_ok = fi.open(infile);
|
||||
bool fi_ok = fi.open(infile, ec);
|
||||
|
||||
|
||||
// ENOATTR is ok... but that's not an errc...
|
||||
std::vector<uint8_t> resource = read_resource_fork(infile, ec);
|
||||
|
||||
if (ec && ec.value() != ENOATTR) {
|
||||
if (ec) {
|
||||
warnc(ec.value(), "%s resource fork\n", infile.c_str());
|
||||
return;
|
||||
}
|
||||
@ -230,7 +243,7 @@ void one_file(const std::string &infile, const std::string &outfile) {
|
||||
if (fi_ok) count++;
|
||||
|
||||
|
||||
int fd = open(outfile.c_str(), O_WRONLY | O_CREAT, 0666);
|
||||
int fd = open(outfile.c_str(), O_WRONLY | O_CREAT | O_BINARY, 0666);
|
||||
memset(&head, 0, sizeof(head));
|
||||
head.magicNum = htonl(APPLEDOUBLE_MAGIC);
|
||||
head.versionNum = htonl(0x00020000);
|
||||
|
@ -28,6 +28,9 @@
|
||||
|
||||
#include "applefile.h"
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
#define XATTR_RESOURCEFORK_NAME "user.com.apple.ResourceFork"
|
||||
@ -78,12 +81,12 @@ std::vector<uint8_t> read_resource_fork(const std::string &path, std::error_code
|
||||
struct stat st;
|
||||
|
||||
#if defined(__sun__)
|
||||
fd = attropen(path.c_str(), XATTR_RESOURCEFORK_NAME, O_RDONLY);
|
||||
fd = attropen(path.c_str(), XATTR_RESOURCEFORK_NAME, O_RDONLY | O_BINARY);
|
||||
#else
|
||||
std::string p(path);
|
||||
p += ":" XATTR_RESOURCEFORK_NAME;
|
||||
|
||||
fd = open(p.c_str(), O_RDONLY);
|
||||
fd = open(p.c_str(), O_RDONLY | O_BINARY);
|
||||
#endif
|
||||
if (fd < 0) {
|
||||
ec = std::error_code(errno, std::generic_category());
|
||||
@ -117,7 +120,7 @@ std::vector<uint8_t> read_resource_fork(const std::string &path, std::error_code
|
||||
return rv;
|
||||
#else
|
||||
|
||||
int fd = open(path.c_str(), O_RDONLY);
|
||||
int fd = open(path.c_str(), O_RDONLY | O_BINARY);
|
||||
if (fd < 0) {
|
||||
ec = std::error_code(errno, std::generic_category());
|
||||
return rv;
|
||||
@ -127,8 +130,11 @@ std::vector<uint8_t> read_resource_fork(const std::string &path, std::error_code
|
||||
ssize_t size = size_xattr(fd, XATTR_RESOURCEFORK_NAME);
|
||||
if (size < 0) {
|
||||
if (errno == EINTR) continue;
|
||||
if (errno != ENOATTR)
|
||||
ec = std::error_code(errno, std::generic_category());
|
||||
if (errno == ENOATTR) {
|
||||
rv.clear();
|
||||
break;
|
||||
}
|
||||
ec = std::error_code(errno, std::generic_category());
|
||||
close(fd);
|
||||
return rv;
|
||||
}
|
||||
@ -138,6 +144,10 @@ std::vector<uint8_t> read_resource_fork(const std::string &path, std::error_code
|
||||
ssize_t rsize = read_xattr(fd, XATTR_RESOURCEFORK_NAME, rv.data(), size);
|
||||
if (rsize < 0) {
|
||||
if (errno == ERANGE || errno == EINTR) continue; // try again.
|
||||
if (errno == ENOATTR) {
|
||||
rv.clear();
|
||||
break;
|
||||
}
|
||||
ec = std::error_code(errno, std::generic_category());
|
||||
rv.clear();
|
||||
break;
|
||||
@ -210,13 +220,14 @@ void one_file(const std::string &infile, const std::string &outfile) {
|
||||
std::error_code ec;
|
||||
|
||||
finder_info_helper fi;
|
||||
bool fi_ok = fi.open(infile);
|
||||
|
||||
bool fi_ok = fi.open(infile, ec);
|
||||
|
||||
|
||||
// ENOATTR is ok... but that's not an errc...
|
||||
std::vector<uint8_t> resource = read_resource_fork(infile, ec);
|
||||
|
||||
if (ec && ec.value() != ENOATTR) {
|
||||
if (ec) {
|
||||
warnc(ec.value(), "%s resource fork\n", infile.c_str());
|
||||
return;
|
||||
}
|
||||
@ -230,7 +241,7 @@ void one_file(const std::string &infile, const std::string &outfile) {
|
||||
if (fi_ok) count++;
|
||||
|
||||
|
||||
int fd = open(outfile.c_str(), O_WRONLY | O_CREAT, 0666);
|
||||
int fd = open(outfile.c_str(), O_WRONLY | O_CREAT | O_BINARY, 0666);
|
||||
memset(&head, 0, sizeof(head));
|
||||
head.magicNum = htonl(APPLESINGLE_MAGIC);
|
||||
head.versionNum = htonl(0x00020000);
|
||||
|
@ -267,10 +267,11 @@ void one_file(const std::string &data, const std::string &rsrc) noexcept try {
|
||||
});
|
||||
|
||||
finder_info_helper fi;
|
||||
bool fi_ok = false;
|
||||
std::error_code ec;
|
||||
bool update_fi = false;
|
||||
bool fi_ok = false;
|
||||
|
||||
fi_ok = fi.open(data, false);
|
||||
fi_ok = fi.open(data, finder_info_helper::read_write, ec);
|
||||
|
||||
std::for_each(begin, end, [&](const ASEntry &tmp){
|
||||
|
||||
@ -320,7 +321,7 @@ void one_file(const std::string &data, const std::string &rsrc) noexcept try {
|
||||
});
|
||||
|
||||
if (update_fi) {
|
||||
if (!fi.write()) {
|
||||
if (!fi.write(ec)) {
|
||||
throw_errno("com.apple.FinderInfo");
|
||||
}
|
||||
}
|
||||
|
@ -8,19 +8,28 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "xattr.h"
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <sys/xattr.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <sys/xattr.h>
|
||||
#define XATTR_FINDERINFO_NAME "user.com.apple.FinderInfo"
|
||||
#define XATTR_RESOURCEFORK_NAME "user.com.apple.ResourceFork"
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/extattr.h>
|
||||
#endif
|
||||
|
||||
#if defined(_AIX)
|
||||
#include <sys/ea.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (_WIN32)
|
||||
#include <windows.h>
|
||||
#define XATTR_FINDERINFO_NAME "AFP_AfpInfo"
|
||||
#endif
|
||||
|
||||
@ -198,24 +207,241 @@ namespace {
|
||||
}
|
||||
|
||||
|
||||
int fi_open(const std::string &path, bool read_only) {
|
||||
template<class T>
|
||||
T _(const T t, std::error_code &ec) {
|
||||
if (t < 0) ec = std::error_code(errno, std::generic_category());
|
||||
return t;
|
||||
}
|
||||
|
||||
/*
|
||||
* extended attributes functions.
|
||||
*/
|
||||
#if defined(__APPLE__)
|
||||
ssize_t size_xattr(int fd, const char *xattr) {
|
||||
return fgetxattr(fd, xattr, NULL, 0, 0, 0);
|
||||
}
|
||||
|
||||
ssize_t read_xattr(int fd, const char *xattr, void *buffer, size_t size) {
|
||||
return fgetxattr(fd, xattr, buffer, size, 0, 0);
|
||||
}
|
||||
|
||||
ssize_t write_xattr(int fd, const char *xattr, const void *buffer, size_t size) {
|
||||
if (fsetxattr(fd, xattr, buffer, size, 0, 0) < 0) return -1;
|
||||
return size;
|
||||
}
|
||||
|
||||
int remove_xattr(int fd, const char *xattr) {
|
||||
return fremovexattr(fd, xattr, 0);
|
||||
}
|
||||
|
||||
#elif defined(__linux__)
|
||||
ssize_t size_xattr(int fd, const char *xattr) {
|
||||
return fgetxattr(fd, xattr, NULL, 0);
|
||||
}
|
||||
|
||||
ssize_t read_xattr(int fd, const char *xattr, void *buffer, size_t size) {
|
||||
return fgetxattr(fd, xattr, buffer, size);
|
||||
}
|
||||
|
||||
ssize_t write_xattr(int fd, const char *xattr, const void *buffer, size_t size) {
|
||||
if (fsetxattr(fd, xattr, buffer, size, 0) < 0) return -1;
|
||||
return size;
|
||||
}
|
||||
|
||||
int remove_xattr(int fd, const char *xattr) {
|
||||
return fremovexattr(fd, xattr);
|
||||
}
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
ssize_t size_xattr(int fd, const char *xattr) {
|
||||
return extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, xattr, NULL, 0);
|
||||
}
|
||||
|
||||
ssize_t read_xattr(int fd, const char *xattr, void *buffer, size_t size) {
|
||||
return extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, xattr, buffer, size);
|
||||
}
|
||||
|
||||
ssize_t write_xattr(int fd, const char *xattr, const void *buffer, size_t size) {
|
||||
return extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, xattr, buffer, size);
|
||||
}
|
||||
|
||||
int remove_xattr(int fd, const char *xattr) {
|
||||
return extattr_delete_fd(fd, EXTATTR_NAMESPACE_USER, xattr);
|
||||
}
|
||||
|
||||
#elif defined(_AIX)
|
||||
ssize_t size_xattr(int fd, const char *xattr) {
|
||||
/*
|
||||
struct stat64x st;
|
||||
if (fstatea(fd, xattr, &st) < 0) return -1;
|
||||
return st.st_size;
|
||||
*/
|
||||
return fgetea(fd, xattr, NULL, 0);
|
||||
}
|
||||
|
||||
ssize_t read_xattr(int fd, const char *xattr, void *buffer, size_t size) {
|
||||
return fgetea(fd, xattr, buffer, size);
|
||||
}
|
||||
|
||||
ssize_t write_xattr(int fd, const char *xattr, const void *buffer, size_t size) {
|
||||
if (fsetea(fd, xattr, buffer, size, 0) < 0) return -1;
|
||||
return size;
|
||||
}
|
||||
|
||||
int remove_xattr(int fd, const char *xattr) {
|
||||
return fremoveea(fd, xattr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void set_or_throw_error(std::error_code *ec, int error, const std::string &what) {
|
||||
if (ec) *ec = std::error_code(error, std::system_category());
|
||||
else throw std::system_error(error, std::system_category(), what);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
/*
|
||||
* allocating a new string could reset GetLastError() to 0.
|
||||
*/
|
||||
void set_or_throw_error(std::error_code *ec, const char *what) {
|
||||
auto e = GetLastError();
|
||||
set_or_throw_error(ec, e, what);
|
||||
}
|
||||
|
||||
void set_or_throw_error(std::error_code *ec, const std::string &what) {
|
||||
auto e = GetLastError();
|
||||
set_or_throw_error(ec, e, what);
|
||||
}
|
||||
|
||||
template<class ...Args>
|
||||
HANDLE CreateFileX(const std::string &s, Args... args) {
|
||||
return CreateFileA(s.c_str(), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class ...Args>
|
||||
HANDLE CreateFileX(const std::wstring &s, Args... args) {
|
||||
return CreateFileW(s.c_str(), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void fi_close(void *fd) {
|
||||
CloseHandle(fd);
|
||||
}
|
||||
|
||||
void *fi_open(const std::string &path, int perm, std::error_code &ec) {
|
||||
|
||||
ec.clear();
|
||||
|
||||
#if defined(__sun__)
|
||||
if (read_only) return attropen(path.c_str(), XATTR_FINDERINFO_NAME, O_RDONLY);
|
||||
else return attropen(path.c_str(), XATTR_FINDERINFO_NAME, O_RDWR | O_CREAT, 0666);
|
||||
#elif defined(_WIN32)
|
||||
std::string s(path);
|
||||
s.append(":" XATTR_FINDERINFO_NAME);
|
||||
if (read_only) return open(s.c_str(), O_RDONLY | O_BINARY);
|
||||
else return open(s.c_str(), O_RDWR | O_CREAT | O_BINARY, 0666);
|
||||
#else
|
||||
|
||||
HANDLE fh;
|
||||
bool ro = perm == 1;
|
||||
|
||||
fh = CreateFileX(s,
|
||||
ro ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
nullptr,
|
||||
ro ? OPEN_EXISTING : OPEN_ALWAYS,
|
||||
ro ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL,
|
||||
nullptr);
|
||||
|
||||
if (fh == INVALID_HANDLE_VALUE)
|
||||
set_or_throw_error(&ec, "CreateFile");
|
||||
|
||||
return fh;
|
||||
}
|
||||
|
||||
void *fi_open(const std::wstring &path, int perm, std::error_code &ec) {
|
||||
|
||||
ec.clear();
|
||||
|
||||
std::wstring s(path);
|
||||
s.append(L":" XATTR_FINDERINFO_NAME);
|
||||
|
||||
HANDLE fh;
|
||||
bool ro = perm == 1;
|
||||
|
||||
fh = CreateFileX(s,
|
||||
ro ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
nullptr,
|
||||
ro ? OPEN_EXISTING : OPEN_ALWAYS,
|
||||
ro ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL,
|
||||
nullptr);
|
||||
|
||||
if (fh == INVALID_HANDLE_VALUE)
|
||||
set_or_throw_error(&ec, "CreateFile");
|
||||
|
||||
return fh;
|
||||
}
|
||||
|
||||
int fi_write(void *handle, const void *data, int length, std::error_code &ec) {
|
||||
|
||||
ec.clear();
|
||||
DWORD rv = 0;
|
||||
BOOL ok;
|
||||
|
||||
LARGE_INTEGER zero = { 0 };
|
||||
|
||||
ok = SetFilePointerEx(handle, zero, nullptr, FILE_BEGIN);
|
||||
if (!ok) {
|
||||
set_or_throw_error(&ec, "SetFilePointerEx");
|
||||
return 0;
|
||||
}
|
||||
ok = WriteFile(handle, data, length, &rv, nullptr);
|
||||
if (!ok) {
|
||||
set_or_throw_error(&ec, "WriteFile");
|
||||
return 0;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
int fi_read(void *handle, void *data, int length, std::error_code &ec) {
|
||||
|
||||
ec.clear();
|
||||
DWORD rv = 0;
|
||||
BOOL ok;
|
||||
LARGE_INTEGER zero = { 0 };
|
||||
|
||||
ok = SetFilePointerEx(handle, zero, nullptr, FILE_BEGIN);
|
||||
if (!ok) {
|
||||
set_or_throw_error(&ec, "SetFilePointerEx");
|
||||
return 0;
|
||||
}
|
||||
ok = ReadFile(handle, data, length, &rv, nullptr);
|
||||
if (!ok) {
|
||||
set_or_throw_error(&ec, "ReadFile");
|
||||
return 0;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void fi_close(int fd) {
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int fi_open(const std::string &path, int perm, std::error_code &ec) {
|
||||
|
||||
#if defined(__sun__)
|
||||
if (perm == 1) return attropen(path.c_str(), XATTR_FINDERINFO_NAME, O_RDONLY);
|
||||
else return attropen(path.c_str(), XATTR_FINDERINFO_NAME, O_RDWR | O_CREAT, 0666);
|
||||
#else
|
||||
// linux needs to open as read/write to write it?
|
||||
//return open(path.c_str(), read_only ? O_RDONLY : O_RDWR);
|
||||
return open(path.c_str(), O_RDONLY);
|
||||
#endif
|
||||
}
|
||||
|
||||
int fi_write(int fd, const void *data, int length) {
|
||||
#if defined(__sun__) || defined(_WIN32)
|
||||
|
||||
int fi_write(int fd, const void *data, int length, std::error_code &ec) {
|
||||
#if defined(__sun__)
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
return write(fd, data, length);
|
||||
#else
|
||||
@ -223,8 +449,8 @@ namespace {
|
||||
#endif
|
||||
}
|
||||
|
||||
int fi_read(int fd, void *data, int length) {
|
||||
#if defined(__sun__) || defined(_WIN32)
|
||||
int fi_read(int fd, void *data, int length, std::error_code &ec) {
|
||||
#if defined(__sun__)
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
return read(fd, data, length);
|
||||
#else
|
||||
@ -232,6 +458,9 @@ namespace {
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
void afp_init(struct AFP_Info *info) {
|
||||
//static_assert(sizeof(AFP_Info) == 60, "Incorrect AFP_Info size");
|
||||
@ -274,10 +503,12 @@ enum {
|
||||
void afp_synchronize(struct AFP_Info *info, int trust) {
|
||||
// if ftype/auxtype is inconsistent between prodos and finder info, use
|
||||
// prodos as source of truth.
|
||||
uint16_t f;
|
||||
uint32_t a;
|
||||
if (finder_info_to_filetype(info->finder_info, &f, &a) != 0) return;
|
||||
if (f == info->prodos_file_type && a == info->prodos_aux_type) return;
|
||||
uint16_t f = 0;
|
||||
uint32_t a = 0;
|
||||
if (finder_info_to_filetype(info->finder_info, &f, &a)) {
|
||||
if (f == info->prodos_file_type && a == info->prodos_aux_type) return;
|
||||
}
|
||||
|
||||
if (trust == trust_prodos)
|
||||
file_type_to_finder_info(info->finder_info, info->prodos_file_type, info->prodos_aux_type);
|
||||
else {
|
||||
@ -300,71 +531,150 @@ finder_info_helper::finder_info_helper() {
|
||||
#endif
|
||||
}
|
||||
|
||||
finder_info_helper::~finder_info_helper() {
|
||||
void finder_info_helper::close() {
|
||||
#if _WIN32
|
||||
if (_fd != INVALID_HANDLE_VALUE) CloseHandle(_fd);
|
||||
_fd = INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
if (_fd >= 0) close(_fd);
|
||||
_fd = -1;
|
||||
#endif
|
||||
|
||||
}
|
||||
finder_info_helper::~finder_info_helper() {
|
||||
close();
|
||||
}
|
||||
|
||||
bool finder_info_helper::open(const std::string &name, bool read_only) {
|
||||
bool finder_info_helper::open(const std::string &name, open_mode perm, std::error_code &ec) {
|
||||
|
||||
if (_fd >= 0) {
|
||||
close(_fd);
|
||||
_fd = -1;
|
||||
ec.clear();
|
||||
|
||||
close();
|
||||
|
||||
if (perm < 1 || perm > 3) {
|
||||
ec = std::make_error_code(std::errc::invalid_argument);
|
||||
return false;
|
||||
}
|
||||
int fd = fi_open(name, read_only);
|
||||
if (fd < 0) return false;
|
||||
|
||||
int ok = read(fd);
|
||||
// if write mode, it's ok if finder info doesn't exist (yet).
|
||||
if (!read_only && !ok) ok = true;
|
||||
auto fd = fi_open(name, perm, ec);
|
||||
if (ec) return false;
|
||||
|
||||
if (read_only) close(fd);
|
||||
else _fd = fd;
|
||||
// win32 should read even if write-only.
|
||||
bool ok = read(_fd, ec);
|
||||
|
||||
return ok;
|
||||
if (perm == read_only) {
|
||||
fi_close(fd);
|
||||
return ok;
|
||||
}
|
||||
|
||||
// write mode, so it's ok if it doesn't exist.
|
||||
if (!ok) ec.clear();
|
||||
_fd = fd;
|
||||
return true;
|
||||
}
|
||||
#if _WIN32
|
||||
|
||||
bool finder_info_helper::open(const std::wstring &name, open_mode perm, std::error_code &ec) {
|
||||
|
||||
ec.clear();
|
||||
|
||||
close();
|
||||
|
||||
if (perm < 1 || perm > 3) {
|
||||
ec = std::make_error_code(std::errc::invalid_argument);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto fd = fi_open(name, perm, ec);
|
||||
if (ec) return false;
|
||||
|
||||
// win32 should read even if write-only.
|
||||
bool ok = read(_fd, ec);
|
||||
|
||||
if (perm == read_only) {
|
||||
fi_close(fd);
|
||||
return ok;
|
||||
}
|
||||
|
||||
// write mode, so it's ok if it doesn't exist.
|
||||
if (!ok) ec.clear();
|
||||
_fd = fd;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool finder_info_helper::read(int fd) {
|
||||
#if defined(_WIN32)
|
||||
int ok = fi_read(fd, &_afp, sizeof(_afp));
|
||||
bool finder_info_helper::read(void *fd, std::error_code &ec) {
|
||||
|
||||
int ok = fi_read(fd, &_afp, sizeof(_afp), ec);
|
||||
if (ec) {
|
||||
afp_init(&_afp);
|
||||
return false;
|
||||
}
|
||||
if (ok < sizeof(_afp) || !afp_verify(&_afp)) {
|
||||
ec = std::make_error_code(std::errc::illegal_byte_sequence); // close enough!
|
||||
afp_init(&_afp);
|
||||
return false;
|
||||
}
|
||||
if (!_afp.prodos_file_type && !_afp.prodos_aux_type)
|
||||
afp_synchronize(&_afp, trust_hfs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool finder_info_helper::write(void *fd, std::error_code &ec) {
|
||||
return fi_write(fd, &_afp, sizeof(_afp), ec) == sizeof(_afp);
|
||||
}
|
||||
|
||||
#else
|
||||
int ok = fi_read(fd, &_finder_info, sizeof(_finder_info));
|
||||
|
||||
bool finder_info_helper::read(int fd, std::error_code &ec) {
|
||||
|
||||
int ok = fi_read(fd, &_finder_info, sizeof(_finder_info), ec);
|
||||
if (ok < 0) {
|
||||
memset(&_finder_info, 0, sizeof(_finder_info));
|
||||
return false;
|
||||
}
|
||||
finder_info_to_filetype(_finder_info, &_prodos_file_type, &_prodos_aux_type);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool finder_info_helper::write(int fd) {
|
||||
#if defined(_WIN32)
|
||||
return fi_write(fd, &_afp, sizeof(_afp));
|
||||
#else
|
||||
return fi_write(fd, &_finder_info, sizeof(_finder_info));
|
||||
bool finder_info_helper::write(int fd, std::error_code &ec) {
|
||||
return fi_write(fd, &_finder_info, sizeof(_finder_info), ec) == sizeof(_finder_info);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
bool finder_info_helper::write() {
|
||||
return write(_fd);
|
||||
bool finder_info_helper::write(std::error_code &ec) {
|
||||
ec.clear();
|
||||
return write(_fd, ec);
|
||||
}
|
||||
|
||||
|
||||
bool finder_info_helper::write(const std::string &name) {
|
||||
int fd = fi_open(name, false);
|
||||
if (fd < 0) return false;
|
||||
bool ok = write(fd);
|
||||
close(fd);
|
||||
bool finder_info_helper::write(const std::string &name, std::error_code &ec) {
|
||||
ec.clear();
|
||||
auto fd = fi_open(name, write_only, ec);
|
||||
|
||||
if (ec)
|
||||
return false;
|
||||
|
||||
bool ok = write(fd, ec);
|
||||
fi_close(fd);
|
||||
return ok;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
bool finder_info_helper::write(const std::wstring &name, std::error_code &ec) {
|
||||
ec.clear();
|
||||
auto fd = fi_open(name, write_only, ec);
|
||||
|
||||
if (ec)
|
||||
return false;
|
||||
|
||||
bool ok = write(fd, ec);
|
||||
fi_close(fd);
|
||||
return ok;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void finder_info_helper::set_prodos_file_type(uint16_t ftype, uint32_t atype) {
|
||||
_prodos_file_type = ftype;
|
||||
@ -385,6 +695,15 @@ bool finder_info_helper::is_text() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool finder_info_helper::is_binary() const {
|
||||
if (is_text()) return false;
|
||||
if (_prodos_file_type || _prodos_aux_type) return true;
|
||||
|
||||
if (memcmp(_finder_info, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) == 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t finder_info_helper::file_type() const {
|
||||
uint32_t rv = 0;
|
||||
|
@ -2,6 +2,9 @@
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
#include <system_error>
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma pack(push, 2)
|
||||
struct AFP_Info {
|
||||
@ -22,6 +25,12 @@ class finder_info_helper {
|
||||
|
||||
public:
|
||||
|
||||
enum open_mode {
|
||||
read_only = 1,
|
||||
write_only = 2,
|
||||
read_write = 3,
|
||||
};
|
||||
|
||||
finder_info_helper();
|
||||
~finder_info_helper();
|
||||
|
||||
@ -33,26 +42,50 @@ public:
|
||||
|
||||
|
||||
const uint8_t *finder_info() const {
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32)
|
||||
return _afp.finder_info;
|
||||
#else
|
||||
#else
|
||||
return _finder_info;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t *finder_info() {
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32)
|
||||
return _afp.finder_info;
|
||||
#else
|
||||
#else
|
||||
return _finder_info;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool read(const std::string &fname);
|
||||
bool write(const std::string &fname);
|
||||
bool open(const std::string &fname, bool read_only = true);
|
||||
bool write();
|
||||
bool read(const std::string &fname, std::error_code &ec) {
|
||||
return open(fname, read_only, ec);
|
||||
}
|
||||
|
||||
bool write(const std::string &fname, std::error_code &ec);
|
||||
|
||||
bool open(const std::string &fname, open_mode perm, std::error_code &ec);
|
||||
bool open(const std::string &fname, std::error_code &ec) {
|
||||
return open(fname, read_only, ec);
|
||||
}
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
bool read(const std::wstring &pathName, std::error_code &ec) {
|
||||
return open(pathName, read_only, ec);
|
||||
}
|
||||
|
||||
bool write(const std::wstring &pathName, std::error_code &ec);
|
||||
|
||||
bool open(const std::wstring &fname, open_mode perm, std::error_code &ec);
|
||||
bool open(const std::wstring &fname, std::error_code &ec) {
|
||||
return open(fname, read_only, ec);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
bool write(std::error_code &ec);
|
||||
|
||||
uint32_t creator_type() const;
|
||||
uint32_t file_type() const;
|
||||
@ -80,17 +113,26 @@ public:
|
||||
void set_creator_type(uint32_t);
|
||||
|
||||
bool is_text() const;
|
||||
bool is_binary() const;
|
||||
|
||||
private:
|
||||
|
||||
bool write(int fd);
|
||||
bool read(int fd);
|
||||
void close();
|
||||
|
||||
int _fd = -1;
|
||||
#if defined(_WIN32)
|
||||
bool write(void *handle, std::error_code &ec);
|
||||
bool read(void *handle, std::error_code &ec);
|
||||
#else
|
||||
bool write(int fd, std::error_code &ec);
|
||||
bool read(int fd, std::error_code &ec);
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
void *_fd = (void *)-1;
|
||||
AFP_Info _afp;
|
||||
#else
|
||||
int _fd = -1;
|
||||
|
||||
uint16_t _prodos_file_type = 0;
|
||||
uint32_t _prodos_aux_type = 0;
|
||||
uint8_t _finder_info[32] = {};
|
||||
|
@ -32,6 +32,17 @@ namespace {
|
||||
set_or_throw_error(ec, e, what);
|
||||
}
|
||||
|
||||
|
||||
template<class ...Args>
|
||||
HANDLE CreateFileX(const std::string &s, Args... args) {
|
||||
return CreateFileA(s.c_str(), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class ...Args>
|
||||
HANDLE CreateFileX(const std::wstring &s, Args... args) {
|
||||
return CreateFileW(s.c_str(), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void mapped_file_base::close() {
|
||||
@ -44,7 +55,8 @@ void mapped_file_base::close() {
|
||||
}
|
||||
}
|
||||
|
||||
void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, size_t offset, std::error_code *ec) {
|
||||
template<class T>
|
||||
void mapped_file_base::open_common(const T& p, mapmode flags, size_t length, size_t offset, std::error_code *ec) {
|
||||
|
||||
if (ec) ec->clear();
|
||||
|
||||
@ -56,7 +68,7 @@ void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, si
|
||||
|
||||
if (is_open()) close();
|
||||
|
||||
fh = CreateFile(p.c_str(),
|
||||
fh = CreateFileX(p,
|
||||
flags == readonly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
nullptr,
|
||||
@ -73,7 +85,7 @@ void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, si
|
||||
if (length == -1) {
|
||||
LARGE_INTEGER file_size;
|
||||
GetFileSizeEx(fh, &file_size);
|
||||
length = file_size.QuadPart;
|
||||
length = (size_t)file_size.QuadPart;
|
||||
}
|
||||
|
||||
if (length == 0) return;
|
||||
@ -102,10 +114,13 @@ void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, si
|
||||
auto mh_close = make_unique_resource(mh, CloseHandle);
|
||||
|
||||
|
||||
ULARGE_INTEGER ll;
|
||||
ll.QuadPart = offset;
|
||||
|
||||
_data = MapViewOfFileEx(mh,
|
||||
access,
|
||||
(DWORD)(offset >> 32),
|
||||
(DWORD)offset,
|
||||
ll.HighPart,
|
||||
ll.LowPart,
|
||||
length,
|
||||
nullptr);
|
||||
if (!_data)
|
||||
@ -118,8 +133,19 @@ void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, si
|
||||
_flags = flags;
|
||||
}
|
||||
|
||||
void mapped_file_base::open(const std::string &p, mapmode flags, size_t length, size_t offset, std::error_code *ec) {
|
||||
open_common(p, flags, length, offset, ec);
|
||||
}
|
||||
|
||||
void mapped_file_base::create(const path_type& p, size_t length, std::error_code *ec) {
|
||||
void mapped_file_base::open(const std::wstring &p, mapmode flags, size_t length, size_t offset, std::error_code *ec) {
|
||||
open_common(p, flags, length, offset, ec);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<class T>
|
||||
void mapped_file_base::create_common(const T& p, size_t length, std::error_code *ec) {
|
||||
|
||||
if (ec) ec->clear();
|
||||
|
||||
@ -135,7 +161,7 @@ void mapped_file_base::create(const path_type& p, size_t length, std::error_code
|
||||
|
||||
if (is_open()) close();
|
||||
|
||||
fh = CreateFile(p.c_str(),
|
||||
fh = CreateFileX(p,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
nullptr,
|
||||
@ -163,10 +189,13 @@ void mapped_file_base::create(const path_type& p, size_t length, std::error_code
|
||||
|
||||
auto mh_close = make_unique_resource(mh, CloseHandle);
|
||||
|
||||
ULARGE_INTEGER ll;
|
||||
ll.QuadPart = offset;
|
||||
|
||||
_data = MapViewOfFileEx(mh,
|
||||
access,
|
||||
(DWORD)(offset >> 32),
|
||||
(DWORD)offset,
|
||||
ll.HighPart,
|
||||
ll.LowPart,
|
||||
length,
|
||||
nullptr);
|
||||
|
||||
@ -180,7 +209,12 @@ void mapped_file_base::create(const path_type& p, size_t length, std::error_code
|
||||
_flags = readwrite;
|
||||
}
|
||||
|
||||
|
||||
void mapped_file_base::create(const std::string &p, size_t length, std::error_code *ec) {
|
||||
create_common(p, length, ec);
|
||||
}
|
||||
void mapped_file_base::create(const std::wstring &p, size_t length, std::error_code *ec) {
|
||||
create_common(p, length, ec);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
@ -213,7 +247,7 @@ void mapped_file_base::close() {
|
||||
}
|
||||
|
||||
|
||||
void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, size_t offset, std::error_code *ec) {
|
||||
void mapped_file_base::open(const std::string& p, mapmode flags, size_t length, size_t offset, std::error_code *ec) {
|
||||
|
||||
if (ec) ec->clear();
|
||||
|
||||
@ -267,7 +301,7 @@ void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, si
|
||||
_flags = flags;
|
||||
}
|
||||
|
||||
void mapped_file_base::create(const path_type& p, size_t length, std::error_code *ec) {
|
||||
void mapped_file_base::create(const std::string& p, size_t length, std::error_code *ec) {
|
||||
|
||||
if (ec) ec->clear();
|
||||
|
||||
|
@ -1,15 +1,13 @@
|
||||
#ifndef __mapped_file_h__
|
||||
#define __mapped_file_h__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <cstddef>
|
||||
#include <system_error>
|
||||
#include <string>
|
||||
|
||||
class mapped_file_base {
|
||||
public:
|
||||
|
||||
typedef std::string path_type;
|
||||
|
||||
enum mapmode { readonly, readwrite, priv };
|
||||
enum createmode { truncate, exclusive };
|
||||
@ -33,8 +31,22 @@ protected:
|
||||
|
||||
void swap(mapped_file_base &rhs);
|
||||
|
||||
void open(const path_type& p, mapmode flags, size_t length, size_t offset, std::error_code *ec);
|
||||
void create(const path_type &p, size_t new_size, std::error_code *ec); // always creates readwrite.
|
||||
void open(const std::string &p, mapmode flags, size_t length, size_t offset, std::error_code *ec);
|
||||
void create(const std::string &p, size_t new_size, std::error_code *ec); // always creates readwrite.
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
void open(const std::wstring &p, mapmode flags, size_t length, size_t offset, std::error_code *ec);
|
||||
void create(const std::wstring &p, size_t new_size, std::error_code *ec); // always creates readwrite.
|
||||
|
||||
template<class S>
|
||||
void open_common(const S &p, mapmode flags, size_t length, size_t offset, std::error_code *ec);
|
||||
|
||||
template<class S>
|
||||
void create_common(const S &p, size_t new_size, std::error_code *ec); // always creates readwrite.
|
||||
|
||||
#endif
|
||||
|
||||
void reset();
|
||||
|
||||
|
||||
@ -68,22 +80,22 @@ public:
|
||||
|
||||
|
||||
mapped_file() = default;
|
||||
mapped_file(const path_type& p, mapmode flags = readonly, size_t length = -1, size_t offset = 0) {
|
||||
mapped_file(const std::string &p, mapmode flags = readonly, size_t length = -1, size_t offset = 0) {
|
||||
open(p, flags, length, offset);
|
||||
}
|
||||
|
||||
mapped_file(const path_type &p, std::error_code &ec) noexcept {
|
||||
mapped_file(const std::string &p, std::error_code &ec) noexcept {
|
||||
open(p, readonly, -1, 0, ec);
|
||||
}
|
||||
mapped_file(const path_type &p, mapmode flags, std::error_code &ec) noexcept {
|
||||
mapped_file(const std::string &p, mapmode flags, std::error_code &ec) noexcept {
|
||||
open(p, flags, -1, 0, ec);
|
||||
}
|
||||
|
||||
mapped_file(const path_type &p, mapmode flags, size_t length, std::error_code &ec) noexcept {
|
||||
mapped_file(const std::string &p, mapmode flags, size_t length, std::error_code &ec) noexcept {
|
||||
open(p, flags, length, 0, ec);
|
||||
}
|
||||
|
||||
mapped_file(const path_type &p, mapmode flags, size_t length, size_t offset, std::error_code &ec) noexcept {
|
||||
mapped_file(const std::string &p, mapmode flags, size_t length, size_t offset, std::error_code &ec) noexcept {
|
||||
open(p, flags, length, offset, ec);
|
||||
}
|
||||
|
||||
@ -95,31 +107,57 @@ public:
|
||||
mapped_file &operator=(const mapped_file &) = delete;
|
||||
|
||||
|
||||
void open(const path_type& p, mapmode flags, size_t length = -1, size_t offset = 0) {
|
||||
void open(const std::string &p, mapmode flags, size_t length = -1, size_t offset = 0) {
|
||||
base::open(p, flags, length, offset, nullptr);
|
||||
}
|
||||
|
||||
void open(const path_type &p, std::error_code &ec) noexcept {
|
||||
void open(const std::string &p, std::error_code &ec) noexcept {
|
||||
base::open(p, readonly, -1, 0, &ec);
|
||||
}
|
||||
void open(const path_type &p, mapmode flags, std::error_code &ec) noexcept {
|
||||
void open(const std::string &p, mapmode flags, std::error_code &ec) noexcept {
|
||||
base::open(p, flags, -1, 0, &ec);
|
||||
}
|
||||
void open(const path_type &p, mapmode flags, size_t length, std::error_code &ec) noexcept {
|
||||
void open(const std::string &p, mapmode flags, size_t length, std::error_code &ec) noexcept {
|
||||
base::open(p, flags, length, 0, &ec);
|
||||
}
|
||||
void open(const path_type &p, mapmode flags, size_t length, size_t offset, std::error_code &ec) noexcept {
|
||||
void open(const std::string &p, mapmode flags, size_t length, size_t offset, std::error_code &ec) noexcept {
|
||||
base::open(p, flags, length, offset, &ec);
|
||||
}
|
||||
|
||||
void create(const path_type &p, size_t size) {
|
||||
base::create(p, size, nullptr);
|
||||
#ifdef _WIN32
|
||||
void open(const std::wstring &p, mapmode flags, size_t length = -1, size_t offset = 0) {
|
||||
base::open(p, flags, length, offset, nullptr);
|
||||
}
|
||||
void open(const std::wstring &p, std::error_code &ec) noexcept {
|
||||
base::open(p, readonly, -1, 0, &ec);
|
||||
}
|
||||
void open(const std::wstring &p, mapmode flags, std::error_code &ec) noexcept {
|
||||
base::open(p, flags, -1, 0, &ec);
|
||||
}
|
||||
void open(const std::wstring &p, mapmode flags, size_t length, std::error_code &ec) noexcept {
|
||||
base::open(p, flags, length, 0, &ec);
|
||||
}
|
||||
void open(const std::wstring &p, mapmode flags, size_t length, size_t offset, std::error_code &ec) noexcept {
|
||||
base::open(p, flags, length, offset, &ec);
|
||||
}
|
||||
|
||||
void create(const path_type &p, size_t size, std::error_code &ec) noexcept {
|
||||
#endif
|
||||
|
||||
void create(const std::string &p, size_t size) {
|
||||
base::create(p, size, nullptr);
|
||||
}
|
||||
void create(const std::string &p, size_t size, std::error_code &ec) noexcept {
|
||||
base::create(p, size, &ec);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void create(const std::wstring &p, size_t size) {
|
||||
base::create(p, size, nullptr);
|
||||
}
|
||||
void create(const std::wstring &p, size_t size, std::error_code &ec) noexcept {
|
||||
base::create(p, size, &ec);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
const value_type *data() const {
|
||||
return (const value_type *)_data;
|
||||
|
Loading…
Reference in New Issue
Block a user