update finder_info_helper.

This commit is contained in:
Kelvin Sherlock 2017-03-06 00:39:50 -05:00
parent 97787b30e4
commit ebd67dc0cc
3 changed files with 164 additions and 36 deletions

View File

@ -206,6 +206,12 @@ namespace {
}
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.
*/
@ -293,19 +299,30 @@ namespace {
int fi_open(const std::wstring &path, int perm) {
#if defined(_WIN32)
std::wstring s(path);
s.append(L":" XATTR_FINDERINFO_NAME);
if (perm == 1) return open(s.c_str(), O_RDONLY | O_BINARY);
else return open(s.c_str(), O_RDWR | O_CREAT | O_BINARY, 0666);
#else
int fi_open(const std::string &path, bool read_only) {
#endif
}
int fi_open(const std::string &path, int perm) {
#if defined(__sun__)
if (read_only) return attropen(path.c_str(), XATTR_FINDERINFO_NAME, O_RDONLY);
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);
#elif defined(_WIN32)
std::string s(path);
s.append(":" XATTR_FINDERINFO_NAME);
if (read_only) return open(s.c_str(), O_RDONLY | O_BINARY);
if (perm == 1) return open(s.c_str(), O_RDONLY | O_BINARY);
else return open(s.c_str(), O_RDWR | O_CREAT | O_BINARY, 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
}
@ -370,10 +387,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 {
@ -400,36 +419,86 @@ finder_info_helper::~finder_info_helper() {
if (_fd >= 0) close(_fd);
}
bool finder_info_helper::open(const std::string &name, bool read_only) {
bool finder_info_helper::open(const std::string &name, std::error_code &ec, open_mode perm) {
ec.clear();
if (_fd >= 0) {
close(_fd);
_fd = -1;
}
int fd = fi_open(name, read_only);
if (perm < 1 || perm > 3) {
ec = std::make_error_code(std::errc::invalid_argument);
return false;
}
int fd = _(fi_open(name, perm), ec);
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;
// win32 should read even if write-only.
bool ok = read(fd, ec);
if (read_only) close(fd);
else _fd = fd;
if (perm == read_only) {
close(fd);
return ok;
}
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 0
bool finder_info_helper::open(const filesystem::path &pathName, std::error_code &ec, open_mode perm) {
ec.clear();
if (_fd >= 0) {
close(_fd);
_fd = -1;
}
if (perm < 1 || perm > 3) {
ec = std::make_error_code(std::errc::invalid_argument);
return false;
}
int fd = _(fi_open(pathName.native(), perm), ec);
if (fd < 0) return false;
// win32 should read even if write-only.
bool ok = read(fd, ec);
if (perm == read_only) {
close(fd);
return ok;
}
// write mode, so it's ok if it doesn't exist.
if (!ok) ec.clear();
_fd = fd;
return true;
}
#endif
bool finder_info_helper::read(int fd, std::error_code &ec) {
#if defined(_WIN32)
int ok = fi_read(fd, &_afp, sizeof(_afp));
int ok = _(fi_read(fd, &_afp, sizeof(_afp)), ec);
if (ok < 0) {
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);
#else
int ok = fi_read(fd, &_finder_info, sizeof(_finder_info));
int ok = _(fi_read(fd, &_finder_info, sizeof(_finder_info)), ec);
if (ok < 0) {
memset(&_finder_info, 0, sizeof(_finder_info));
return false;
@ -439,27 +508,44 @@ bool finder_info_helper::read(int fd) {
return true;
}
bool finder_info_helper::write(int fd) {
bool finder_info_helper::write(int fd, std::error_code &ec) {
#if defined(_WIN32)
return fi_write(fd, &_afp, sizeof(_afp));
return _(fi_write(fd, &_afp, sizeof(_afp)),ec);
#else
return fi_write(fd, &_finder_info, sizeof(_finder_info));
return _(fi_write(fd, &_finder_info, sizeof(_finder_info)),ec);
#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);
bool finder_info_helper::write(const std::string &name, std::error_code &ec) {
ec.clear();
int fd = _(fi_open(name, write_only), ec);
if (fd < 0)
return false;
bool ok = write(fd, ec);
close(fd);
return ok;
}
#if 0
bool finder_info_helper::write(const filesystem::path &pathName, std::error_code &ec) {
ec.clear();
int fd = _(fi_open(pathName.native(), write_only), ec);
if (fd < 0)
return false;
bool ok = write(fd, ec);
close(fd);
return ok;
}
#endif
void finder_info_helper::set_prodos_file_type(uint16_t ftype, uint32_t atype) {
@ -481,6 +567,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,8 @@
#include <stdint.h>
#include <string>
#include <system_error>
#if defined(_WIN32)
#pragma pack(push, 2)
struct AFP_Info {
@ -22,6 +24,12 @@ class finder_info_helper {
public:
enum open_mode {
read_only = 1,
write_only = 2,
read_write = 3,
};
finder_info_helper();
~finder_info_helper();
@ -49,10 +57,33 @@ public:
}
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, ec);
}
bool write(const std::string &fname, std::error_code &ec);
bool open(
const std::string &fname,
std::error_code &ec,
open_mode perm = read_only
);
#if 0
bool read(const filesystem::path &pathName, std::error_code &ec) {
return open(pathName, ec);
}
bool write(const filesystem::path &pathName, std::error_code &ec);
bool open(
const filesystem::path &pathName,
std::error_code &ec,
open_mode perm = read_only
);
#endif
bool write(std::error_code &ec);
uint32_t creator_type() const;
uint32_t file_type() const;
@ -80,11 +111,12 @@ public:
void set_creator_type(uint32_t);
bool is_text() const;
bool is_binary() const;
private:
bool write(int fd);
bool read(int fd);
bool write(int fd, std::error_code &ec);
bool read(int fd, std::error_code &ec);
int _fd = -1;

View File

@ -9,10 +9,11 @@ int set_file_type(const std::string &path, uint16_t file_type, uint32_t aux_type
finder_info_helper fi;
bool ok;
ok = fi.open(path, false);
std::error_code ec;
ok = fi.open(path, ec, finder_info_helper::read_write);
if (!ok) return -1;
fi.set_prodos_file_type(file_type, aux_type);
ok = fi.write();
ok = fi.write(ec);
if (!ok) return -1;
return 0;