better create support for resource fork files.

This commit is contained in:
Kelvin Sherlock 2016-11-04 15:29:56 -04:00
parent 9d16456b80
commit 93bb259471
5 changed files with 83 additions and 22 deletions

View File

@ -366,8 +366,37 @@ namespace native {
// todo -- verify behavior on non-hfs volume. // todo -- verify behavior on non-hfs volume.
//if ((oflag & O_ACCMODE) & O_WRONLY) oflag |= O_CREAT; //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); 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); auto tmp = new fd_file(path_name, fd);
tmp->resource = true; tmp->resource = true;

View File

@ -47,7 +47,7 @@ namespace {
class xattr_file final : public file { class xattr_file final : public file {
public: 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(); ~xattr_file();
@ -65,7 +65,7 @@ namespace {
int _fd = -1; int _fd = -1;
off_t _displacement = 0; off_t _displacement = 0;
bool _readonly = false;
}; };
xattr_file::~xattr_file() { xattr_file::~xattr_file() {
@ -101,6 +101,8 @@ namespace {
tool_return<size_t> xattr_file::write(const void *in_buffer, size_t count) { tool_return<size_t> xattr_file::write(const void *in_buffer, size_t count) {
if (_readonly) return MacOS::wrPermErr;
std::vector<uint8_t> buffer; std::vector<uint8_t> buffer;
ssize_t size; ssize_t size;
size = read_rfork(buffer); size = read_rfork(buffer);
@ -140,6 +142,8 @@ namespace {
tool_return<void> xattr_file::set_eof(ssize_t new_eof) { tool_return<void> xattr_file::set_eof(ssize_t new_eof) {
if (_readonly) return MacOS::wrPermErr;
if (new_eof < 0) return paramErr; if (new_eof < 0) return paramErr;
std::vector<uint8_t> buffer; std::vector<uint8_t> buffer;
@ -159,11 +163,26 @@ namespace {
namespace native { namespace native {
tool_return<file_ptr> open_resource_fork(const std::string &path_name, int oflag) { tool_return<file_ptr> open_resource_fork(const std::string &path_name, int oflag) {
int fd = open(rname.c_str(), oflag); /* under HFS, every file has a resource fork.
if (fd < 0) return macos_error_from_errno(); * Therefore, create it if opening for O_RDWR or O_WRONLY
return std::make_shared<file>(fd); */
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);
} }

View File

@ -206,14 +206,35 @@ namespace native {
/* under HFS, every file has a resource fork. /* under HFS, every file has a resource fork.
* Therefore, create it if opening for O_RDWR or O_WRONLY * 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; int mode = oflag & O_ACCMODE;
if (mode == O_WRONLY || mode == O_RDWR) oflag |= O_CREAT; if (mode == O_WRONLY || mode == O_RDWR) oflag |= O_CREAT;
int fd = attropen(path_name.c_str(), XATTR_RESOURCEFORK_NAME, oflag, 0666); //int fd = attropen(path_name.c_str(), XATTR_RESOURCEFORK_NAME, oflag, 0666);
if (fd < 0) return macos_error_from_errno(); 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); auto tmp = new fd_file(path_name, fd);
tmp->resource = true; tmp->resource = true;
return file_ptr(tmp); return file_ptr(tmp);
} }

View File

@ -328,25 +328,17 @@ namespace native {
} }
tool_return<file_ptr> open_fork(const std::string &path_name, int fork, int oflag, int perm) { tool_return<file_ptr> open_fork(const std::string &path_name, int fork, int oflag) {
if (!fork) { 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(); if (fd < 0) return macos_error_from_errno();
return file_ptr(new fd_file(path_name, fd)); 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); return open_resource_fork(path_name, oflag);
} }

View File

@ -53,7 +53,7 @@ namespace native {
tool_return<file_ptr> open_fork(const std::string &path_name, int fork, int oflag, int perm = 0666); tool_return<file_ptr> open_fork(const std::string &path_name, int fork, int oflag);
tool_return<file_ptr> open_resource_fork(const std::string &path_name, int oflag); tool_return<file_ptr> open_resource_fork(const std::string &path_name, int oflag);
} }