diff --git a/native/Darwin.cpp b/native/Darwin.cpp index ea07797..90ff141 100644 --- a/native/Darwin.cpp +++ b/native/Darwin.cpp @@ -366,8 +366,37 @@ namespace native { // todo -- verify behavior on non-hfs volume. //if ((oflag & O_ACCMODE) & O_WRONLY) oflag |= O_CREAT; + // under apfs, resource fork needs to be specifically created. + // (if 0-length, it doesn't actually exist...) + + // apfs -- zero-length resource fork + + int parent; + if (oflag & O_CREAT) { + int excl = oflag & O_EXCL; + parent = open(path_name.c_str(), O_RDONLY | O_CREAT | excl, 0666); + } else { + parent = open(path_name.c_str(), O_RDONLY); + } + + if (parent < 0) return macos_error_from_errno(); + close(parent); + + oflag &= ~(O_CREAT | O_EXCL); + int mode = oflag & O_ACCMODE; + if (mode == O_WRONLY || mode == O_RDWR) oflag |= O_CREAT; + int fd = open(rname.c_str(), oflag, 0666); - if (fd < 0) return macos_error_from_errno(); + if (fd < 0) { + auto e = macos_error_from_errno(); + + if (errno == ENOENT && mode == O_RDONLY) { + auto tmp = new empty_file(path_name); + tmp->resource = true; + return file_ptr(tmp); + } + return e; + } auto tmp = new fd_file(path_name, fd); tmp->resource = true; diff --git a/native/Linux.cpp b/native/Linux.cpp index 39e1286..fae3768 100644 --- a/native/Linux.cpp +++ b/native/Linux.cpp @@ -47,7 +47,7 @@ namespace { class xattr_file final : public file { public: - xattr_file(int fd): _fd(fd); + xattr_file(const std::string &path, int fd, bool readonly): file(path), _fd(fd), _readonly(readonly); ~xattr_file(); @@ -65,7 +65,7 @@ namespace { int _fd = -1; off_t _displacement = 0; - + bool _readonly = false; }; xattr_file::~xattr_file() { @@ -101,6 +101,8 @@ namespace { tool_return xattr_file::write(const void *in_buffer, size_t count) { + if (_readonly) return MacOS::wrPermErr; + std::vector buffer; ssize_t size; size = read_rfork(buffer); @@ -140,6 +142,8 @@ namespace { tool_return xattr_file::set_eof(ssize_t new_eof) { + if (_readonly) return MacOS::wrPermErr; + if (new_eof < 0) return paramErr; std::vector buffer; @@ -159,11 +163,26 @@ namespace { namespace native { - tool_return open_resource_fork(const std::string &path_name, int oflag) { + tool_return open_resource_fork(const std::string &path_name, int oflag) { - int fd = open(rname.c_str(), oflag); - if (fd < 0) return macos_error_from_errno(); - return std::make_shared(fd); + /* under HFS, every file has a resource fork. + * Therefore, create it if opening for O_RDWR or O_WRONLY + */ + + int parent; + if (oflag & O_CREAT) { + int excl = oflag & O_EXCL; + parent = open(path_name.c_str(), O_RDONLY | O_CREAT | excl, 0666); + } else { + parent = open(path_name.c_str(), O_RDONLY); + } + if (parent < 0) return macos_error_from_errno(); + + int mode = oflag & O_ACCMODE; + + auto tmp = new xattr_file(path_name, parent, oflags == O_RDONLY); + tmp->resource = true; + return file_ptr(tmp); } diff --git a/native/SunOS.cpp b/native/SunOS.cpp index ebefcf9..d611e8e 100644 --- a/native/SunOS.cpp +++ b/native/SunOS.cpp @@ -206,14 +206,35 @@ namespace native { /* under HFS, every file has a resource fork. * Therefore, create it if opening for O_RDWR or O_WRONLY */ + + int parent; + if (oflag & O_CREAT) { + int excl = oflag & O_EXCL; + parent = open(path_name.c_str(), O_RDONLY | O_CREAT | excl, 0666); + } else { + parent = open(path_name.c_str(), O_RDONLY); + } + if (parent < 0) return macos_error_from_errno(); + + oflag &= ~(O_CREAT | O_EXCL); int mode = oflag & O_ACCMODE; if (mode == O_WRONLY || mode == O_RDWR) oflag |= O_CREAT; - int fd = attropen(path_name.c_str(), XATTR_RESOURCEFORK_NAME, oflag, 0666); - if (fd < 0) return macos_error_from_errno(); + //int fd = attropen(path_name.c_str(), XATTR_RESOURCEFORK_NAME, oflag, 0666); + int fd = openat(parent, XATTR_RESOURCEFORK_NAME, oflag | O_XATTR, 0666); + if (fd < 0) { + int e = macos_error_from_errno(); + close(parent); + if (e == ENOENT && mode == O_RDONLY) { + auto tmp = new empty_file(path_name); + tmp->resource = true; + return file_ptr(tmp); + } + return e; + } + close(parent); auto tmp = new fd_file(path_name, fd); tmp->resource = true; - return file_ptr(tmp); } diff --git a/native/native.cpp b/native/native.cpp index 2ff4e85..75808a1 100644 --- a/native/native.cpp +++ b/native/native.cpp @@ -328,25 +328,17 @@ namespace native { } - tool_return open_fork(const std::string &path_name, int fork, int oflag, int perm) { + tool_return open_fork(const std::string &path_name, int fork, int oflag) { if (!fork) { - int fd = ::open(path_name.c_str(), oflag, perm); + int fd = ::open(path_name.c_str(), oflag, 0666); if (fd < 0) return macos_error_from_errno(); return file_ptr(new fd_file(path_name, fd)); } - // if O_CREAT or E_EXCL, may need to create the file - - int tmp = oflag & (O_CREAT | O_EXCL); - if (tmp) { - int fd = ::open(path_name.c_str(), (oflag & O_ACCMODE) | tmp, perm); - if (fd < 0) return macos_error_from_errno(); - ::close(fd); - oflag &= ~ (O_CREAT | O_EXCL); - } return open_resource_fork(path_name, oflag); + } diff --git a/native/native.h b/native/native.h index 2ed2892..a31b226 100644 --- a/native/native.h +++ b/native/native.h @@ -53,7 +53,7 @@ namespace native { - tool_return open_fork(const std::string &path_name, int fork, int oflag, int perm = 0666); + tool_return open_fork(const std::string &path_name, int fork, int oflag); tool_return open_resource_fork(const std::string &path_name, int oflag); }