From 5a88e793d24eb49f72a7f1217b52ca07c34a0b7c Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Wed, 9 Aug 2017 23:14:15 -0400 Subject: [PATCH] use afp for finder info / resource fork. --- Makefile | 18 +- afp | 1 + appledouble.cpp | 158 ++------- applesingle.cpp | 155 ++------- dot_clean.cpp | 95 ++---- finder_info_helper.cpp | 739 ----------------------------------------- finder_info_helper.h | 140 -------- xattr.c | 101 ------ xattr.h | 27 -- 9 files changed, 109 insertions(+), 1325 deletions(-) create mode 160000 afp delete mode 100644 finder_info_helper.cpp delete mode 100644 finder_info_helper.h delete mode 100644 xattr.c delete mode 100644 xattr.h diff --git a/Makefile b/Makefile index b107e28..87b30bf 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ LINK.o = $(LINK.cc) CXXFLAGS += -std=c++11 -g -Wall +CPPFLAGS += -I afp/include + # static link if using mingw32 or mingw64 to make redistribution easier. # also add mingw directory. ifeq ($(MSYSTEM),MINGW32) @@ -19,12 +21,18 @@ all : dot_clean applesingle appledouble .PHONY: clean clean : $(RM) *.o dot_clean applesingle appledouble + $(MAKE) -C afp clean +.PHONY: submodules +submodules : + $(MAKE) -C afp -dot_clean : dot_clean.o mapped_file.o finder_info_helper.o xattr.o +afp/libafp.a : submodules -applesingle : applesingle.o mapped_file.o finder_info_helper.o xattr.o -appledouble : appledouble.o mapped_file.o finder_info_helper.o xattr.o +dot_clean : dot_clean.o mapped_file.o afp/libafp.a + +applesingle : applesingle.o mapped_file.o afp/libafp.a +appledouble : appledouble.o mapped_file.o afp/libafp.a mapped_file.o : mapped_file.cpp mapped_file.h unique_resource.h @@ -32,7 +40,3 @@ dot_clean.o : dot_clean.cpp mapped_file.h applefile.h defer.h applesingle.o : applesingle.cpp mapped_file.h applefile.h defer.h appledouble.o : appledouble.cpp mapped_file.h applefile.h defer.h - -finder_info_helper.o: finder_info_helper.cpp finder_info_helper.h - -xattr.o : xattr.c xattr.h diff --git a/afp b/afp new file mode 160000 index 0000000..3d031fe --- /dev/null +++ b/afp @@ -0,0 +1 @@ +Subproject commit 3d031fe4513b0cf1453a60a283ff1204bf479220 diff --git a/appledouble.cpp b/appledouble.cpp index 9bef760..25ca0bd 100644 --- a/appledouble.cpp +++ b/appledouble.cpp @@ -23,8 +23,9 @@ #endif #include "mapped_file.h" -#include "xattr.h" -#include "finder_info_helper.h" + +#include +#include #include "applefile.h" @@ -34,25 +35,6 @@ #endif - -#if defined(__linux__) -#define XATTR_RESOURCEFORK_NAME "user.com.apple.ResourceFork" -#endif - - -#if defined (_WIN32) -#define XATTR_FINDERINFO_NAME "AFP_Resource" -#endif - -#ifndef XATTR_FINDERINFO_NAME -#define XATTR_FINDERINFO_NAME "com.apple.FinderInfo" -#endif - -#ifndef XATTR_RESOURCEFORK_NAME -#define XATTR_RESOURCEFORK_NAME "com.apple.ResourceFork" -#endif - - void usage() { fputs("Usage: appledouble [-hv] [-o outfile] file ...\n", stderr); exit(EX_USAGE); @@ -74,97 +56,6 @@ bool _v = false; int _rv = 0; -std::vector read_resource_fork(const std::string &path, std::error_code ec) { - std::vector rv; - - ec.clear(); - - #if defined(__sun__) || defined(_WIN32) - int fd; - struct stat st; - - #if defined(__sun__) - 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 | O_BINARY); - #endif - if (fd < 0) { - ec = std::error_code(errno, std::generic_category()); - return rv; - } - - if (fstat(fd, &st) < 0) { - ec = std::error_code(errno, std::generic_category()); - close(fd); - return rv; - } - - if (st.st_size == 0) { - close(fd); - return rv; - } - - for(;;) { - rv.resize(st.st_size); - ssize_t ok = read(fd, rv.data(), st.st_size); - if (ok < 0) { - if (errno == EINTR) continue; - ec = std::error_code(errno, std::generic_category()); - rv.clear(); - break; - } - rv.resize(ok); - break; - } - close(fd); - return rv; - #else - - int fd = open(path.c_str(), O_RDONLY | O_BINARY); - if (fd < 0) { - ec = std::error_code(errno, std::generic_category()); - return rv; - } - - for(;;) { - ssize_t size = size_xattr(fd, XATTR_RESOURCEFORK_NAME); - if (size < 0) { - if (errno == EINTR) continue; - if (errno == ENOATTR) { - rv.clear(); - break; - } - ec = std::error_code(errno, std::generic_category()); - close(fd); - return rv; - } - if (size == 0) break; - rv.resize(size); - - 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; - } - rv.resize(rsize); - break; - } - close(fd); - return rv; - - #endif -} - - /* check if a file is apple single or apple double format (or neither). */ uint32_t classify(const mapped_file &mf) { if (mf.size() < sizeof(ASHeader)) return 0; @@ -190,6 +81,7 @@ void one_file(const std::string &infile, const std::string &outfile) { mapped_file mf; ASHeader head; ASEntry e; + std::error_code ec; try { @@ -220,26 +112,38 @@ void one_file(const std::string &infile, const std::string &outfile) { int count = 0; - std::error_code ec; + afp::finder_info fi; + afp::resource_fork rf; + + size_t rfork_size = 0; + std::unique_ptr rfork_data; - finder_info_helper fi; bool fi_ok = fi.open(infile, ec); + bool rf_ok = rf.open(infile, afp::resource_fork::read_only, ec); - // ENOATTR is ok... but that's not an errc... - std::vector resource = read_resource_fork(infile, ec); + if (rf_ok) { + rfork_size = rf.size(ec); + if (rfork_size) { - if (ec) { - warnc(ec.value(), "%s resource fork\n", infile.c_str()); - return; + rfork_data.reset(new uint8_t[rfork_size]); + rfork_size = rf.read(rfork_data.get(), rfork_size, ec); + + if (ec) { + warnx("%s resource fork: %s", infile.c_str(), ec.message().c_str()); + return; + } + } + rf.close(); } + if (!rfork_size) rf_ok = false; - if (!fi_ok && resource.empty()) { + if (!fi_ok && !rf_ok) { warnx("%s: File is not extended.", infile.c_str()); return; } - if (resource.size()) count++; + if (rf_ok) count++; if (fi_ok) count++; @@ -263,26 +167,26 @@ void one_file(const std::string &infile, const std::string &outfile) { offset += 32; } // 2 - resource fork? - if (resource.size()) { + if (rf_ok) { e.entryID = htonl(AS_RESOURCE); e.entryOffset = htonl(offset); - e.entryLength = htonl(resource.size()); + e.entryLength = htonl(rfork_size); write(fd, &e, sizeof(e)); - offset += resource.size(); + offset += rfork_size; } // now write it.. // 1 - finder info if (fi_ok) { - write(fd, fi.finder_info(), 32); + write(fd, fi.data(), 32); } // 2 - resource fork? - if (resource.size()) { - write(fd, resource.data(), resource.size()); + if (rf_ok) { + write(fd, rfork_data.get(), rfork_size); } close(fd); } diff --git a/applesingle.cpp b/applesingle.cpp index 77f187a..9dcd1e2 100644 --- a/applesingle.cpp +++ b/applesingle.cpp @@ -23,8 +23,9 @@ #endif #include "mapped_file.h" -#include "xattr.h" -#include "finder_info_helper.h" + +#include +#include #include "applefile.h" @@ -32,22 +33,6 @@ #define O_BINARY 0 #endif -#if defined(__linux__) -#define XATTR_RESOURCEFORK_NAME "user.com.apple.ResourceFork" -#endif - - -#if defined (_WIN32) -#define XATTR_FINDERINFO_NAME "AFP_Resource" -#endif - -#ifndef XATTR_FINDERINFO_NAME -#define XATTR_FINDERINFO_NAME "com.apple.FinderInfo" -#endif - -#ifndef XATTR_RESOURCEFORK_NAME -#define XATTR_RESOURCEFORK_NAME "com.apple.ResourceFork" -#endif void usage() { @@ -71,96 +56,6 @@ bool _v = false; int _rv = 0; -std::vector read_resource_fork(const std::string &path, std::error_code ec) { - std::vector rv; - - ec.clear(); - - #if defined(__sun__) || defined(_WIN32) - int fd; - struct stat st; - - #if defined(__sun__) - 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 | O_BINARY); - #endif - if (fd < 0) { - ec = std::error_code(errno, std::generic_category()); - return rv; - } - - if (fstat(fd, &st) < 0) { - ec = std::error_code(errno, std::generic_category()); - close(fd); - return rv; - } - - if (st.st_size == 0) { - close(fd); - return rv; - } - - for(;;) { - rv.resize(st.st_size); - ssize_t ok = read(fd, rv.data(), st.st_size); - if (ok < 0) { - if (errno == EINTR) continue; - ec = std::error_code(errno, std::generic_category()); - rv.clear(); - break; - } - rv.resize(ok); - break; - } - close(fd); - return rv; - #else - - int fd = open(path.c_str(), O_RDONLY | O_BINARY); - if (fd < 0) { - ec = std::error_code(errno, std::generic_category()); - return rv; - } - - for(;;) { - ssize_t size = size_xattr(fd, XATTR_RESOURCEFORK_NAME); - if (size < 0) { - if (errno == EINTR) continue; - if (errno == ENOATTR) { - rv.clear(); - break; - } - ec = std::error_code(errno, std::generic_category()); - close(fd); - return rv; - } - if (size == 0) break; - rv.resize(size); - - 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; - } - rv.resize(rsize); - break; - } - close(fd); - return rv; - - #endif -} - /* check if a file is apple single or apple double format (or neither). */ uint32_t classify(const mapped_file &mf) { @@ -219,25 +114,39 @@ void one_file(const std::string &infile, const std::string &outfile) { std::error_code ec; - finder_info_helper fi; + afp::finder_info fi; + afp::resource_fork rf; + + size_t rfork_size = 0; + std::unique_ptr rfork_data; bool fi_ok = fi.open(infile, ec); + bool rf_ok = rf.open(infile, afp::resource_fork::read_only, ec); - // ENOATTR is ok... but that's not an errc... - std::vector resource = read_resource_fork(infile, ec); + if (rf_ok) { + rfork_size = rf.size(ec); + if (rfork_size) { - if (ec) { - warnc(ec.value(), "%s resource fork\n", infile.c_str()); - return; + rfork_data.reset(new uint8_t[rfork_size]); + rfork_size = rf.read(rfork_data.get(), rfork_size, ec); + + if (ec) { + warnx("%s resource fork: %s", infile.c_str(), ec.message().c_str()); + return; + } + } + rf.close(); } + if (!rfork_size) rf_ok = false; - if (!fi_ok && resource.empty()) { + + if (!fi_ok && !rf_ok) { warnx("%s: File is not extended.", infile.c_str()); return; } - if (resource.size()) count++; + if (rf_ok) count++; if (fi_ok) count++; @@ -288,15 +197,15 @@ void one_file(const std::string &infile, const std::string &outfile) { offset += mf.size(); - // 5 - resource fork? - if (resource.size()) { + // 5 - resource fork + if (rf_ok) { e.entryID = htonl(AS_RESOURCE); e.entryOffset = htonl(offset); - e.entryLength = htonl(resource.size()); + e.entryLength = htonl(rfork_size); write(fd, &e, sizeof(e)); - offset += resource.size(); + offset += rfork_size; } // now write it.. @@ -308,15 +217,15 @@ void one_file(const std::string &infile, const std::string &outfile) { // 3 - finder info if (fi_ok) { - write(fd, fi.finder_info(), 32); + write(fd, fi.data(), 32); } // 4 - data fork write(fd, mf.data(), mf.size()); // 5 - resource fork? - if (resource.size()) { - write(fd, resource.data(), resource.size()); + if (rf_ok) { + write(fd, rfork_data.get(), rfork_size); } close(fd); } diff --git a/dot_clean.cpp b/dot_clean.cpp index 5f587d9..1a9457e 100644 --- a/dot_clean.cpp +++ b/dot_clean.cpp @@ -15,9 +15,9 @@ #include #include + #ifdef _WIN32 #include "win.h" -#define XATTR_RESOURCEFORK_NAME "AFP_Resource" #else #include @@ -30,25 +30,13 @@ #include #include -#ifdef __linux__ -#include -#define XATTR_RESOURCEFORK_NAME "user.com.apple.ResourceFork" -#endif - -#ifdef __APPLE__ -#include -#endif - -#ifndef XATTR_RESOURCEFORK_NAME -#define XATTR_RESOURCEFORK_NAME "com.apple.ResourceFork" -#endif - +#include +#include #include "applefile.h" #include "mapped_file.h" #include "defer.h" -#include "finder_info_helper.h" #ifndef O_BINARY #define O_BINARY 0 @@ -93,47 +81,16 @@ void throw_errno(const std::string &what) { throw std::system_error(errno, std::generic_category(), what); } - -void write_resource_fork(const std::string &parent_path, int parent_fd, void *data, size_t size) { - - #ifdef __sun__ - int rfd = openat(parent_fd, XATTR_RESOURCEFORK_NAME, O_XATTR | O_CREAT | O_TRUNC | O_WRONLY, 0666); - if (rfd < 0) throw_errno(XATTR_RESOURCEFORK_NAME); - defer close_fd([rfd](){ close(rfd); }); - - if (!size) return; - - ssize_t ok = write(rfd, data, size); - if (ok < 0) throw_errno(XATTR_RESOURCEFORK_NAME); - #endif - - #ifdef _WIN32 - std::string tmp = parent_path + ":" XATTR_RESOURCEFORK_NAME; - int rfd = open(tmp.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); - if (rfd < 0) throw_errno(XATTR_RESOURCEFORK_NAME); - defer close_fd([rfd](){ close(rfd); }); - - if (!size) return; - - int ok = write(rfd, data, size); - if (ok < 0) throw_errno(XATTR_RESOURCEFORK_NAME); - #endif - - #ifdef __linux__ - int ok = fsetxattr(parent_fd, XATTR_RESOURCEFORK_NAME, data, size, 0); - if (ok < 0) throw_errno(XATTR_RESOURCEFORK_NAME); - #endif - - #ifdef __APPLE__ - int ok; - ok = fremovexattr(parent_fd, XATTR_RESOURCEFORK_NAME, 0); - if (ok < 0) throw_errno(XATTR_RESOURCEFORK_NAME); - if (!size) return; - ok = fsetxattr(parent_fd, XATTR_RESOURCEFORK_NAME, data, size, 0, XATTR_CREATE); - if (ok < 0) throw_errno(XATTR_RESOURCEFORK_NAME); - #endif +void throw_ec(const std::error_code &ec) { + throw std::system_error(ec); } +void throw_ec(const std::error_code &ec, const std::string &what) { + throw std::system_error(ec, what); +} + + + /* * resource is straight data (cadius, nulib2, etc) */ @@ -170,15 +127,25 @@ void one_flat_file(const std::string &data, const std::string rsrc) noexcept try defer close_fd([fd]{close(fd); }); if (stat(rsrc.c_str(), &rsrc_st) < 0) throw_errno("stat"); + + + + std::error_code ec; + if (rsrc_st.st_size == 0) { // truncate any existing resource fork. - write_resource_fork(data, fd, nullptr, 0); + if (!afp::resource_fork::remove(data, ec)) + throw_ec(ec, "resource_fork::remove()"); + if (!_p) unlink_list.push_back(rsrc); return; } mapped_file mf(rsrc, mapped_file::readonly, rsrc_st.st_size); - write_resource_fork(data, fd, mf.data(), mf.size()); + + afp::resource_fork::write(data, mf.data(), mf.size(), ec); + if (ec) throw_ec(ec, "resource_fork::write()"); + if (!_p) unlink_list.push_back(rsrc); } catch (const std::exception &ex) { _rv = 1; @@ -266,12 +233,12 @@ void one_file(const std::string &data, const std::string &rsrc) noexcept try { }); - finder_info_helper fi; + afp::finder_info fi; std::error_code ec; bool update_fi = false; bool fi_ok = false; - fi_ok = fi.open(data, finder_info_helper::read_write, ec); + fi_ok = fi.open(data, afp::finder_info::read_write, ec); std::for_each(begin, end, [&](const ASEntry &tmp){ @@ -294,7 +261,13 @@ void one_file(const std::string &data, const std::string &rsrc) noexcept try { } #endif case AS_RESOURCE: { - write_resource_fork(data, fd, mf.data()+ e.entryOffset, e.entryLength); + if (e.entryLength == 0) { + if (!afp::resource_fork::remove(data, ec)) + throw_ec(ec, "resource_fork::remove()"); + } else { + afp::resource_fork::write(data, mf.data()+ e.entryOffset, e.entryLength, ec); + if (ec) throw_ec(ec, "resource_fork::write()"); + } break; } @@ -304,7 +277,7 @@ void one_file(const std::string &data, const std::string &rsrc) noexcept try { fputs("Warning: Invalid Finder Info size.\n", stderr); break; } - memcpy(fi.finder_info(), mf.data() + e.entryOffset, 32); + memcpy(fi.data(), mf.data() + e.entryOffset, 32); update_fi = true; break; } @@ -322,7 +295,7 @@ void one_file(const std::string &data, const std::string &rsrc) noexcept try { if (update_fi) { if (!fi.write(ec)) { - throw_errno("com.apple.FinderInfo"); + throw_ec(ec, "com.apple.FinderInfo"); } } diff --git a/finder_info_helper.cpp b/finder_info_helper.cpp deleted file mode 100644 index bfa9125..0000000 --- a/finder_info_helper.cpp +++ /dev/null @@ -1,739 +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) -#include -#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 - - - 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 - HANDLE CreateFileX(const std::string &s, Args... args) { - return CreateFileA(s.c_str(), std::forward(args)...); - } - - template - HANDLE CreateFileX(const std::wstring &s, Args... args) { - return CreateFileW(s.c_str(), std::forward(args)...); - } - - void fi_close(void *fd) { - CloseHandle(fd); - } - - void *fi_open(const std::string &path, int perm, std::error_code &ec) { - - ec.clear(); - - std::string s(path); - s.append(":" 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; - } - - 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, std::error_code &ec) { - #if defined(__sun__) - 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, std::error_code &ec) { - #if defined(__sun__) - lseek(fd, 0, SEEK_SET); - return read(fd, data, length); - #else - return read_xattr(fd, XATTR_FINDERINFO_NAME, data, length); - #endif - } - -#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 -} - -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, 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; -} -#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(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 - -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); - return true; -} - -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(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(); - 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; - _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 a727eea..0000000 --- a/finder_info_helper.h +++ /dev/null @@ -1,140 +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, 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; - - 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: - - void close(); - -#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] = {}; - #endif -}; diff --git a/xattr.c b/xattr.c deleted file mode 100644 index 078ac88..0000000 --- a/xattr.c +++ /dev/null @@ -1,101 +0,0 @@ - -#include "xattr.h" - -#if defined(__APPLE__) -#include -#endif - -#if defined(__linux__) -#include -#endif - -#if defined(__FreeBSD__) -#include -#include -#endif - -#if defined(_AIX) -#include -#endif - - -/* - * 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 diff --git a/xattr.h b/xattr.h deleted file mode 100644 index 28bc498..0000000 --- a/xattr.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef xattr_h -#define xattr_h - -#include -#include - -#include - -#ifndef ENOATTR -#define ENOATTR ENODATA -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -ssize_t size_xattr(int fd, const char *xattr); -ssize_t read_xattr(int fd, const char *xattr, void *buffer, size_t size); -ssize_t write_xattr(int fd, const char *xattr, const void *buffer, size_t size); -int remove_xattr(int fd, const char *xattr); - - -#ifdef __cplusplus -} -#endif - -#endif