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.
//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;

View File

@ -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<size_t> xattr_file::write(const void *in_buffer, size_t count) {
if (_readonly) return MacOS::wrPermErr;
std::vector<uint8_t> buffer;
ssize_t size;
size = read_rfork(buffer);
@ -140,6 +142,8 @@ namespace {
tool_return<void> xattr_file::set_eof(ssize_t new_eof) {
if (_readonly) return MacOS::wrPermErr;
if (new_eof < 0) return paramErr;
std::vector<uint8_t> buffer;
@ -159,11 +163,26 @@ namespace {
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);
if (fd < 0) return macos_error_from_errno();
return std::make_shared<file>(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);
}

View File

@ -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);
}

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) {
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);
}

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);
}