diff --git a/toolbox/os_internal.cpp b/toolbox/os_internal.cpp index ce4bb97..af42ea5 100644 --- a/toolbox/os_internal.cpp +++ b/toolbox/os_internal.cpp @@ -7,6 +7,8 @@ #include #include +#include + namespace OS { namespace Internal { @@ -42,6 +44,151 @@ namespace OS { namespace Internal { } + + /* + + 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) + + */ + + uint16_t GetFinderInfo(const std::string &pathName, void *info, bool extended) + { + // todo -- move to separate function? used in multiple places. + uint8_t buffer[32]; + std::memset(buffer, 0, sizeof(buffer)); + int rv; + + rv = ::getxattr(pathName.c_str(), XATTR_FINDERINFO_NAME, buffer, 32, 0, 0); + + if (rv < 0) + { + switch (errno) + { + case ENOENT: + case EACCES: + return errno_to_oserr(errno); + } + } + + // override for source files. + // TODO -- only override if missing? + if (IsTextFile(pathName)) + { + std::memcpy(buffer, "TEXTMPS ", 8); + } + + + // convert pdos types... + if (::memcmp(buffer + 4, "pdos", 4) == 0) + { + // mpw expects 'xx ' where + // xx are the ascii-encode hex value of the file type. + // the hfs fst uses 'p' ftype8 auxtype16 + if (buffer[0] == 'p') + { + static char Hex[] = "0123456789ABCDEF"; + + uint8_t ftype = buffer[1]; + buffer[0] = Hex[ftype >> 4]; + buffer[1] = Hex[ftype & 0x0f]; + buffer[2] = ' '; + buffer[3] = ' '; + } + } + + if (extended) + std::memcpy(info, buffer, 32); + else + std::memcpy(info, buffer, 16); + return 0; + } + + unsigned tox(unsigned x) + { + if (x >= '0' && x <= '9') return x - '0'; + if (x >= 'a' && x <= 'f') return x - 'a' + 10; + if (x >= 'A' && x <= 'F') return x - 'A' + 10; + return 0; + } + + uint16_t SetFinderInfo(const std::string &pathName, void *info, bool extended) + { + uint8_t buffer[32]; + std::memset(buffer, 0, sizeof(buffer)); + int rv; + + if (!extended) + { + rv = ::getxattr(pathName.c_str(), XATTR_FINDERINFO_NAME, buffer, 32, 0, 0); + + if (rv < 0) + { + switch (errno) + { + case ENOENT: + case EACCES: + return errno_to_oserr(errno); + } + } + } + + if (extended) + std::memmove(buffer, info, 16); + else + std::memmove(buffer, info, 32); + + // convert pdos types. + if (::memcmp(buffer + 2, " pdos", 6) == 0) + { + unsigned a = buffer[0]; + unsigned b = buffer[1]; + + if (isxdigit(a) && isxdigit(b)) + { + buffer[0] = 'p'; + buffer[1] = (tox(a) << 4) | tox(b); + buffer[2] = 0; + buffer[3] = 0; + } + } + + rv = ::setxattr(pathName.c_str(), XATTR_FINDERINFO_NAME, buffer, 32, 0, 0); + if (rv < 0) return errno_to_oserr(errno); + + return 0; + } + + int32_t mac_seek(uint16_t refNum, uint16_t mode, int32_t offset) { off_t rv; diff --git a/toolbox/os_internal.h b/toolbox/os_internal.h index 639e7e0..6c97f88 100644 --- a/toolbox/os_internal.h +++ b/toolbox/os_internal.h @@ -8,8 +8,8 @@ namespace OS { namespace Internal { uint16_t errno_to_oserr(int xerrno); - uint16_t GetFinderInfo(const std::string &pathname, void *info); - uint16_t SetFinderInfo(const std::string &pathname, void *info); + uint16_t GetFinderInfo(const std::string &pathname, void *info, bool extended); + uint16_t SetFinderInfo(const std::string &pathname, void *info, bool extended); uint16_t GetFileType(const std::string &pathname, uint16_t *fileType, uint32_t *auxType);