diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8e5ca65 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "afp"] + path = afp + url = https://github.com/ksherlock/afp diff --git a/Makefile b/Makefile index a1c6b27..141b685 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ LINK.o = $(LINK.cc) -CXXFLAGS = -std=c++14 -g -Wall -Wno-sign-compare +CXXFLAGS = -std=c++14 -g -Wall -Wno-sign-compare CCFLAGS = -g DUMP_OBJS = dumpobj.o disassembler.o zrdz_disassembler.o -LINK_OBJS = link.o expression.o omf.o set_file_type.o finder_info_helper.o +LINK_OBJS = link.o expression.o omf.o set_file_type.o afp/libafp.a # static link if using mingw32 or mingw64 to make redistribution easier. # also add mingw directory. @@ -31,17 +31,25 @@ wdclink : $(LINK_OBJS) $(LINK.o) $^ $(LDLIBS) -o $@ +subdirs : + $(MAKE) -C afp + disassembler.o : disassembler.cpp disassembler.h zrdz_disassembler.o : zrdz_disassembler.cpp zrdz_disassembler.h disassembler.h dumpobj.o : dumpobj.cpp zrdz_disassembler.h disassembler.h omf.o : omf.cpp omf.h expression.o : expression.cpp expression.h -finder_info_helper.o : finder_info_helper.cpp finder_info_helper.h mingw/err.o : mingw/err.c mingw/err.h +set_file_type.o : CPPFLAGS += -I afp/include +set_file_type.o : set_file_type.cpp + +afp/libafp.a : subdirs + .PHONY: clean clean: $(RM) wdcdumpobj wdclink $(DUMP_OBJS) $(LINK_OBJS) + $(MAKE) -C afp clean .PHONY: variables diff --git a/afp b/afp new file mode 160000 index 0000000..dc3c9ed --- /dev/null +++ b/afp @@ -0,0 +1 @@ +Subproject commit dc3c9ed1ce0b35bcf3edf27bb9c71bfad46a7a99 diff --git a/finder_info_helper.cpp b/finder_info_helper.cpp deleted file mode 100644 index b1d3029..0000000 --- a/finder_info_helper.cpp +++ /dev/null @@ -1,611 +0,0 @@ -#include "finder_info_helper.h" - -#include -#include -#include -#include - -#include -#include - -#if defined(__APPLE__) -#include -#endif - -#if defined(__linux__) -#include -#define XATTR_FINDERINFO_NAME "user.com.apple.FinderInfo" -#define XATTR_RESOURCEFORK_NAME "user.com.apple.ResourceFork" -#endif - -#if defined(__FreeBSD__) -#include -#include -#endif - -#if defined(_AIX) -#include -#endif - - -#if defined (_WIN32) -#define XATTR_FINDERINFO_NAME "AFP_AfpInfo" -#endif - -#ifndef XATTR_FINDERINFO_NAME -#define XATTR_FINDERINFO_NAME "com.apple.FinderInfo" -#endif - - -#if defined(_WIN32) -#define _prodos_file_type _afp.prodos_file_type -#define _prodos_aux_type _afp.prodos_aux_type -#define _finder_info _afp.finder_info -#endif - -namespace { - - /* - - tech note PT515 - ProDOS -> Macintosh conversion - - ProDOS Macintosh - Filetype Auxtype Creator Filetype - $00 $0000 'pdos' 'BINA' - $B0 (SRC) (any) 'pdos' 'TEXT' - $04 (TXT) $0000 'pdos' 'TEXT' - $FF (SYS) (any) 'pdos' 'PSYS' - $B3 (S16) (any) 'pdos' 'PS16' - $uv $wxyz 'pdos' 'p' $uv $wx $yz - - Programmer's Reference for System 6.0: - - ProDOS Macintosh - File Type Auxiliary Type Creator Type File Type - $00 $0000 “pdos” “BINA” - $04 (TXT) $0000 “pdos” “TEXT” - $FF (SYS) (any) “pdos” “PSYS” - $B3 (S16) $DByz “pdos” “p” $B3 $DB $yz - $B3 (S16) (any) “pdos” “PS16” - $D7 $0000 “pdos” “MIDI” - $D8 $0000 “pdos” “AIFF” - $D8 $0001 “pdos” “AIFC” - $E0 $0005 “dCpy” “dImg” - $FF (SYS) (any) “pdos” “PSYS” - $uv $wxyz “pdos” “p” $uv $wx $yz - - - mpw standard: - $uv (any) "pdos" printf("%02x ",$uv) - - */ - - - - int hex(uint8_t c) - { - if (c >= '0' && c <= '9') return c - '0'; - if (c >= 'a' && c <= 'f') return c + 10 - 'a'; - if (c >= 'A' && c <= 'F') return c + 10 - 'A'; - return 0; - } - - - bool finder_info_to_filetype(const uint8_t *buffer, uint16_t *file_type, uint32_t *aux_type) { - - if (!memcmp("pdos", buffer + 4, 4)) - { - if (buffer[0] == 'p') { - *file_type = buffer[1]; - *aux_type = (buffer[2] << 8) | buffer[3]; - return true; - } - if (!memcmp("PSYS", buffer, 4)) { - *file_type = 0xff; - *aux_type = 0x0000; - return true; - } - if (!memcmp("PS16", buffer, 4)) { - *file_type = 0xb3; - *aux_type = 0x0000; - return true; - } - - // old mpw method for encoding. - if (!isxdigit(buffer[0]) && isxdigit(buffer[1]) && buffer[2] == ' ' && buffer[3] == ' ') - { - *file_type = (hex(buffer[0]) << 8) | hex(buffer[1]); - *aux_type = 0; - return true; - } - } - if (!memcmp("TEXT", buffer, 4)) { - *file_type = 0x04; - *aux_type = 0x0000; - return true; - } - if (!memcmp("BINA", buffer, 4)) { - *file_type = 0x00; - *aux_type = 0x0000; - return true; - } - if (!memcmp("dImgdCpy", buffer, 8)) { - *file_type = 0xe0; - *aux_type = 0x0005; - return true; - } - - if (!memcmp("MIDI", buffer, 4)) { - *file_type = 0xd7; - *aux_type = 0x0000; - return true; - } - - if (!memcmp("AIFF", buffer, 4)) { - *file_type = 0xd8; - *aux_type = 0x0000; - return true; - } - - if (!memcmp("AIFC", buffer, 4)) { - *file_type = 0xd8; - *aux_type = 0x0001; - return true; - } - - return false; - } - - bool file_type_to_finder_info(uint8_t *buffer, uint16_t file_type, uint32_t aux_type) { - if (file_type > 0xff || aux_type > 0xffff) return false; - - if (!file_type && aux_type == 0x0000) { - memcpy(buffer, "BINApdos", 8); - return true; - } - - if (file_type == 0x04 && aux_type == 0x0000) { - memcpy(buffer, "TEXTpdos", 8); - return true; - } - - if (file_type == 0xff && aux_type == 0x0000) { - memcpy(buffer, "PSYSpdos", 8); - return true; - } - - if (file_type == 0xb3 && aux_type == 0x0000) { - memcpy(buffer, "PS16pdos", 8); - return true; - } - - if (file_type == 0xd7 && aux_type == 0x0000) { - memcpy(buffer, "MIDIpdos", 8); - return true; - } - if (file_type == 0xd8 && aux_type == 0x0000) { - memcpy(buffer, "AIFFpdos", 8); - return true; - } - if (file_type == 0xd8 && aux_type == 0x0001) { - memcpy(buffer, "AIFCpdos", 8); - return true; - } - if (file_type == 0xe0 && aux_type == 0x0005) { - memcpy(buffer, "dImgdCpy", 8); - return true; - } - - - memcpy(buffer, "p pdos", 8); - buffer[1] = (file_type) & 0xff; - buffer[2] = (aux_type >> 8) & 0xff; - buffer[3] = (aux_type) & 0xff; - return true; - } - - - template - 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 - - - - - - - - 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 - -#endif - } - - int fi_open(const std::string &path, int perm) { - - #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); - #elif defined(_WIN32) - std::string s(path); - s.append(":" 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 - // 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) - lseek(fd, 0, SEEK_SET); - return write(fd, data, length); - #else - return write_xattr(fd, XATTR_FINDERINFO_NAME, data, length); - #endif - } - - int fi_read(int fd, void *data, int length) { - #if defined(__sun__) || defined(_WIN32) - lseek(fd, 0, SEEK_SET); - return read(fd, data, length); - #else - return read_xattr(fd, XATTR_FINDERINFO_NAME, data, length); - #endif - } - -#if defined(_WIN32) -void afp_init(struct AFP_Info *info) { - //static_assert(sizeof(AFP_Info) == 60, "Incorrect AFP_Info size"); - memset(info, 0, sizeof(*info)); - info->magic = 0x00504641; - info->version = 0x00010000; - info->backup_date = 0x80000000; -} - -int afp_verify(struct AFP_Info *info) { - if (!info) return 0; - - if (info->magic != 0x00504641) return 0; - if (info->version != 0x00010000) return 0; - - return 1; -} - - -int afp_to_filetype(struct AFP_Info *info, uint16_t *file_type, uint32_t *aux_type) { - // check for prodos ftype/auxtype... - if (info->prodos_file_type || info->prodos_aux_type) { - *file_type = info->prodos_file_type; - *aux_type = info->prodos_aux_type; - return 0; - } - int ok = finder_info_to_filetype(info->finder_info, file_type, aux_type); - if (ok == 0) { - info->prodos_file_type = *file_type; - info->prodos_aux_type = *aux_type; - } - return 0; -} - -enum { - trust_prodos, - trust_hfs -}; - -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 = 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 { - info->prodos_file_type = f; - info->prodos_aux_type = a; - } -} - - - -#endif - -} - -finder_info_helper::finder_info_helper() { -#if defined(_WIN32) - afp_init(&_afp); -#else - memset(&_finder_info, 0, sizeof(_finder_info)); -#endif -} - -finder_info_helper::~finder_info_helper() { - if (_fd >= 0) close(_fd); -} - -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; - } - - 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; - - // 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; -} - -#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)), 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)), 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, std::error_code &ec) { -#if defined(_WIN32) - return _(fi_write(fd, &_afp, sizeof(_afp)),ec); -#else - return _(fi_write(fd, &_finder_info, sizeof(_finder_info)),ec); -#endif -} - -bool finder_info_helper::write(std::error_code &ec) { - ec.clear(); - return write(_fd, ec); -} - - -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) { - _prodos_file_type = ftype; - _prodos_aux_type = atype; - file_type_to_finder_info(_finder_info, ftype, atype); -} - - -void finder_info_helper::set_prodos_file_type(uint16_t ftype) { - set_prodos_file_type(ftype, _prodos_aux_type); -} - -bool finder_info_helper::is_text() const { - if (memcmp(_finder_info, "TEXT", 4) == 0) return true; - if (_prodos_file_type == 0x04) return true; - if (_prodos_file_type == 0xb0) return true; - - 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; - for (unsigned i = 0; i < 4; ++i) { - rv <<= 8; - rv |= _finder_info[i]; - } - return rv; -} - -uint32_t finder_info_helper::creator_type() const { - uint32_t rv = 0; - for (unsigned i = 4; i < 8; ++i) { - rv <<= 8; - rv |= _finder_info[i]; - } - return rv; -} - -void finder_info_helper::set_file_type(uint32_t x) { - _finder_info[0] = x >> 24; - _finder_info[1] = x >> 16; - _finder_info[2] = x >> 8; - _finder_info[3] = x >> 0; -} - - -void finder_info_helper::set_creator_type(uint32_t x) { - _finder_info[4] = x >> 24; - _finder_info[5] = x >> 16; - _finder_info[6] = x >> 8; - _finder_info[7] = x >> 0; -} diff --git a/finder_info_helper.h b/finder_info_helper.h deleted file mode 100644 index 45e8f47..0000000 --- a/finder_info_helper.h +++ /dev/null @@ -1,130 +0,0 @@ - -#include -#include - -#include - -#if defined(_WIN32) -#pragma pack(push, 2) -struct AFP_Info { - uint32_t magic; - uint32_t version; - uint32_t file_id; - uint32_t backup_date; - uint8_t finder_info[32]; - uint16_t prodos_file_type; - uint32_t prodos_aux_type; - uint8_t reserved[6]; -}; -#pragma pack(pop) - -#endif - -class finder_info_helper { - -public: - - enum open_mode { - read_only = 1, - write_only = 2, - read_write = 3, - }; - - finder_info_helper(); - ~finder_info_helper(); - - finder_info_helper(const finder_info_helper &) = delete; - finder_info_helper(finder_info_helper &&) = delete; - - finder_info_helper& operator=(const finder_info_helper &) = delete; - finder_info_helper& operator=(finder_info_helper &&) = delete; - - - const uint8_t *finder_info() const { - #if defined(_WIN32) - return _afp.finder_info; - #else - return _finder_info; - #endif - } - - uint8_t *finder_info() { - #if defined(_WIN32) - return _afp.finder_info; - #else - return _finder_info; - #endif - } - - - 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; - - uint16_t prodos_file_type() const { - #if defined(_WIN32) - return _afp.prodos_file_type; - #else - return _prodos_file_type; - #endif - } - - uint32_t prodos_aux_type() const { - #if defined(_WIN32) - return _afp.prodos_aux_type; - #else - return _prodos_aux_type; - #endif - } - - void set_prodos_file_type(uint16_t); - void set_prodos_file_type(uint16_t, uint32_t); - - void set_file_type(uint32_t); - void set_creator_type(uint32_t); - - bool is_text() const; - bool is_binary() const; - -private: - - bool write(int fd, std::error_code &ec); - bool read(int fd, std::error_code &ec); - - int _fd = -1; - - #if defined(_WIN32) - AFP_Info _afp; - #else - uint16_t _prodos_file_type = 0; - uint32_t _prodos_aux_type = 0; - uint8_t _finder_info[32] = {}; - #endif -}; diff --git a/set_file_type.cpp b/set_file_type.cpp index d9c4786..309b49a 100644 --- a/set_file_type.cpp +++ b/set_file_type.cpp @@ -1,20 +1,20 @@ #include #include - -#include "finder_info_helper.h" +#include +#include int set_file_type(const std::string &path, uint16_t file_type, uint32_t aux_type) { - finder_info_helper fi; - - bool ok; + afp::finder_info fi; 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(ec); - if (!ok) return -1; - return 0; + if (!fi.open(path, afp::finder_info::read_write, ec)) + return -1; + + fi.set_prodos_file_type(file_type, aux_type); + if (!fi.write(ec)) + return -1; + + return 0; }