updated finder_info, mapped_file, etc

This commit is contained in:
Kelvin Sherlock 2017-07-23 15:29:28 -04:00
parent faec01b209
commit d12a961627
7 changed files with 570 additions and 112 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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");
}
}

View File

@ -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;

View File

@ -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] = {};

View File

@ -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();

View File

@ -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;