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. * 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 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); else return attropen(path.c_str(), XATTR_FINDERINFO_NAME, O_RDWR | O_CREAT, 0666);
#elif defined(_WIN32) #elif defined(_WIN32)
std::string s(path); std::string s(path);
s.append(":" XATTR_FINDERINFO_NAME); 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 return open(s.c_str(), O_RDWR | O_CREAT | O_BINARY, 0666);
#else #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); return open(path.c_str(), O_RDONLY);
#endif #endif
} }
@ -370,10 +387,12 @@ enum {
void afp_synchronize(struct AFP_Info *info, int trust) { void afp_synchronize(struct AFP_Info *info, int trust) {
// if ftype/auxtype is inconsistent between prodos and finder info, use // if ftype/auxtype is inconsistent between prodos and finder info, use
// prodos as source of truth. // prodos as source of truth.
uint16_t f; uint16_t f = 0;
uint32_t a; uint32_t a = 0;
if (finder_info_to_filetype(info->finder_info, &f, &a) != 0) return; if (finder_info_to_filetype(info->finder_info, &f, &a)) {
if (f == info->prodos_file_type && a == info->prodos_aux_type) return; if (f == info->prodos_file_type && a == info->prodos_aux_type) return;
}
if (trust == trust_prodos) if (trust == trust_prodos)
file_type_to_finder_info(info->finder_info, info->prodos_file_type, info->prodos_aux_type); file_type_to_finder_info(info->finder_info, info->prodos_file_type, info->prodos_aux_type);
else { else {
@ -400,36 +419,86 @@ finder_info_helper::~finder_info_helper() {
if (_fd >= 0) close(_fd); 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) { if (_fd >= 0) {
close(_fd); close(_fd);
_fd = -1; _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; if (fd < 0) return false;
int ok = read(fd); // win32 should read even if write-only.
// if write mode, it's ok if finder info doesn't exist (yet). bool ok = read(fd, ec);
if (!read_only && !ok) ok = true;
if (read_only) close(fd); if (perm == read_only) {
else _fd = fd; 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) #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)) { if (ok < sizeof(_afp) || !afp_verify(&_afp)) {
ec = std::make_error_code(std::errc::illegal_byte_sequence); // close enough!
afp_init(&_afp); afp_init(&_afp);
return false; return false;
} }
if (!_afp.prodos_file_type && !_afp.prodos_aux_type) if (!_afp.prodos_file_type && !_afp.prodos_aux_type)
afp_synchronize(&_afp, trust_hfs); afp_synchronize(&_afp, trust_hfs);
#else #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) { if (ok < 0) {
memset(&_finder_info, 0, sizeof(_finder_info)); memset(&_finder_info, 0, sizeof(_finder_info));
return false; return false;
@ -439,27 +508,44 @@ bool finder_info_helper::read(int fd) {
return true; return true;
} }
bool finder_info_helper::write(int fd) { bool finder_info_helper::write(int fd, std::error_code &ec) {
#if defined(_WIN32) #if defined(_WIN32)
return fi_write(fd, &_afp, sizeof(_afp)); return _(fi_write(fd, &_afp, sizeof(_afp)),ec);
#else #else
return fi_write(fd, &_finder_info, sizeof(_finder_info)); return _(fi_write(fd, &_finder_info, sizeof(_finder_info)),ec);
#endif #endif
} }
bool finder_info_helper::write() { bool finder_info_helper::write(std::error_code &ec) {
return write(_fd); ec.clear();
return write(_fd, ec);
} }
bool finder_info_helper::write(const std::string &name) { bool finder_info_helper::write(const std::string &name, std::error_code &ec) {
int fd = fi_open(name, false); ec.clear();
if (fd < 0) return false; int fd = _(fi_open(name, write_only), ec);
bool ok = write(fd);
if (fd < 0)
return false;
bool ok = write(fd, ec);
close(fd); close(fd);
return ok; 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) { 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; 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 finder_info_helper::file_type() const {
uint32_t rv = 0; uint32_t rv = 0;

View File

@ -2,6 +2,8 @@
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <system_error>
#if defined(_WIN32) #if defined(_WIN32)
#pragma pack(push, 2) #pragma pack(push, 2)
struct AFP_Info { struct AFP_Info {
@ -22,6 +24,12 @@ class finder_info_helper {
public: public:
enum open_mode {
read_only = 1,
write_only = 2,
read_write = 3,
};
finder_info_helper(); finder_info_helper();
~finder_info_helper(); ~finder_info_helper();
@ -49,10 +57,33 @@ public:
} }
bool read(const std::string &fname); bool read(const std::string &fname, std::error_code &ec) {
bool write(const std::string &fname); return open(fname, ec);
bool open(const std::string &fname, bool read_only = true); }
bool write();
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 creator_type() const;
uint32_t file_type() const; uint32_t file_type() const;
@ -80,11 +111,12 @@ public:
void set_creator_type(uint32_t); void set_creator_type(uint32_t);
bool is_text() const; bool is_text() const;
bool is_binary() const;
private: private:
bool write(int fd); bool write(int fd, std::error_code &ec);
bool read(int fd); bool read(int fd, std::error_code &ec);
int _fd = -1; 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; finder_info_helper fi;
bool ok; 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; if (!ok) return -1;
fi.set_prodos_file_type(file_type, aux_type); fi.set_prodos_file_type(file_type, aux_type);
ok = fi.write(); ok = fi.write(ec);
if (!ok) return -1; if (!ok) return -1;
return 0; return 0;